ewsgui.psm1

$script:ModuleRoot = $PSScriptRoot
$script:ModuleVersion = (Import-PowerShellDataFile -Path "$($script:ModuleRoot)\EWSGui.psd1").ModuleVersion

# Detect whether at some level dotsourcing was enforced
$script:doDotSource = Get-PSFConfigValue -FullName EWSGui.Import.DoDotSource -Fallback $false
if ($EWSGui_dotsourcemodule) { $script:doDotSource = $true }

<#
Note on Resolve-Path:
All paths are sent through Resolve-Path/Resolve-PSFPath in order to convert them to the correct path separator.
This allows ignoring path separators throughout the import sequence, which could otherwise cause trouble depending on OS.
Resolve-Path can only be used for paths that already exist, Resolve-PSFPath can accept that the last leaf my not exist.
This is important when testing for paths.
#>


# Detect whether at some level loading individual module files, rather than the compiled module was enforced
$importIndividualFiles = Get-PSFConfigValue -FullName EWSGui.Import.IndividualFiles -Fallback $false
if ($EWSGui_importIndividualFiles) { $importIndividualFiles = $true }
if (Test-Path (Resolve-PSFPath -Path "$($script:ModuleRoot)\..\.git" -SingleItem -NewChild)) { $importIndividualFiles = $true }
if ("<was compiled>" -eq '<was not compiled>') { $importIndividualFiles = $true }
    
function Import-ModuleFile
{
    <#
        .SYNOPSIS
            Loads files into the module on module import.
         
        .DESCRIPTION
            This helper function is used during module initialization.
            It should always be dotsourced itself, in order to proper function.
             
            This provides a central location to react to files being imported, if later desired
         
        .PARAMETER Path
            The path to the file to load
         
        .EXAMPLE
            PS C:\> . Import-ModuleFile -File $function.FullName
     
            Imports the file stored in $function according to import policy
    #>

    [CmdletBinding()]
    Param (
        [string]
        $Path
    )
    
    $resolvedPath = $ExecutionContext.SessionState.Path.GetResolvedPSPathFromPSPath($Path).ProviderPath
    if ($doDotSource) { . $resolvedPath }
    else { $ExecutionContext.InvokeCommand.InvokeScript($false, ([scriptblock]::Create([io.file]::ReadAllText($resolvedPath))), $null, $null) }
}

#region Load individual files
if ($importIndividualFiles)
{
    # Execute Preimport actions
    foreach ($path in (& "$ModuleRoot\internal\scripts\preimport.ps1")) {
        . Import-ModuleFile -Path $path
    }
    
    # Import all internal functions
    foreach ($function in (Get-ChildItem "$ModuleRoot\internal\functions" -Filter "*.ps1" -Recurse -ErrorAction Ignore))
    {
        . Import-ModuleFile -Path $function.FullName
    }
    
    # Import all public functions
    foreach ($function in (Get-ChildItem "$ModuleRoot\functions" -Filter "*.ps1" -Recurse -ErrorAction Ignore))
    {
        . Import-ModuleFile -Path $function.FullName
    }
    
    # Execute Postimport actions
    foreach ($path in (& "$ModuleRoot\internal\scripts\postimport.ps1")) {
        . Import-ModuleFile -Path $path
    }
    
    # End it here, do not load compiled code below
    return
}
#endregion Load individual files

#region Load compiled code
<#
This file loads the strings documents from the respective language folders.
This allows localizing messages and errors.
Load psd1 language files for each language you wish to support.
Partial translations are acceptable - when missing a current language message,
it will fallback to English or another available language.
#>

Import-PSFLocalizedString -Path "$($script:ModuleRoot)\en-us\*.psd1" -Module 'EWSGui' -Language 'en-US'

Function Connect-EWSService {
    <#
    .SYNOPSIS
    Function to Create service object and authenticate the user.
     
    .DESCRIPTION
    This function will create the service object.
    Will opt to the user to select connection either to On-premises or Exchange Online.
    Will use basic auth to connect to on-premises. Endpoint will be discovered using Autodiscover.
    Will use modern auth to connect to Exchange Online. Endpoint is hard-coded to EXO EWS URL.
     
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
 
    .EXAMPLE
    PS C:\> Connect-EWSService
    Creates service object and authenticate the user.
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidGlobalVars", "")]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "")]
    [Cmdletbinding()]
    param(
        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    # Choosing if connection is to Office 365 or an Exchange on-premises
    $PremiseForm.Controls.Add($radiobutton1)
    $PremiseForm.Controls.Add($radiobutton2)
    $PremiseForm.Controls.Add($radiobutton3)
    $PremiseForm.ClientSize = New-Object System.Drawing.Size(250, 160)
    $PremiseForm.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $PremiseForm.Name = "form1"
    $PremiseForm.Text = "Choose your Exchange version"
    #
    # radiobutton1
    #
    $radiobutton1.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton1.Location = New-Object System.Drawing.Point(20, 20)
    $radiobutton1.Size = New-Object System.Drawing.Size(150, 25)
    $radiobutton1.TabStop = $True
    $radiobutton1.Text = "Exchange 2010"
    $radioButton1.Checked = $true
    $radiobutton1.UseVisualStyleBackColor = $True
    #
    # radiobutton2
    #
    $radiobutton2.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton2.Location = New-Object System.Drawing.Point(20, 55)
    $radiobutton2.Size = New-Object System.Drawing.Size(150, 30)
    $radiobutton2.TabStop = $True
    $radiobutton2.Text = "Exchange 2013/2016/2019"
    $radioButton2.Checked = $false
    $radiobutton2.UseVisualStyleBackColor = $True
    #
    # radiobutton3
    #
    $radiobutton3.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton3.Location = New-Object System.Drawing.Point(20, 95)
    $radiobutton3.Size = New-Object System.Drawing.Size(150, 25)
    $radiobutton3.TabStop = $True
    $radiobutton3.Text = "Office365"
    $radiobutton3.Checked = $false
    $radiobutton3.UseVisualStyleBackColor = $True

    #"Go" button
    $buttonGo.DataBindings.DefaultDataSourceUpdateMode = 0
    $buttonGo.ForeColor = [System.Drawing.Color]::FromArgb(255, 0, 0, 0)
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 170
    $System_Drawing_Point.Y = 20
    $buttonGo.Location = $System_Drawing_Point
    $buttonGo.Name = "Go"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 25
    $System_Drawing_Size.Width = 50
    $buttonGo.Size = $System_Drawing_Size
    $buttonGo.Text = "Go"
    $buttonGo.UseVisualStyleBackColor = $True
    $buttonGo.add_Click( {
            if ($radiobutton1.Checked) { $Global:option = "Exchange2010_SP2" }
            elseif ($radiobutton2.Checked) { $Global:option = "Exchange2013_SP1" }
            elseif ($radiobutton3.Checked) { $Global:option = "Exchange2013_SP1" }
            $PremiseForm.Hide()
        })
    $PremiseForm.Controls.Add($buttonGo)

    #"Exit" button
    $buttonExit.DataBindings.DefaultDataSourceUpdateMode = 0
    $buttonExit.ForeColor = [System.Drawing.Color]::FromArgb(255, 0, 0, 0)
    $System_Drawing_Point = New-Object System.Drawing.Point
    $System_Drawing_Point.X = 170
    $System_Drawing_Point.Y = 50
    $buttonExit.Location = $System_Drawing_Point
    $buttonExit.Name = "Exit"
    $System_Drawing_Size = New-Object System.Drawing.Size
    $System_Drawing_Size.Height = 25
    $System_Drawing_Size.Width = 50
    $buttonExit.Size = $System_Drawing_Size
    $buttonExit.Text = "Exit"
    $buttonExit.UseVisualStyleBackColor = $True
    $buttonExit.add_Click( { $PremiseForm.Close() ; $buttonExit.Dispose() })
    $PremiseForm.Controls.Add($buttonExit)

    #Show Form
    $PremiseForm.Add_Shown( { $PremiseForm.Activate() })
    $PremiseForm.ShowDialog() | Out-Null
    #exit if 'Exit' button is pushed
    if ($buttonExit.IsDisposed) { return }

    #creating service object
    Add-Type -Path $ModuleRoot\Bin\Microsoft.IdentityModel.Abstractions.dll
    Install-Module Microsoft.Identity.Client -Scope CurrentUser -Force -WarningAction SilentlyContinue
    Install-Module msal.ps -Scope CurrentUser -Force -WarningAction SilentlyContinue

    $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::$option
    $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)
    $service.ReturnClientRequestId = $true
    $service.UserAgent = "EwsGuiApp/2.0.21"

    if ($radiobutton3.Checked) {
        $Token = Get-EWSToken -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret
        $exchangeCredentials = New-Object Microsoft.Exchange.WebServices.Data.OAuthCredentials($Token.AccessToken)
        $Global:email = $Token.Account.Username
        $service.Url = New-Object Uri("https://outlook.office365.com/ews/exchange.asmx")
    }
    else {
        $psCred = Get-Credential -Message "Type your credentials or Administrator credentials"
        $Global:email = $psCred.UserName
        $exchangeCredentials = New-Object System.Net.NetworkCredential($psCred.UserName.ToString(), $psCred.GetNetworkCredential().password.ToString())
        # setting Autodiscover endpoint
        $service.EnableScpLookup = $True
        $service.AutodiscoverUrl($email, { $true })
    }
    $Service.Credentials = $exchangeCredentials

    return $service
}

function Get-EWSToken {
    <#
    .SYNOPSIS
    Function to fetch an authentication AccessToken, or a RefreshToken.
     
    .DESCRIPTION
    Function to fetch an authentication AccessToken, or a RefreshToken.
     
    .PARAMETER Refresh
    Use this optional parameter to request a Refresh Token.
 
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
     
    .EXAMPLE
    PS C:\> Get-EWSToken -ClientID "1234" -TenantID "abcd" -ClientSecret "a1b2c3d4"
 
    The function gets an authentication token based on the parameters passed.
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidGlobalVars", "")]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")]
    [CmdletBinding()]
    param (
        [Switch] $Refresh = $false,

        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    
    begin {
        
    }
    
    process {
        # creating time watcher or restarting if already passed 50 minutes since launch
        if ( $global:stopWatch.IsRunning -eq $true ) {
            $global:stopWatch.Restart()
        }
        else {
            $global:stopWatch = [System.Diagnostics.Stopwatch]::StartNew()
        }
        
        #Getting oauth credentials
        if ( $Refresh ) {
            Write-PSFMessage -Level Important -Message "Obtaining resfresh token to continue."
        }
        #region Connecting using Oauth with Application permissions with passed parameters
        if ( -not[String]::IsNullOrEmpty($ClientID) -or -not[String]::IsNullOrEmpty($TenantID) -or -not[String]::IsNullOrEmpty($ClientSecret) ) {
            Write-PSFMessage -Level Important -Message "Connecting using Oauth with Application permissions with passed parameters"
            $cid = $ClientID
            $tid = $TenantID
            $cs = ConvertTo-SecureString -String $clientSecret -AsPlainText -Force

            $scopes = New-Object System.Collections.Generic.List[string]
            $scopes.Add("https://outlook.office365.com/.default")
            try {
                $token = Get-MsalToken -ClientId $cid -TenantId $tid -ClientSecret $cs -Scopes $scopes -ForceRefresh:$Refresh -ErrorAction Stop
            }
            catch {
                Write-PSFMessage -Level Error -Message "Something failed to get authentication token." -ErrorRecord $_
            }
            Write-PSFMessage -Level Important -Message "Connected using Application permissions with passed ClientID, TenantID and ClientSecret"
        }
        #endregion
        #region Connecting using Oauth with Application permissions with saved values in the module
        elseif (
            $null -ne (Get-PSFConfig -Module EwsGui -Name ClientID).value -and `
                $null -ne (Get-PSFConfig -Module EwsGui -Name TenantID).value -and `
                $null -ne (Get-PSFConfig -Module EwsGui -Name ClientSecret).value
        ) {
            Write-PSFMessage -Level Important -Message "Connecting using Oauth with Application permissions with saved values in the module"
            $cid = (Get-PSFConfig -Module EwsGui -Name ClientID).value
            $tid = (Get-PSFConfig -Module EwsGui -Name TenantID).value
            $cs = ConvertTo-SecureString -String (Get-PSFConfig -Module EwsGui -Name ClientSecret).value -AsPlainText -Force

            $scopes = New-Object System.Collections.Generic.List[string]
            $scopes.Add("https://outlook.office365.com/.default")
            try {
                $token = Get-MsalToken -ClientId $cid -TenantId $tid -ClientSecret $cs -Scopes $scopes -ForceRefresh:$Refresh -ErrorAction Stop
            }
            catch {
                Write-PSFMessage -Level Error -Message "Something failed to get authentication token." -ErrorRecord $_
            }
            Write-PSFMessage -Level Important -Message "Connected using Application permissions with registered ClientID, TenantID and ClientSecret embedded to the module."
        }
        #endregion
        #region Connecting using Oauth with delegated permissions
        else {
            Write-PSFMessage -Level Important -Message "Connecting using Oauth with delegated permissions"
            $scopes = New-Object System.Collections.Generic.List[string]
            $scopes.Add("https://outlook.office365.com/.default")
            try {
                $token = Get-MsalToken -ClientId "8799ab60-ace5-4bda-b31f-621c9f6668db" -RedirectUri "http://localhost/code" -Scopes $scopes -UseEmbeddedWebView -ForceRefresh:$Refresh -ErrorAction Stop
            }
            catch {
                if ( $_.Exception.toString().StartsWith("System.Threading.ThreadStateException: ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2'")) {
                    Write-PSFMessage -Level Error -Message "Known issue occurred. There is work in progress to fix authentication flow. More info at: https://github.com/agallego-css/ewsgui/issues/28"
                    Write-PSFMessage -Level Error -Message "Failed to obtain authentication token. Exiting script. Please rerun the script again and it should work."
                }
                else {
                    Write-PSFMessage -Level Error -Message "Something failed to get authentication token." -ErrorRecord $_
                }
                break
            }
            Write-PSFMessage -Level Important -Message "Connected using Delegated permissions with: $($token.Account.Username)"
        }
        #endregion
    }
    
    end {
        return $token
    }
}

Function Method10 {
    <#
    .SYNOPSIS
    Method to get user's Inbox Rules.
     
    .DESCRIPTION
    Method to get user's Inbox Rules.
     
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
     
    .EXAMPLE
    PS C:\> Method10
    Method to get user's Inbox Rules.
 
    #>

    [CmdletBinding()]
    param(
        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    $statusBarLabel.Text = "Running..."

    Test-StopWatch -Service $service -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret

    $txtBoxResults.Text = "This method is still under construction."
    $dgResults.Visible = $False
    $txtBoxResults.Visible = $True
    $PremiseForm.refresh()
    $statusBarLabel.text = "Ready..."
    
    <#
    $rules = $service.GetInboxRules()
    $array = New-Object System.Collections.ArrayList
    foreach ( $rule in $rules )
    {
        $output = $rule | select DisplayName, Conditions, Actions, Exceptions
        $array.Add($output)
    }
    $dgResults.datasource = $array
    $dgResults.AutoResizeColumns()
    $dgResults.Visible = $True
    $txtBoxResults.Visible = $False
    $PremiseForm.refresh()
    $statusBarLabel.text = "Ready..."
    Write-PSFMessage -Level Host -Message "Task finished succesfully" -FunctionName "Method 10" -Target $email
    #>

}

Function Method11 {
    <#
    .SYNOPSIS
    Method to get user's OOF Settings.
     
    .DESCRIPTION
    Method to get user's OOF Settings.
     
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
 
    .EXAMPLE
    PS C:\> Method11
    Method to get user's OOF Settings.
 
    #>

    [CmdletBinding()]
    param(
        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    $statusBarLabel.Text = "Running..."

    Test-StopWatch -Service $service -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret

    $array = New-Object System.Collections.ArrayList
    $output = $service.GetUserOofSettings($email) | Select-Object `
        State, `
        ExternalAudience, `
        @{ Name = "StartTime" ; Expression = { $service.GetUserOofSettings($email).Duration.StartTime.ToString() } }, `
        @{ Name = "EndTime" ; Expression = { $service.GetUserOofSettings($email).Duration.EndTime.ToString() } }, `
        @{ Name = "InternalReply" ; Expression = { $service.GetUserOofSettings($email).InternalReply.Message } }, `
        @{ Name = "ExternalReply" ; Expression = { $service.GetUserOofSettings($email).ExternalReply.Message } }, `
        AllowExternalOof
    $array.Add($output)

    $dgResults.datasource = $array
    $dgResults.AutoResizeColumns()
    $dgResults.Visible = $True
    $txtBoxResults.Visible = $False
    $PremiseForm.refresh()
    $statusBarLabel.text = "Ready..."
    Write-PSFMessage -Level Host -Message "Task finished succesfully" -FunctionName "Method 11" -Target $email
}

Function Method12 {
    <#
    .SYNOPSIS
    Method to move items between folders.
     
    .DESCRIPTION
    Method to move items between folders by using FolderID values.
     
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
     
    .EXAMPLE
    PS C:\> Method12
    Method to move items between folders.
 
    #>

    [CmdletBinding()]
    param(
        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    $statusBarLabel.Text = "Running..."

    Test-StopWatch -Service $service -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret

    if ( $txtBoxFolderID.Text -ne "")
    {
        # Creating Filter variables
        $FolderID = new-object Microsoft.Exchange.WebServices.Data.FolderId($txtBoxFolderID.Text)
        $Folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$FolderID)
        $TargetFolderId = new-object Microsoft.Exchange.WebServices.Data.FolderId($txtBoxTargetFolderID.Text)
        $StartDate = $FromDatePicker.Value
        $EndDate = $ToDatePicker.Value
        $MsgSubject = $txtBoxSubject.text
        [int]$i = 0

        # Combining Filters into a single Collection
        $filters = @()
        if ( $MsgSubject -ne "" )
        {
            $Filter1 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::Subject,$MsgSubject, [Microsoft.Exchange.WebServices.Data.ContainmentMode]::ExactPhrase, [Microsoft.Exchange.WebServices.Data.ComparisonMode]::IgnoreCase)
            $filters += $Filter1
        }
        if ( $StartDate -ne "" )
        {
            $Filter2 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsGreaterThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived,[DateTime]$StartDate)
            $filters += $Filter2
        }
        if ( $EndDate -ne "" )
        {
            $Filter3 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived,[DateTime]$EndDate)
            $filters += $Filter3
        }

        $searchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::AND,$filters)

        if ( $filters.Length -eq 0 )
        {
            $searchFilter = $Null
        }

        $ivItemView =  New-Object Microsoft.Exchange.WebServices.Data.ItemView(250)
        $fiItems = $null
        $array = New-Object System.Collections.ArrayList
        do{
            $fiItems = $service.FindItems($Folder.Id, $searchFilter, $ivItemView)
            foreach ( $Item in $fiItems.Items )
            {
                $i++
                $output = $Item | Select-Object @{Name="Action";Expression={"Moving Item"}}, DateTimeReceived, Subject
                $array.Add($output)
                $tempItem = [Microsoft.Exchange.WebServices.Data.Item]::Bind($service,$Item.Id)
                $tempItem.Move($TargetFolderId) | Out-Null
            }
            $ivItemView.Offset += $fiItems.Items.Count
            Start-Sleep -Milliseconds 500
        } while ( $fiItems.MoreAvailable -eq $true )
        $dgResults.datasource = $array
        $dgResults.AutoResizeColumns()
        $dgResults.Visible = $True
        $txtBoxResults.Visible = $False
        $PremiseForm.refresh()
        $statusBarLabel.text = "Ready. Moved Items: $i"
        Write-PSFMessage -Level Host -Message "Task finished succesfully" -FunctionName "Method 12" -Target $email
    }
    else
    {
        [Microsoft.VisualBasic.Interaction]::MsgBox("FolderID textbox is empty. Check and try again",[Microsoft.VisualBasic.MsgBoxStyle]::Okonly,"Information Message")
        $statusBarLabel.text = "Process finished with warnings/errors"
    }
}

Function Method13 {
    <#
    .SYNOPSIS
    Method to Delete a subset of items in a folder.
     
    .DESCRIPTION
    Method to Delete a subset of items in a folder using Date Filters and/or subject.
     
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
 
    .EXAMPLE
    PS C:\> Method13
    Method to Delete a subset of items in a folder.
 
    #>

    [CmdletBinding()]
    param(
        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    $statusBarLabel.Text = "Running..."

    Test-StopWatch -Service $service -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret

    if ( $txtBoxFolderID.Text -ne "" )
    {
        # Creating Filter variables
        $FolderID = new-object Microsoft.Exchange.WebServices.Data.FolderId($txtBoxFolderID.Text)
        $Folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$FolderID)
        $StartDate = $FromDatePicker.Value
  $EndDate = $ToDatePicker.Value
  $MsgSubject = $txtBoxSubject.text
        [int]$i = 0
        
        # Combining Filters into a single Collection
        $filters = @()
        if ( $MsgSubject -ne "" )
        {
            $Filter1 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::Subject,$MsgSubject, [Microsoft.Exchange.WebServices.Data.ContainmentMode]::ExactPhrase, [Microsoft.Exchange.WebServices.Data.ComparisonMode]::IgnoreCase)
            $filters += $Filter1
        }
        if ( $StartDate -ne "" )
        {
            $Filter2 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsGreaterThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived,[DateTime]$StartDate)
            $filters += $Filter2
        }
        if ( $EndDate -ne "" )
        {
            $Filter3 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived,[DateTime]$EndDate)
            $filters += $Filter3
        }

        $searchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::AND,$filters)

        if ( $filters.Length -eq 0 )
        {
            $searchFilter = $Null
        }

        $ivItemView =  New-Object Microsoft.Exchange.WebServices.Data.ItemView(250)
  $fiItems = $null

        $array = New-Object System.Collections.ArrayList
        do {
            $fiItems = $service.FindItems($Folder.Id, $searchFilter, $ivItemView)
            foreach ( $Item in $fiItems.Items )
            {
                $i++
                $output = $Item | Select-Object @{Name="Action";Expression={"Deleting Item"}}, DateTimeReceived, Subject
                $array.Add($output)
            
                $tempItem = [Microsoft.Exchange.WebServices.Data.Item]::Bind($service,$Item.Id)
                $tempItem.Delete($ComboOption, $True)
            }
            $ivItemView.Offset += $fiItems.Items.Count
            Start-Sleep -Milliseconds 500
        } while ( $fiItems.MoreAvailable -eq $true )
        $dgResults.datasource = $array
        $dgResults.AutoResizeColumns()
        $dgResults.Visible = $True
        $txtBoxResults.Visible = $False
        $PremiseForm.refresh()
        $statusBarLabel.text = "Ready. Deleted items: $i"
        Write-PSFMessage -Level Host -Message "Task finished succesfully" -FunctionName "Method 13" -Target $email
    }
    else
    {
        [Microsoft.VisualBasic.Interaction]::MsgBox("FolderID textbox is empty. Check and try again",[Microsoft.VisualBasic.MsgBoxStyle]::Okonly,"Information Message")
        $statusBarLabel.text = "Process finished with warnings/errors"
    }
}

Function Method14 {
    <#
    .SYNOPSIS
    Get user's Delegates information
     
    .DESCRIPTION
    Get user's Delegates information
     
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
     
    .EXAMPLE
    PS C:\> Method14
    Get user's Delegates information
 
    #>

    [CmdletBinding()]
    param(
        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    $statusBarLabel.Text = "Running..."

    Test-StopWatch -Service $service -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret

    # Create a mailbox object that represents the user in case we are impersonating.
    $mailbox = New-Object Microsoft.Exchange.WebServices.Data.Mailbox($email);
    # Call the GetDelegates method to get the delegates of the mailbox object.
    $delegates = $service.GetDelegates($mailbox , $true)
    $Collection = @()
    foreach( $Delegate in $delegates.DelegateUserResponses )
    {
        $Obj = "" | Select-Object EmailAddress,Inbox,Calendar,Contacts,Tasks,Notes,Journal,MeetingMessages,ViewPrivateItems
        $Obj.EmailAddress = $Delegate.DelegateUser.UserId.PrimarySmtpAddress
        $Obj.Inbox = $Delegate.DelegateUser.Permissions.InboxFolderPermissionLevel
        $Obj.Calendar = $Delegate.DelegateUser.Permissions.CalendarFolderPermissionLevel
        $Obj.Contacts = $Delegate.DelegateUser.Permissions.ContactsFolderPermissionLevel
        $Obj.Tasks = $Delegate.DelegateUser.Permissions.TasksFolderPermissionLevel
        $Obj.Notes = $Delegate.DelegateUser.Permissions.NotesFolderPermissionLevel
        $Obj.Journal = $Delegate.DelegateUser.Permissions.JournalFolderPermissionLevel
        $Obj.ViewPrivateItems = $Delegate.DelegateUser.ViewPrivateItems
        $Obj.MeetingMessages = $Delegate.DelegateUser.ReceiveCopiesOfMeetingMessages
        $Collection += $Obj
    }
    $array = New-Object System.Collections.ArrayList
    [int]$i = 0
    foreach ( $Del in $Collection )
    {
        $i++
        $output = $Del | Select-Object EmailAddress, Inbox, Calendar, Tasks, Notes, Journal, ViewPrivateItems, MeetingMessages
        $array.Add($output)
    }
    $dgResults.datasource = $array
    $dgResults.AutoResizeColumns()
    $dgResults.Visible = $True
    $txtBoxResults.Visible = $False
    $PremiseForm.refresh()
    $statusBarLabel.text = "Ready. Amount of Delegates: $i"
    Write-PSFMessage -Level Host -Message "Task finished succesfully" -FunctionName "Method 14" -Target $email
}

Function Method15 {
    <#
    .SYNOPSIS
    Method to change sensitivity to items in a folder.
     
    .DESCRIPTION
    Method to change sensitivity to items in a folder.
     
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
     
    .EXAMPLE
    PS C:\> Method15
    Method to change sensitivity to items in a folder.
 
    #>

    [CmdletBinding()]
    param(
        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    $statusBarLabel.Text = "Running..."

    Test-StopWatch -Service $service -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret

    if ( $txtBoxFolderID.Text -ne "" )
    {
        # Creating Filter variables
        $FolderID = new-object Microsoft.Exchange.WebServices.Data.FolderId($txtBoxFolderID.Text)
        $Folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$FolderID)
        $StartDate = $FromDatePicker.Value
  $EndDate = $ToDatePicker.Value
  $MsgSubject = $txtBoxSubject.text
        [int]$i = 0

        # Combining Filters into a single Collection
        $filters = @()
        if ( $MsgSubject -ne "" )
        {
            $Filter1 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::Subject,$MsgSubject, [Microsoft.Exchange.WebServices.Data.ContainmentMode]::ExactPhrase, [Microsoft.Exchange.WebServices.Data.ComparisonMode]::IgnoreCase)
            $filters += $Filter1
        }
        if ( $StartDate -ne "" )
        {
            $Filter2 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsGreaterThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived,[DateTime]$StartDate)
            $filters += $Filter2
        }
        if ( $EndDate -ne "" )
        {
            $Filter3 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived,[DateTime]$EndDate)
            $filters += $Filter3
        }
        $searchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::AND,$filters)

        if ( $filters.Length -eq 0 )
        {
            $searchFilter = $Null
        }

        $ivItemView =  New-Object Microsoft.Exchange.WebServices.Data.ItemView(250)
        $fiItems = $null
        $array = New-Object System.Collections.ArrayList
        do {
            $fiItems = $service.FindItems($Folder.Id, $searchFilter, $ivItemView)
            foreach ( $Item in $fiItems.Items )
            {
                $i++
                $output = $Item | Select-Object @{Name="Action";Expression={"Applying Sensitivity" + $DeleteOpt}}, DateTimeReceived, Subject
                $array.Add($output)

                $tempItem = [Microsoft.Exchange.WebServices.Data.Item]::Bind($service,$Item.Id)
                $tempItem.Sensitivity = $DeleteOpt
                $tempItem.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)
            }
            $ivItemView.Offset += $fiItems.Items.Count
            Start-Sleep -Milliseconds 500
        } while ( $fiItems.MoreAvailable -eq $true )
        $dgResults.datasource = $array
        $dgResults.AutoResizeColumns()
        $dgResults.Visible = $True
        $txtBoxResults.Visible = $False
        $PremiseForm.refresh()
        $statusBarLabel.text = "Ready. Items changed: $i"
        Write-PSFMessage -Level Host -Message "Task finished succesfully" -FunctionName "Method 15" -Target $email
    }
    else
    {
        [Microsoft.VisualBasic.Interaction]::MsgBox("FolderID textbox is empty. Check and try again",[Microsoft.VisualBasic.MsgBoxStyle]::Okonly,"Information Message")
        $statusBarLabel.text = "Process finished with warnings/errors"
    }
}

Function Method16 {
    <#
    .SYNOPSIS
    Method to remove OWA configurations.
     
    .DESCRIPTION
    Method to remove OWA configurations.
     
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
     
    .EXAMPLE
    PS C:\> Method16
    Method to remove OWA configurations.
 
    #>

    [CmdletBinding()]
    param(
        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    $statusBarLabel.Text = "Running..."

    Test-StopWatch -Service $service -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret

    $output = "Checking" + $ComboOption2
    $txtBoxResults.Text = $output
    $txtBoxResults.Visible = $True
    $PremiseForm.Refresh()

    $fid = $null
    if ( $ComboOption1 -eq "Root" )
    {
        $fid = New-Object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Root, $email)
    }
    elseif ( $ComboOption1 -eq "Calendar" )
    {
        $fid = New-Object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar, $email)
    }
    elseif ( $ComboOption1 -eq "Inbox" )
    {
        $fid = New-Object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox, $email)
    }
    
    if ( $ComboOption2 -ne "CleanFinders" )
    {
        try
        {
            $Config = [Microsoft.Exchange.WebServices.Data.UserConfiguration]::Bind($Service, $ComboOption2, $fid, [Microsoft.Exchange.WebServices.Data.UserConfigurationProperties]::All)
            $Config.Delete();
            $output = $output + $nl + "Deleted $ComboOption2"
        }
        catch
        {
            $output = $output + $nl + "$ComboOption2 doesn't exist"
        }
        $statusBarLabel.text = "Ready..."
        Write-PSFMessage -Level Host -Message "Task finished succesfully" -FunctionName "Method 16" -Target $email
        $txtBoxResults.Text = $output
        $txtBoxResults.Visible = $True
        $PremiseForm.Refresh()

    }
    else
    {
        # Creating folder object (SearchFolders also know as Finder)
        $folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::SearchFolders,$SmtpAddress)

        # Opening the bind to user Folder Finder
        $output = $output + $nl + "Opening Mailbox: $email"
        try
        {
            $finderFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($Service,$folderid)
            $output = $output + $nl + "Cleaning SearchFolder (same as Outlook /Cleanfinders)"

            # If the bind was created, clean the folder Finder
            Try
            {
                $finderFolder.Empty([Microsoft.Exchange.WebServices.Data.DeleteMode]::SoftDelete, $true)
                $output = $output + $nl + "The Cleanup process for the Mailbox: $email Succeed!"
            }
            catch
            {
                $output = $output + $nl + "Fail to clean Search folder Mailbox: $email"
            }
        }
        catch
        {
            $output = $output + $nl + "Fail to open Mailbox: $email"
        }
        $txtBoxResults.Text = $output
        $txtBoxResults.Visible = $True
        $statusBarLabel.text = "Ready..."
        Write-PSFMessage -Level Host -Message "Task finished succesfully" -FunctionName "Method 16"
        $PremiseForm.Refresh()

        #Cleaning Variables
        $SmtpAddress = $null
        $finderFolder = $null
        $folderid = $null
    }
}

Function Method17 {
    <#
    .SYNOPSIS
    Method to switch to another mailbox.
     
    .DESCRIPTION
    Method to switch to another mailbox.
     
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
     
    .EXAMPLE
    PS C:\> Method17
    Method to switch to another mailbox.
 
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidGlobalVars", "")]
    [CmdletBinding()]
    param(
        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    $statusBarLabel.Text = "Running..."

    Test-StopWatch -Service $service -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret

    if ( $txtBoxFolderID.Text -ne "" )
    {
        $TargetSmtpAddress = $txtBoxFolderID.Text
        $service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $TargetSmtpAddress)
        $service.HttpHeaders.Clear()
        $service.HttpHeaders.Add("X-AnchorMailbox", $TargetSmtpAddress)
        $Global:email = $TargetSmtpAddress

        $labImpersonation.Location = New-Object System.Drawing.Point(575,200)
        $labImpersonation.Size = New-Object System.Drawing.Size(300,20)
        $labImpersonation.Name = "labImpersonation"
        $labImpersonation.ForeColor = "Blue"
        $PremiseForm.Controls.Add($labImpersonation)
        $labImpersonation.Text = $Global:email
        $PremiseForm.Text = "Managing user: " + $Global:email + ". Choose your Option"

        Write-PSFMessage -Level Host -Message "Task finished succesfully" -FunctionName "Method 17" -Target $email
        $statusBarLabel.text = "Ready..."
        $PremiseForm.Refresh()
    }
    else
    {
        [Microsoft.VisualBasic.Interaction]::MsgBox("Email Address textbox is empty. Check and try again",[Microsoft.VisualBasic.MsgBoxStyle]::Okonly,"Information Message")
        $statusBarLabel.text = "Process finished with warnings/errors"
    }
}

Function Method1to6 {
    <#
    .SYNOPSIS
    Method to list folders in the user mailbox.
     
    .DESCRIPTION
    Method to list folders in the user mailbox, showing Folder name, FolderId, Number of items, and number of subfolders.
     
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
 
    .EXAMPLE
    PS C:\> Method1to6
    lists folders in the user mailbox.
 
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "")]
    [CmdletBinding()]
    param(
        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    $statusBarLabel.Text = "Running..."

    Test-StopWatch -Service $service -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret

    Function Find-Subfolders {
        Param (
            $array,

            $ParentFolderId,

            $ParentDisplayname
        )
        $sourceFolderId = new-object Microsoft.Exchange.WebServices.Data.FolderId($ParentFolderId)
        $rootfolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$sourceFolderId)

        $FolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(100)
        #$FolderView.Traversal = "Deep"
        
        $rootfolder.load()
        foreach ($folder in $rootfolder.FindFolders($FolderView) ) {
            $i++
            $DisplayName = "$ParentDisplayname\$($Folder.Displayname)"
            $output = $folder | Select-Object @{N = "Displayname" ; E = {$DisplayName}}, @{N = "TotalItemsCount"; E = { $_.TotalCount } }, @{N = "# of Subfolders"; E = { $_.ChildFolderCount } }, Id
            $array.Add($output)
            if ($folder.ChildFolderCount -gt 0) {
                #write-host "looking for subfolders under $($folder.displayname)" -ForegroundColor Green
                Find-Subfolders -ParentFolderId $folder.id -ParentDisplayname $Displayname -Array $array
            }
        }
    }

    if ($radiobutton1.Checked) { $Wellknownfolder = "MsgFolderRoot" }
    elseif ($radiobutton2.Checked) { $Wellknownfolder = "ArchiveMsgFolderRoot" }
    elseif ($radiobutton3.Checked) { $Wellknownfolder = "PublicFoldersRoot" }
    elseif ($radiobutton4.Checked) { $Wellknownfolder = "RecoverableItemsRoot" }
    elseif ($radiobutton5.Checked) { $Wellknownfolder = "ArchiveRecoverableItemsRoot" }

    #listing all available folders in the mailbox
    $rootfolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service, [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::$Wellknownfolder)
    $array = New-Object System.Collections.ArrayList
    Find-Subfolders -ParentFolderId $rootfolder.id -Array $array -ParentDisplayname ""

    $dgResults.datasource = $array
    $dgResults.AutoResizeColumns()
    $dgResults.Visible = $True
    $txtBoxResults.Visible = $False
    $PremiseForm.refresh()
    $statusBarLabel.Text = "Ready. Folders found: $($array.Count)"
    Write-PSFMessage -Level Output -Message "Task finished succesfully" -FunctionName "Method 1-6" -Target $email
}

Function Method7 {
    <#
    .SYNOPSIS
    Method to list items in a specific folders in the user mailbox.
     
    .DESCRIPTION
    Method to list items in a specific folders in the user mailbox.
     
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
     
    .EXAMPLE
    PS C:\> Method7
    Method to list items in a specific folders in the user mailbox.
 
    #>

    [CmdletBinding()]
    param(
        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    $statusBarLabel.Text = "Running..."

    Test-StopWatch -Service $service -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret

    if ( $txtBoxFolderID.Text -ne "" )
    {
        # Creating Filter variables
        $FolderID = new-object Microsoft.Exchange.WebServices.Data.FolderId($txtBoxFolderID.Text)
        $Folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$FolderID)
        $StartDate = $FromDatePicker.Value
        $EndDate = $ToDatePicker.Value
        $MsgSubject = $txtBoxSubject.text
        [int]$i=0

        # Combining Filters into a single Collection
        $filters = @()
        if ( $MsgSubject -ne "" )
        {
            $Filter1 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::Subject,$MsgSubject, [Microsoft.Exchange.WebServices.Data.ContainmentMode]::ExactPhrase, [Microsoft.Exchange.WebServices.Data.ComparisonMode]::IgnoreCase)
            $filters += $Filter1
        }
        if ( $StartDate -ne "" )
        {
            $Filter2 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsGreaterThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived,[DateTime]$StartDate)
            $filters += $Filter2
        }
        if ( $EndDate -ne "" )
        {
            $Filter3 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived,[DateTime]$EndDate)
            $filters += $Filter3
        }

        $searchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::AND,$filters)

        if ( $filters.Length -eq 0 )
        {
            $searchFilter = $Null
        }
        
        $ivItemView =  New-Object Microsoft.Exchange.WebServices.Data.ItemView(250)
        
        $fiItems = $null
        $array = New-Object System.Collections.ArrayList
        do {
            $fiItems = $service.FindItems($Folder.Id, $searchFilter, $ivItemView)
            foreach ( $Item in $fiItems.Items )
            {
                $i++
                $output = $Item | Select-Object Subject, Sender, DateTimeReceived, Size
                $array.Add($output)
            }
            $ivItemView.Offset += $fiItems.Items.Count
        } while ( $fiItems.MoreAvailable -eq $true )

        $dgResults.datasource = $array
        $dgResults.AutoResizeColumns()
        $dgResults.Visible = $True
        $txtBoxResults.Visible = $False
        $PremiseForm.refresh()
        $statusBarLabel.text = "Ready. Items found: $i"
        Write-PSFMessage -Level Output -Message "Task finished succesfully" -FunctionName "Method 7" -Target $email
    }
    else
    {
        [Microsoft.VisualBasic.Interaction]::MsgBox("FolderID textbox is empty. Check and try again",[Microsoft.VisualBasic.MsgBoxStyle]::Okonly,"Information Message")
        $statusBarLabel.text = "Process finished with warnings/errors"
    }
}

Function Method8 {
    <#
    .SYNOPSIS
    Method to create a custom folder in mailbox's Root.
     
    .DESCRIPTION
    Method to create a custom folder in mailbox's Root.
     
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
     
    .EXAMPLE
    PS C:\> Method8
    Method to create a custom folder in mailbox's Root.
 
    #>

    [CmdletBinding()]
    param(
        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    
    if ( $txtBoxFolderID.Text -ne "" )
    {
        $statusBarLabel.text = "Running..."
        Test-StopWatch -Service $service -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret

        $folder = new-object Microsoft.Exchange.WebServices.Data.Folder($service)
        $folder.DisplayName = $txtBoxFolderID.Text
        $folder.Save([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot)

        Write-PSFMessage -Level Host -Message "Task finished succesfully. Folder Created: $($txtBoxFolderID.Text)" -FunctionName "Method 8" -Target $email
        $statusBarLabel.text = "Ready..."
        $PremiseForm.Refresh()
    }
    else
    {
        [Microsoft.VisualBasic.Interaction]::MsgBox("FolderID textbox is empty. Check and try again",[Microsoft.VisualBasic.MsgBoxStyle]::Okonly,"Information Message")
        $statusBarLabel.text = "Method 8 finished with warnings/errors"
    }
}

Function Method9 {
    <#
    .SYNOPSIS
    Method to delete a specific folder in the user mailbox.
     
    .DESCRIPTION
    Method to delete a specific folder in the user mailbox with 3 different deletion methods.
     
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
 
    .EXAMPLE
    PS C:\> Method9
    Method to delete a specific folder in the user mailbox.
 
    #>

    [CmdletBinding()]
    param(
        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    $statusBarLabel.Text = "Running..."

    Test-StopWatch -Service $service -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret

    if ( $txtBoxFolderID.Text -ne "" )
    {
        $sourceFolderId = new-object Microsoft.Exchange.WebServices.Data.FolderId($txtBoxFolderID.Text)
        $SourceFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$sourceFolderId)
        $sourceFolder.Delete($ComboOption)

        Write-PSFMessage -Level Host -Message "Task finished succesfully" -FunctionName "Method 9" -Target $email
        $statusBarLabel.text = "Ready..."
        $PremiseForm.Refresh()
    }
    else
    {
        [Microsoft.VisualBasic.Interaction]::MsgBox("FolderID textbox is empty. Check and try again",[Microsoft.VisualBasic.MsgBoxStyle]::Okonly,"Information Message")
        $statusBarLabel.text = "Process finished with warnings/errors"
    }
}

Function Register-EWSGuiApp {
    <#
    .SYNOPSIS
    Registers EWS API Application into AzureAD
     
    .DESCRIPTION
    Registers EWS API Application into AzureAD and grant Admin consent on behalf of the Organization.
     
    .EXAMPLE
    PS C:\> Regiser-EWSGuiApp
    Registers EWS API Application into AzureAD
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "")]
    [Cmdletbinding()]
    param(
        # Parameters
    )
    Invoke-PSFProtectedCommand -Action "Connecting to AzureAD" -Target "AzureAD" -ScriptBlock {
        Write-PSFHostColor -String "[$((Get-Date).ToString("HH:mm:ss"))] Connecting to AzureAD"
        if ( !(Get-Module AzureAD -ListAvailable) -and !(Get-Module AzureAD) ) {
            Install-Module AzureAD -Force -ErrorAction Stop
        }
        try {
            Import-module AzureAD
            Write-PSFHostColor -String "[$((Get-Date).ToString("HH:mm:ss"))] We will connect to AzureAD to allow this app to connect to your tenant using OAUTH"
            $ConnStatus = Connect-AzureAD -ErrorAction Stop
        }
        catch {
            return $_
        }
    } -EnableException $true -PSCmdlet $PSCmdlet

    # register "PowerShellEWSScripts" as Enterprise App, by creating servicePrincipal (if not created)
    Write-PSFHostColor -String "[$((Get-Date).ToString("HH:mm:ss"))] Register `"PowerShellEWSScripts`" as Enterprise App, by creating servicePrincipal (if not created)"
    if ( $null -eq ( Get-AzureADServicePrincipal -All:$True | Where-object { $_.displayname -eq "PowerShellEWSScripts" } ) ) {
        $AzureADServicePrincipalParams = @{
            AccountEnabled            = $True
            AppId                     = "8799ab60-ace5-4bda-b31f-621c9f6668db"
            ServicePrincipalNames     = "8799ab60-ace5-4bda-b31f-621c9f6668db"
            AppRoleAssignmentRequired = $False
            DisplayName               = "PowerShellEWSScripts"
            PublisherName             = "Microsoft"
            ReplyUrls                 = "http://localhost/code"
            ServicePrincipalType      = "Application"
            Tags                      = "WindowsAzureActiveDirectoryIntegratedApp"
            ErrorAction               = "Stop"
        }
        $AppDetails = New-AzureADServicePrincipal @AzureADServicePrincipalParams
    }
    else {
        $AppDetails = Get-AzureADServicePrincipal -All:$True | Where-object { $_.displayname -eq "PowerShellEWSScripts" }
    }

    # register Service Principal Assignment between Global admin and the registered app:
    $AdminObjectId = (Get-AzureAdUser -Filter "userprincipalname eq '$($ConnStatus.Account.id)'").ObjectId
    if ( -not (Get-AzureADServiceAppRoleAssignment -ObjectId $AppDetails.ObjectId -All:$true | Where-Object { $_.PrincipalId -eq $AdminObjectId }) ) {
        $null = $appDetails | New-AzureADServiceAppRoleAssignment -PrincipalId $AdminObjectId -ResourceId $AppDetails.ObjectId -id "00000000-0000-0000-0000-000000000000" -ErrorAction Stop
    }

    # Grant consent to the App to access EXO and Windows Azure AD to sign in on behalf of the whole tenant (no user consent will be needed afterwards)
    Write-PSFHostColor -String "[$((Get-Date).ToString("HH:mm:ss"))] Grant consent to the App to access EXO and AzureAD to sign-in on behalf of the users"
    if ( -not (Get-AzureADServicePrincipalOAuth2PermissionGrant -ObjectId $AppDetails.ObjectId -All:$True | Where-Object { ($_.Scope -eq "User.Read" -and $_.ResourceID -eq "525065a3-df7d-474d-be08-90fa1d62d4bb") -or ($_.Scope -eq "EWS.AccessAsUser.All" -and $_.ResourceID -eq "8b951d63-7dd0-46e8-a326-15e3f6a26353") }) ) {
        $TenantId = (Get-AzureADTenantDetail).objectid
        $context = Get-AzContext
        $refreshToken = @($context.TokenCache.ReadItems() | Where-Object { $_.tenantId -eq $tenantId -and $_.ExpiresOn -gt (Get-Date) })[0].RefreshToken
        $body = "grant_type=refresh_token&refresh_token=$($refreshToken)&resource=74658136-14ec-4630-ad9b-26e160ff0fc6"
        $apiToken = Invoke-RestMethod "https://login.windows.net/$tenantId/oauth2/token" -Method POST -Body $body -ContentType 'application/x-www-form-urlencoded' -ErrorAction Stop
        $header = @{
            'Authorization'          = 'Bearer ' + $apiToken.access_token
            'X-Requested-With'       = 'XMLHttpRequest'
            'x-ms-client-request-id' = [guid]::NewGuid()
            'x-ms-correlation-id'    = [guid]::NewGuid()
        }
        $url = "https://main.iam.ad.ext.azure.com/api/RegisteredApplications/$($AppDetails.AppId)/Consent?onBehalfOfAll=true"
        Invoke-RestMethod â€“Uri $url â€“Headers $header â€“Method POST -ErrorAction Stop
    }
}

Function Start-ModuleUpdate {
    <#
    .SYNOPSIS
    Function to start checking for updates on this module.
     
    .DESCRIPTION
    Function to start checking for updates on this module.
     
    .PARAMETER ModuleRoot
    Modules root path.
 
    .PARAMETER Confirm
    If this switch is enabled, you will be prompted for confirmation before executing any operations that change state.
 
    .PARAMETER WhatIf
    If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run.
     
    .EXAMPLE
    PS C:\> Start-ModuleUpdate -ModuleRoot "C:\Temp"
    Runs the function to start checking for update for current module in "C:\Temp"
    #>

    [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low')]
    Param (
        [String]$ModuleRoot
    )

    $ScriptBlock = {
        Param (
            [String]$ModuleRoot
        )
        $moduleManifest = (Import-PowerShellDataFile -Path "$((Get-ChildItem -Path $ModuleRoot -Filter *.psd1).Fullname)")
        $moduleFileName = $moduleManifest.RootModule
        $moduleName = $ModuleFileName.Substring(0, $ModuleFileName.IndexOf("."))
        $script:ModuleVersion = $moduleManifest.ModuleVersion -as [version]

        $GalleryModule = Find-Module -Name $ModuleName -Repository PSGallery
        if ( $script:ModuleVersion -lt $GalleryModule.version ) {
            $bt = New-BTButton -Content "Get Update" -Arguments "$($moduleManifest.PrivateData.PSData.ProjectUri)#installation"
            New-BurntToastNotification -Text "$ModuleName Update found", 'There is a new version of this module available.' -Button $bt
        }
    }

    # Create Runspace, set maximum threads
    $pool = [RunspaceFactory]::CreateRunspacePool(1, 1)
    $pool.ApartmentState = "MTA"
    $pool.Open()

    $runspace = [PowerShell]::Create()
    $runspace.Runspace.Name = "$ModuleName.Update"
    $null = $runspace.AddScript( $ScriptBlock )
    $null = $runspace.AddArgument( $ModuleRoot )
    $runspace.RunspacePool = $pool

    [PSCustomObject]@{
        Pipe   = $runspace
        Status = $runspace.BeginInvoke()
        Pool   = $pool
    }
}

Function Stop-ModuleUpdate {
    <#
    .SYNOPSIS
    Function to stop checking for updates on this module and clear runspaces.
     
    .DESCRIPTION
    Function to stop checking for updates on this module and clear runspaces.
     
    .PARAMETER RunspaceData
    Runspace data retrieved from intial Start-ModuleUpdate function.
 
    .PARAMETER Confirm
    If this switch is enabled, you will be prompted for confirmation before executing any operations that change state.
 
    .PARAMETER WhatIf
    If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run.
     
    .EXAMPLE
    PS C:\> Stop-ModuleUpdate -RunspaceData $data
    Runs the function to stop checking for update on this module and clear runspaces.
    #>

    [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low')]
    Param(
        $RunspaceData
    )
    # Receive Results and cleanup
    $null = $RunspaceData.Pipe.EndInvoke($RunspaceData.Status)
    $RunspaceData.Pipe.Dispose()

    # Cleanup Runspace Pool
    $RunspaceData.pool.Close()
    $RunspaceData.pool.Dispose()
}

function Test-StopWatch {
    <#
    .SYNOPSIS
    Function to check time elapsed since the last token was retrieved.
    If the time elapsed is greater than 50 minutes, we will go and fetch a new AccessToken based on the refresh token.
     
    .DESCRIPTION
    Function to check time elapsed since the last token was retrieved.
    If the time elapsed is greater than 50 minutes, we will go and fetch a new AccessToken based on the refresh token.
 
    .PARAMETER service
    EWS Service object.
 
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
     
    .EXAMPLE
    PS C:\> Test-StopWatch -Service $svcObj -ClientID "1234" -TenantID "abcd" -ClientSecret "a1b2c3d4"
 
    The function will check the time elapsed in the stop watcher, and fetch a new AccessToken if needed.
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidGlobalVars", "")]
    [CmdletBinding()]
    param (
        $service,

        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    
    begin {
        
    }
    
    process {
        if ( $global:stopWatch.Elapsed.Minutes -gt 50) {
            $token = Get-EWSToken -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret -Refresh
            $exchangeCredentials = New-Object Microsoft.Exchange.WebServices.Data.OAuthCredentials($Token.AccessToken)
            $Service.Credentials = $exchangeCredentials
        }
    }
    
    end {
        
    }
}

function Export-EWSGuiLog {
    <#
    .SYNOPSIS
    This function will export current PSFramework logs.
     
    .DESCRIPTION
    This function will export current PSFramework logs based on the amount of days old define in the 'DaysOld' parameter.
    It will allow to export to CSV file and/or display in powershell GridView.
    Output will have the following header: "ComputerName","Username","Timestamp","Level","Message","Type","FunctionName","ModuleName","File","Line","Tags","TargetObject","Runspace","Callstack"
     
    .PARAMETER FilePath
    Defines the path file to export the CSV file.
    Default value is the user's Desktop with a file name like "yyyy-MM-dd HH_mm_ss" - EWSGui logs.csv"
     
    .PARAMETER OutputType
    Defines the output types available. Can be a single output or combined.
    Current available options are CSV, GridView.
 
    .PARAMETER DaysOld
    Defines how old we will go to fetch the logs. Valid range is between 1 through 7 days old. Default Value is 1
     
    .EXAMPLE
    PS C:\> Export-EWSGuiLog -OutputType CSV
    In this example, the script will fetch all logs within the last 24 hrs (by default), and export to CSV to default location at the Desktop.
     
    .EXAMPLE
    PS C:\> Export-EWSGuiLog -OutputType GridView -DaysOld 3
    In this example, the script will fetch all logs within the last 3 days, and displays them in powershell's GridView.
 
    .EXAMPLE
    PS C:\> Export-EWSGuiLog -OutputType CSV,GridView -DaysOld 5
    In this example, the script will fetch all logs within the last 5 days, export to CSV to default location at the Desktop and also displays in powershell's GridView.
 
    .EXAMPLE
    PS C:\> Export-EWSGuiLog -OutputType CSV,GridView -DaysOld 7 -FilePath "C:\Temp\newLog.csv"
    In this example, the script will fetch all logs within the last 7 days, export to CSV to path "C:\Temp\newLog.csv" and also displays them in powershell's GridView.
    #>

    [CmdletBinding()]
    Param (
        [ValidateScript({
            if($_ -notmatch "(\.csv)"){
                throw "The file specified in the path argument must be of type CSV"
            }
            return $true
        })]
        [String]$FilePath = "$home\Desktop\$(get-date -Format "yyyy-MM-dd HH_mm_ss") - EWSGui logs.csv",
        
        [ValidateSet('CSV', 'GridView')]
        [string[]]$OutputType = "GridView",

        [ValidateRange(1, 7)]
        [int]$DaysOld = 1
    )
    # creating folder path if it doesn't exists
    $folderPath = ([System.IO.FileInfo]$FilePath).DirectoryName
    if ( $FilePath -notlike "$home\Desktop\*" ) {
        if ( -not (Test-Path $folderPath) ) {
            Write-PSFMessage -Level Warning -Message "Folder '$folderPath' does not exists. Creating folder."
            $null = New-Item -Path $folderPath -ItemType Directory -Force
        }
    }
    else {
        # Checking if Desktop folder is located in the user's profile folder, or synched to OneDrive
        if ( -not(Test-Path $folderPath) ) {
            $FilePath = "$env:OneDriveCommercial\Desktop\$(get-date -Format "yyyy-MM-dd HH_mm_ss") - EWSGui logs.csv"
        }
    }

    Import-module PSFramework
    $loggingpath = (Get-PSFConfig PSFramework.Logging.FileSystem.LogPath).Value
    $logFiles = Get-ChildItem -Path $loggingpath | Where-Object LastwriteTime -gt (Get-Date).adddays(-1 * $DaysOld)
    $csv = Import-Csv -Path $logFiles.FullName
    $output = $csv | Where-Object ModuleName -eq "EWSGui" | Select-Object @{N = "Date"; E = { ($_.timestamp -split " ")[0] } }, @{N = "Time"; E = { Get-Date ($_.timestamp.Substring($_.timestamp.IndexOf(" ")).trim()) -Format HH:mm:ss } }, `
        "ComputerName", "Username", "Level", "FunctionName", "Message", "Type", "ModuleName", "File", "Line", "Tags", "TargetObject", "Runspace", "Callstack" | Sort-Object Date -Descending

    Switch ( $OutputType) {
        CSV { $output | export-csv -Path $FilePath -NoTypeInformation }
        GridView { $output | Out-GridView }
    }
}


function Register-EWsGuiAADAppData {
    <#
    .SYNOPSIS
    Function to register ClientID, TenantID and ClientSecret to the EWSGui powershell module.
 
    .DESCRIPTION
    Function to register ClientID, TenantID and ClientSecret to the EWSGui powershell module.
     
    .PARAMETER ClientID
    String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    String parameter with the Client Secret which is configured in the AzureAD App.
     
    .EXAMPLE
    PS C:\> Register-EWsGuiAADAppData -ClientID "your app client ID" -TenantID "Your tenant ID" -ClientSecret "your Secret passcode"
 
    The script will register these values in the EWSGui module to be used automatically.
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [String] $ClientID,

        [Parameter(Mandatory = $true)]
        [String] $TenantID,

        [Parameter(Mandatory = $true)]
        [String] $ClientSecret
    )

    begin {
        if ( $ClientID -eq '' -or $TenantID -eq '' -or $CertificateThumbprint -eq '' ) {
            throw "Either ClientID, TenantID or ClientSecret are null or empty."
        }
    }

    process {
        Write-PSFMessage -Level Important -Message "Registering ClientID string to EWSGui Module."
        Set-PSFConfig -Module EwsGui -Name "ClientID" -Value $ClientID -Description "AppID of your Azure Registered App" -AllowDelete -PassThru | Register-PSFConfig
        
        Write-PSFMessage -Level Important -Message "Registering TenantID string to EWSGui Module."
        Set-PSFConfig -Module EwsGui -Name "TenantID" -Value $TenantID -Description "TenantID where your Azure App is registered." -AllowDelete -PassThru | Register-PSFConfig
        
        Write-PSFMessage -Level Important -Message "Registering ClientSecret string to EWSGui Module."
        Set-PSFConfig -Module EwsGui -Name "ClientSecret" -Value $clientSecret -Description "ClientSecret passcode for your Azure App" -AllowDelete -PassThru | Register-PSFConfig
    }

    end {

    }
}

Function Start-EWSGui {
    <#
    .SYNOPSIS
        Allows to perform 16 different operations using EWS API.
 
    .DESCRIPTION
        Allows to perform 16 different operations using EWS API:
        1) List Folders in Root
        2) List Folders in Archive Root
        3) List Folders in Public Folder Root
        4) List subFolders from a desired Parent Folder
        5) List folders in Recoverable Items Root folder
        6) List folders in Recoverable Items folder in Archive
        7) List Items in a desired Folder
        8) Create a custom Folder in Root
        9) Delete a Folder
        10) Get user's Inbox Rules
        11) Get user's OOF Settings
        12) Move items between folders
        13) Delete a subset of items in a folder
        14) Get user's Delegate information
        15) Change sensitivity to items in a folder
        16) Remove OWA configurations
        17) Switch to another Mailbox
     
    .PARAMETER ClientID
    This is an optional parameter. String parameter with the ClientID (or AppId) of your AzureAD Registered App.
 
    .PARAMETER TenantID
    This is an optional parameter. String parameter with the TenantID your AzureAD tenant.
 
    .PARAMETER ClientSecret
    This is an optional parameter. String parameter with the Client Secret which is configured in the AzureAD App.
 
    .PARAMETER Confirm
    If this switch is enabled, you will be prompted for confirmation before executing any operations that change state.
 
    .PARAMETER WhatIf
    If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run.
 
    .EXAMPLE
    PS C:\ Start-Ewsgui.ps1
    Runs the GUI tool to use EWS with Exchange server and Online.
 
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidGlobalVars", "")]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "")]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "")]
    [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low')]
    param(
        [String] $ClientID,

        [String] $TenantID,

        [String] $ClientSecret
    )
    $script:nl = "`r`n"
    $ProgressPreference = "SilentlyContinue"

    $runspaceData = Start-ModuleUpdate -ModuleRoot $script:ModuleRoot
    function GenerateForm {
   
    #region Import the Assemblies
    Add-Type -AssemblyName System.Windows.Forms
    Add-Type -AssemblyName System.Drawing
    Add-Type -AssemblyName Microsoft.VisualBasic
    [System.Windows.Forms.Application]::EnableVisualStyles()
    #endregion
 
    #region Generated Form Objects
    $Global:PremiseForm = New-Object System.Windows.Forms.Form
    $Global:radiobutton1 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton2 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton3 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton4 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton5 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton6 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton7 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton8 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton9 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton10 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton11 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton12 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton13 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton14 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton15 = New-Object System.Windows.Forms.RadioButton
    $Global:radiobutton16 = New-Object System.Windows.Forms.RadioButton
    $Global:labImpersonation = New-Object System.Windows.Forms.Label
    $labImpersonationHelp = New-Object System.Windows.Forms.Label
    $Global:buttonGo = New-Object System.Windows.Forms.Button
    $Global:buttonExit = New-Object System.Windows.Forms.Button

    $Global:dgResults = New-Object System.Windows.Forms.DataGridView
    $Global:txtBoxResults = New-Object System.Windows.Forms.Label
    $Global:InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
    [String]$Global:email = $null
    #endregion Generated Form Objects

    # registering EWS API as an Enterprise App in Azure AD
    # Register-EWSGuiApp

    # Connecting to EWS and creating service object
    $service = Connect-EWSService -ClientID $ClientID -TenantID $TenantID -ClientSecret $ClientSecret

    $ExpandFilters = {
    # Removing all controls, in order to reload the screen appropiately for each selection
    $PremiseForm.Controls.RemoveByKey("FromDate")
    $PremiseForm.Controls.RemoveByKey("FromDatePicker")
    $PremiseForm.Controls.RemoveByKey("ToDate")
    $PremiseForm.Controls.RemoveByKey("ToDatePicker")
    $PremiseForm.Controls.RemoveByKey("labSubject")
    $PremiseForm.Controls.RemoveByKey("txtBoxSubject")
    $PremiseForm.Controls.RemoveByKey("labFolderID")
    $PremiseForm.Controls.RemoveByKey("txtBoxFolderID")
    $PremiseForm.Controls.RemoveByKey("txtBoxTargetFolderID")
    $PremiseForm.Controls.RemoveByKey("labTargetFolderID")
    $PremiseForm.Controls.RemoveByKey("labelCombobox")
    $PremiseForm.Controls.RemoveByKey("comboBoxMenu")
    $PremiseForm.Controls.RemoveByKey("labelComboboxFolder")
    $PremiseForm.Controls.RemoveByKey("comboBoxFolder")
    $PremiseForm.Controls.RemoveByKey("labelComboboxConfig")
    $PremiseForm.Controls.RemoveByKey("comboBoxConfig")

    $Global:labFromDate = New-Object System.Windows.Forms.Label
    $Global:FromDatePicker = New-Object System.Windows.Forms.DateTimePicker
    $Global:labToDate = New-Object System.Windows.Forms.Label
    $Global:ToDatePicker = New-Object System.Windows.Forms.DateTimePicker
    $Global:labSubject = New-Object System.Windows.Forms.Label
    $Global:txtBoxSubject = New-Object System.Windows.Forms.TextBox
    $Global:labFolderID = New-Object System.Windows.Forms.Label
    $Global:txtBoxFolderID = New-Object System.Windows.Forms.TextBox
    $Global:labTargetFolderID = New-Object System.Windows.Forms.Label
    $Global:txtBoxTargetFolderID = New-Object System.Windows.Forms.TextBox
    $Global:labelCombobox = New-Object System.Windows.Forms.Label
    $Global:comboBoxMenu = New-Object System.Windows.Forms.ComboBox
    $Global:labelComboboxFolder = New-Object System.Windows.Forms.Label
    $Global:comboBoxFolder = New-Object System.Windows.Forms.ComboBox
    $Global:labelComboboxConfig = New-Object System.Windows.Forms.Label
    $Global:comboBoxConfig = New-Object System.Windows.Forms.ComboBox

    #Label FromDate
    $labFromDate.Location = New-Object System.Drawing.Point(5,285)
    $labFromDate.Size = New-Object System.Drawing.Size(80,35)
    $labFromDate.Name = "FromDate"
    $labFromDate.Text = "From or greater than"

    # FromDate Date Picker
    $FromDatePicker.DataBindings.DefaultDataSourceUpdateMode = 0
    $FromDatePicker.Location = New-Object System.Drawing.Point(100,285)
    $FromDatePicker.Name = "FromDatePicker"
    $FromDatePicker.Text = ""

    #Label ToDate
    $labToDate.Location = New-Object System.Drawing.Point(5,330)
    $labToDate.Name = "ToDate"
    $labToDate.Size = New-Object System.Drawing.Size(80,40)
    $labToDate.Text = "To or less than"

    # ToDate Date Picker
    $ToDatePicker.DataBindings.DefaultDataSourceUpdateMode = 0
    $ToDatePicker.Location = New-Object System.Drawing.Point(100,330)
    $ToDatePicker.Name = "ToDatePicker"
    $ToDatePicker.Text = ""

    #Label Subject
    $labSubject.Location = New-Object System.Drawing.Point(5,370)
    $labSubject.Size = New-Object System.Drawing.Size(50,20)
    $labSubject.Name = "labSubject"
    $labSubject.Text = "Subject: "
 
    #TextBox Subject
    $txtBoxSubject.Location = New-Object System.Drawing.Point(100,370)
    $txtBoxSubject.Size = New-Object System.Drawing.Size(280,20)
    $txtBoxSubject.Name = "txtBoxSubject"
    $txtBoxSubject.Text = ""

    #Label FolderID
    $labFolderID.Location = New-Object System.Drawing.Point(5,400)
    $labFolderID.Size = New-Object System.Drawing.Size(55,20)
    $labFolderID.Name = "labFolderID"
    $labFolderID.Text = "FolderID:"

    #TextBox FolderID
    $txtBoxFolderID.Location = New-Object System.Drawing.Point(100,400)
    $txtBoxFolderID.Size = New-Object System.Drawing.Size(280,20)
    $txtBoxFolderID.Name = "txtBoxFolderID"
    $txtBoxFolderID.Text = ""

    #Adapting FolderID and TxtBoxFolderID based on the selection
    if($radiobutton7.Checked -or $radiobutton8.Checked){
        $labFolderID.Location = New-Object System.Drawing.Point(5,285)
        $txtBoxFolderID.Location = New-Object System.Drawing.Point(100,285)
    }
    elseif($radiobutton11.Checked){
        $labFolderID.Size = New-Object System.Drawing.Size(95,20)
        $labFolderID.Text = "SourceFolderID:"
    }
    elseif($radiobutton16.Checked){
        $labFolderID.Location = New-Object System.Drawing.Point(5,285)
        $labFolderID.Size = New-Object System.Drawing.Size(95,20)
        $labFolderID.Text = "E-mail Address:"
        $txtBoxFolderID.Location = New-Object System.Drawing.Point(100,285)
    }

    #Label Target FolderID
    $labTargetFolderID.Location = New-Object System.Drawing.Point(5,430)
    $labTargetFolderID.Size = New-Object System.Drawing.Size(95,20)
    $labTargetFolderID.Name = "labTargetFolderID"
    $labTargetFolderID.Text = "TargetFolderID:"

    #TextBox Target FolderID
    $txtBoxTargetFolderID.Location = New-Object System.Drawing.Point(100,430)
    $txtBoxTargetFolderID.Size = New-Object System.Drawing.Size(280,20)
    $txtBoxTargetFolderID.Name = "txtBoxTargetFolderID"
    $txtBoxTargetFolderID.Text = ""

    #Label Combobox
    $labelCombobox.Location = New-Object System.Drawing.Point(400,285)
    $labelCombobox.Size = New-Object System.Drawing.Size(80,35)
    $labelCombobox.Name = "labelCombobox"
    if($radiobutton14.Checked){
        $labelCombobox.Text = "Change Option"
    }
    else {
        $labelCombobox.Text = "Delete Option"
    }

    #ComboBox Menu
    $comboBoxMenu.DataBindings.DefaultDataSourceUpdateMode = 0
    $comboBoxMenu.FormattingEnabled = $True
    $comboBoxMenu.Location = New-Object System.Drawing.Point(485,285)
    $comboBoxMenu.Name = "comboBoxMenu"
    $comboBoxMenu.add_SelectedIndexChanged($handler_comboBoxMenu_SelectedIndexChanged)

    #Label ComboboxFolder
    $labelComboboxFolder.Location = New-Object System.Drawing.Point(5,285)
    $labelComboboxFolder.Size = New-Object System.Drawing.Size(50,35)
    $labelComboboxFolder.Name = "labelComboboxFolder"
    $labelComboboxFolder.Text = "Folder:"

    #ComboBoxFolder
    $comboBoxFolder.DataBindings.DefaultDataSourceUpdateMode = 0
    $comboBoxFolder.FormattingEnabled = $True
    $comboBoxFolder.Location = New-Object System.Drawing.Point(55,285)
    $comboBoxFolder.Size = New-Object System.Drawing.Size(70,35)
    $comboBoxFolder.Name = "comboBoxFolder"
    $comboBoxFolder.Items.Add("")|Out-Null
    $comboBoxFolder.Items.Add("Root")|Out-Null
    $comboBoxFolder.Items.Add("Calendar")|Out-Null
    $comboBoxFolder.Items.Add("Inbox")|Out-Null
    $comboBoxFolder.add_SelectedIndexChanged($handler_comboBoxFolder_SelectedIndexChanged)

    #Label ComboboxConfig
    $labelComboboxConfig.Location = New-Object System.Drawing.Point(145,285)
    $labelComboboxConfig.Size = New-Object System.Drawing.Size(75,35)
    $labelComboboxConfig.Name = "labelComboboxConfig"
    $labelComboboxConfig.Text = "Config Name:"

    #ComboBoxConfig
    $comboBoxConfig.DataBindings.DefaultDataSourceUpdateMode = 0
    $comboBoxConfig.FormattingEnabled = $True
    $comboBoxConfig.Location = New-Object System.Drawing.Point(225,285)
    $ComboboxConfig.Size = New-Object System.Drawing.Size(180,35)
    $comboBoxConfig.Name = "comboBoxConfig"
    $comboBoxConfig.Items.Add("")|Out-Null
    $comboBoxConfig.Items.Add("Aggregated.OwaUserConfiguration")|Out-Null
    $comboBoxConfig.Items.Add("UserConfigurationProperties.All")|Out-Null
    $comboBoxConfig.Items.Add("OWA.AttachmentDataProvider")|Out-Null
    $comboBoxConfig.Items.Add("OWA.AutocompleteCache")|Out-Null
    $comboBoxConfig.Items.Add("OWA.SessionInformation")|Out-Null
    $comboBoxConfig.Items.Add("OWA.UserOptions")|Out-Null
    $comboBoxConfig.Items.Add("OWA.ViewStateConfiguration")|Out-Null
    $comboBoxConfig.Items.Add("Suite.Storage")|Out-Null
    $comboBoxConfig.Items.Add("UM.E14.PersonalAutoAttendants")|Out-Null
    $comboBoxConfig.Items.Add("CleanFinders")|Out-Null
    $comboBoxConfig.add_SelectedIndexChanged($handler_comboBoxConfig_SelectedIndexChanged)

    if($radiobutton6.Checked){
        $PremiseForm.Controls.Add($labFolderID)
        $PremiseForm.Controls.Add($txtBoxFolderID)
        $PremiseForm.Controls.Add($labFromDate)
        $PremiseForm.Controls.Add($FromDatePicker)
        $PremiseForm.Controls.Add($labToDate)
        $PremiseForm.Controls.Add($ToDatePicker)
        $PremiseForm.Controls.Add($labSubject)
        $PremiseForm.Controls.Add($txtBoxSubject)
    }
    elseif($radiobutton7.Checked){
        $labFolderID.Size = New-Object System.Drawing.Size(95,20)
        $labFolderID.Text = "Folder Name:"
        $PremiseForm.Controls.Add($labFolderID)
        $PremiseForm.Controls.Add($txtBoxFolderID)
    }
    elseif($radiobutton8.Checked){
        $comboBoxMenu.Items.Add("")|Out-Null
        $comboBoxMenu.Items.Add("HardDelete")|Out-Null
        $comboBoxMenu.Items.Add("MoveToDeletedItems")|Out-Null
        $comboBoxMenu.SelectedItem = "MoveToDeletedItems"
        $PremiseForm.Controls.Add($labFolderID)
        $PremiseForm.Controls.Add($txtBoxFolderID)
        $PremiseForm.Controls.Add($labelCombobox)
        $PremiseForm.Controls.Add($comboBoxMenu)
    }
    elseif($radiobutton11.Checked){
        $PremiseForm.Controls.Add($labFromDate)
        $PremiseForm.Controls.Add($FromDatePicker)
        $PremiseForm.Controls.Add($labToDate)
        $PremiseForm.Controls.Add($ToDatePicker)
        $PremiseForm.Controls.Add($labSubject)
        $PremiseForm.Controls.Add($txtBoxSubject)
        $PremiseForm.Controls.Add($labFolderID)
        $PremiseForm.Controls.Add($txtBoxFolderID)
        $PremiseForm.Controls.Add($labTargetFolderID)
        $PremiseForm.Controls.Add($txtBoxTargetFolderID)
    }
    elseif($radiobutton12.Checked){
        $comboBoxMenu.Items.Add("")|Out-Null
        $comboBoxMenu.Items.Add("SoftDelete")|Out-Null
        $comboBoxMenu.Items.Add("HardDelete")|Out-Null
        $comboBoxMenu.Items.Add("MoveToDeletedItems")|Out-Null
        $comboBoxMenu.SelectedItem = "MoveToDeletedItems"
        $PremiseForm.Controls.Add($labFromDate)
        $PremiseForm.Controls.Add($FromDatePicker)
        $PremiseForm.Controls.Add($labToDate)
        $PremiseForm.Controls.Add($ToDatePicker)
        $PremiseForm.Controls.Add($labSubject)
        $PremiseForm.Controls.Add($txtBoxSubject)
        $PremiseForm.Controls.Add($labFolderID)
        $PremiseForm.Controls.Add($txtBoxFolderID)
        $PremiseForm.Controls.Add($labelCombobox)
        $PremiseForm.Controls.Add($comboBoxMenu)
    }
    elseif($radiobutton14.Checked){
        $comboBoxMenu.Items.Add("")|Out-Null
        $comboBoxMenu.Items.Add("Normal")|Out-Null
        $comboBoxMenu.Items.Add("Personal")|Out-Null
        $comboBoxMenu.Items.Add("Private")|Out-Null
        $comboBoxMenu.Items.Add("Confidential")|Out-Null
        $comboBoxMenu.SelectedItem = "Normal"
        $PremiseForm.Controls.Add($labFromDate)
        $PremiseForm.Controls.Add($FromDatePicker)
        $PremiseForm.Controls.Add($labToDate)
        $PremiseForm.Controls.Add($ToDatePicker)
        $PremiseForm.Controls.Add($labSubject)
        $PremiseForm.Controls.Add($txtBoxSubject)
        $PremiseForm.Controls.Add($labFolderID)
        $PremiseForm.Controls.Add($txtBoxFolderID)
        $PremiseForm.Controls.Add($labelCombobox)
        $PremiseForm.Controls.Add($comboBoxMenu)
    }
    elseif($radiobutton15.Checked){
        $PremiseForm.Controls.Add($labelComboboxFolder)
        $PremiseForm.Controls.Add($comboBoxFolder)
        $PremiseForm.Controls.Add($labelComboboxConfig)
        $PremiseForm.Controls.Add($comboBoxConfig)
    }
    elseif($radiobutton16.Checked){
        $PremiseForm.Controls.Add($labFolderID)
        $PremiseForm.Controls.Add($txtBoxFolderID)
    }
    $PremiseForm.refresh()
    }

    $handler_comboBoxMenu_SelectedIndexChanged= {
    # Get the Event ID when item is selected
        $Global:ComboOption = $comboBoxMenu.selectedItem.ToString()
    }

    $handler_comboBoxFolder_SelectedIndexChanged= {
    # Get the Event ID when item is selected
        $Global:ComboOption1 = $comboBoxFolder.selectedItem.ToString()
    }

    $handler_comboBoxConfig_SelectedIndexChanged= {
        # Get the Event ID when item is selected
            $Global:ComboOption2 = $comboBoxConfig.selectedItem.ToString()
    }

    $handler_labImpersonationHelp_Click={
        [Microsoft.VisualBasic.Interaction]::MsgBox("In order to use Impersonation, we must first assign proper ManagementRole to the 'administrative' account that run the different options.
    New-ManagementRoleAssignment -Name:impersonationAssignmentName -Role:ApplicationImpersonation -User:<Account>
 
    More info at: https://msdn.microsoft.com/en-us/library/bb204095(exchg.140).aspx
 
    Press CTRL + C to copy this message to clipboard."
,[Microsoft.VisualBasic.MsgBoxStyle]::Okonly,"Information Message")
    }

    $OnLoadMainWindow_StateCorrection={#Correct the initial state of the form to prevent the .Net maximized form issue
        $PremiseForm.WindowState = $InitialFormWindowState
    }

    #----------------------------------------------
    #region Generated Form Code

    $PremiseForm.Controls.Add($radiobutton1)
    $PremiseForm.Controls.Add($radiobutton2)
    $PremiseForm.Controls.Add($radiobutton3)
    $PremiseForm.Controls.Add($radiobutton4)
    $PremiseForm.Controls.Add($radiobutton5)
    $PremiseForm.Controls.Add($radiobutton6)
    $PremiseForm.Controls.Add($radiobutton7)
    $PremiseForm.Controls.Add($radiobutton8)
    $PremiseForm.Controls.Add($radiobutton9)
    $PremiseForm.Controls.Add($radiobutton10)
    $PremiseForm.Controls.Add($radiobutton11)
    $PremiseForm.Controls.Add($radiobutton12)
    $PremiseForm.Controls.Add($radiobutton13)
    $PremiseForm.Controls.Add($radiobutton14)
    $PremiseForm.Controls.Add($radiobutton15)
    $PremiseForm.Controls.Add($radiobutton16)
    $statusBar = New-Object System.Windows.Forms.StatusStrip
    $statusBar.Name = "statusBar"
    $statusBarLabel = New-Object System.Windows.Forms.ToolStripStatusLabel
    $null = $statusBar.Items.Add($statusBarLabel)
    $statusBarLabel.Text = "Ready..."
    $PremiseForm.Controls.Add($statusBar)
    $PremiseForm.ClientSize = New-Object System.Drawing.Size(850,720)
    $PremiseForm.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $PremiseForm.Name = "form1"
    $PremiseForm.Text = "Managing user: " + $email + ". Choose your Option"
    $PremiseForm.StartPosition = "CenterScreen"
    $PremiseForm.KeyPreview = $True
    $PremiseForm.Add_KeyDown({if ($_.KeyCode -eq "Escape"){$PremiseForm.Close()} })
    #
    # radiobutton1
    #
    $radiobutton1.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton1.Location = New-Object System.Drawing.Point(20,20)
    $radiobutton1.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton1.TabIndex = 1
    $radiobutton1.Text = "1 - List Folders in Root"
    $radioButton1.Checked = $true
    $radiobutton1.UseVisualStyleBackColor = $True
    $radiobutton1.Add_Click({& $ExpandFilters})
    #
    # radiobutton2
    #
    $radiobutton2.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton2.Location = New-Object System.Drawing.Point(20,50)
    $radiobutton2.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton2.TabIndex = 2
    $radiobutton2.Text = "2 - List Folders in Archive Root"
    $radioButton2.Checked = $false
    $radiobutton2.UseVisualStyleBackColor = $True
    $radiobutton2.Add_Click({& $ExpandFilters})
    #
    # radiobutton3
    #
    $radiobutton3.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton3.Location = New-Object System.Drawing.Point(20,80)
    $radiobutton3.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton3.TabIndex = 3
    $radiobutton3.Text = "3 - List Folders in Public Folder Root"
    $radiobutton3.Checked = $false
    $radiobutton3.UseVisualStyleBackColor = $True
    $radiobutton3.Add_Click({& $ExpandFilters})
    #
    # radiobutton4
    #
    $radiobutton4.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton4.Location = New-Object System.Drawing.Point(20,110)
    $radiobutton4.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton4.TabIndex = 4
    $radiobutton4.Text = "4 - List folders in Recoverable Items Root folder"
    $radiobutton4.Checked = $false
    $radiobutton4.UseVisualStyleBackColor = $True
    $radiobutton4.Add_Click({& $ExpandFilters})
    #
    # radiobutton5
    #
    $radiobutton5.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton5.Location = New-Object System.Drawing.Point(20,140)
    $radiobutton5.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton5.Tabindex = 5
    $radiobutton5.Text = "5 - List folders in Recoverable Items folder in Archive"
    $radiobutton5.Checked = $false
    $radiobutton5.UseVisualStyleBackColor = $True
    $radiobutton5.Add_Click({& $ExpandFilters})
    #
    # radiobutton6
    #
    $radiobutton6.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton6.Location = New-Object System.Drawing.Point(20,170)
    $radiobutton6.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton6.TabIndex = 6
    $radiobutton6.Text = "6 - List Items in a desired Folder"
    $radiobutton6.Checked = $false
    $radiobutton6.UseVisualStyleBackColor = $True
    $radiobutton6.Add_Click({& $ExpandFilters})
    #
    # radiobutton7
    #
    $radiobutton7.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton7.Location = New-Object System.Drawing.Point(20,200)
    $radiobutton7.Name = "radiobutton7"
    $radiobutton7.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton7.TabIndex = 7
    $radiobutton7.Text = "7 - Create a custom Folder in Root"
    $radiobutton7.Checked = $false
    $radiobutton7.UseVisualStyleBackColor = $True
    $radiobutton7.Add_Click({& $ExpandFilters})
    #
    # radiobutton8
    #
    $radiobutton8.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton8.Location = New-Object System.Drawing.Point(20,230)
    $radiobutton8.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton8.TabIndex = 8
    $radiobutton8.Text = "8 - Delete a Folder"
    $radiobutton8.Checked = $false
    $radiobutton8.UseVisualStyleBackColor = $True
    $radiobutton8.Add_Click({& $ExpandFilters})
    #
    # radiobutton9
    #
    $radiobutton9.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton9.Location = New-Object System.Drawing.Point(20,260)
    $radiobutton9.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton9.TabIndex = 9
    $radiobutton9.Text = "9 - Get user's Inbox Rules"
    $radiobutton9.Checked = $false
    $radiobutton9.UseVisualStyleBackColor = $True
    $radiobutton9.Add_Click({& $ExpandFilters})
    #
    # radiobutton10
    #
    $radiobutton10.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton10.Location = New-Object System.Drawing.Point(400,20)
    $radiobutton10.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton10.TabIndex = 10
    $radiobutton10.Text = "10 - Get user's OOF Settings"
    $radiobutton10.Checked = $false
    $radiobutton10.UseVisualStyleBackColor = $True
    $radiobutton10.Add_Click({& $ExpandFilters})
    #
    # radiobutton11
    #
    $radiobutton11.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton11.Location = New-Object System.Drawing.Point(400,50)
    $radiobutton11.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton11.TabIndex = 11
    $radiobutton11.Text = "11 - Move items between folders"
    $radiobutton11.Checked = $false
    $radiobutton11.UseVisualStyleBackColor = $True
    $radiobutton11.Add_Click({& $ExpandFilters})
    #
    # radiobutton12
    #
    $radiobutton12.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton12.Location = New-Object System.Drawing.Point(400,80)
    $radiobutton12.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton12.TabIndex = 12
    $radiobutton12.Text = "12 - Delete a subset of items in a folder"
    $radiobutton12.Checked = $false
    $radiobutton12.UseVisualStyleBackColor = $True
    $radiobutton12.Add_Click({& $ExpandFilters})
    #
    # radiobutton13
    #
    $radiobutton13.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton13.Location = New-Object System.Drawing.Point(400,110)
    $radiobutton13.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton13.TabIndex = 13
    $radiobutton13.Text = "13 - Get user's Delegate information"
    $radiobutton13.Checked = $false
    $radiobutton13.UseVisualStyleBackColor = $True
    $radiobutton13.Add_Click({& $ExpandFilters})
    #
    # radiobutton14
    #
    $radiobutton14.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton14.Location = New-Object System.Drawing.Point(400,140)
    $radiobutton14.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton14.TabIndex = 14
    $radiobutton14.Text = "14 - Change sensitivity to items in a folder"
    $radiobutton14.Checked = $false
    $radiobutton14.UseVisualStyleBackColor = $True
    $radiobutton14.Add_Click({& $ExpandFilters})
    #
    # radiobutton15
    #
    $radiobutton15.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton15.Location = New-Object System.Drawing.Point(400,170)
    $radiobutton15.Size = New-Object System.Drawing.Size(300,15)
    $radiobutton15.TabIndex = 15
    $radiobutton15.Text = "15 - Remove OWA configurations"
    $radiobutton15.Checked = $false
    $radiobutton15.UseVisualStyleBackColor = $True
    $radiobutton15.Add_Click({& $ExpandFilters})
    #
    # radiobutton16
    #
    $radiobutton16.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation
    $radiobutton16.Location = New-Object System.Drawing.Point(400,200)
    $radiobutton16.Size = New-Object System.Drawing.Size(175,15)
    $radiobutton16.TabIndex = 16
    $radiobutton16.Text = "16 - Switch to another Mailbox"
    $radiobutton16.Checked = $false
    $radiobutton16.UseVisualStyleBackColor = $True
    $radiobutton16.Add_Click({& $ExpandFilters})
    #
    # Label Impersonation Help
    #
    $labImpersonationHelp.Location = New-Object System.Drawing.Point(380,200)
    $labImpersonationHelp.Size = New-Object System.Drawing.Size(10,20)
    $labImpersonationHelp.Name = "labImpersonation"
    $labImpersonationHelp.ForeColor = "Blue"
    $labImpersonationHelp.Text = "?"
    $labImpersonationHelp.add_Click($handler_labImpersonationHelp_Click)
    $PremiseForm.Controls.Add($labImpersonationHelp)

    #"Go" button
    $Global:buttonGo.Dispose()

    $Global:buttonGo2 = New-Object System.Windows.Forms.Button
    $buttonGo2.DataBindings.DefaultDataSourceUpdateMode = 0
    $buttonGo2.ForeColor = [System.Drawing.Color]::FromArgb(255,0,0,0)
    $buttonGo2.Location = New-Object System.Drawing.Point(700,20)
    $buttonGo2.Size = New-Object System.Drawing.Size(50,25)
    $buttonGo2.TabIndex = 17
    $buttonGo2.Name = "Go"
    $buttonGo2.Text = "Go"
    $buttonGo2.UseVisualStyleBackColor = $True
    $buttonGo2.add_Click({
            if($radiobutton1.Checked){Method1to6}
            elseif($radiobutton2.Checked){Method1to6}
            elseif($radiobutton3.Checked){Method1to6}
            elseif($radiobutton4.Checked){Method1to6}
            elseif($radiobutton5.Checked){Method1to6}
            elseif($radiobutton6.Checked){Method7}
            elseif($radiobutton7.Checked){Method8}
            elseif($radiobutton8.Checked){Method9}
            elseif($radiobutton9.Checked){Method10}
            elseif($radiobutton10.Checked){Method11}
            elseif($radiobutton11.Checked){Method12}
            elseif($radiobutton12.Checked){Method13}
            elseif($radiobutton13.Checked){Method14}
            elseif($radiobutton14.Checked){Method15}
            elseif($radiobutton15.Checked){Method16}
            elseif($radiobutton16.Checked){Method17}
    })
    $PremiseForm.Controls.Add($buttonGo2)

    #"Exit" button
    $buttonExit.DataBindings.DefaultDataSourceUpdateMode = 0
    $buttonExit.ForeColor = [System.Drawing.Color]::FromArgb(255,0,0,0)
    $buttonExit.Location = New-Object System.Drawing.Point(700,50)
    $buttonExit.Size = New-Object System.Drawing.Size(50,25)
    $buttonExit.TabIndex = 17
    $buttonExit.Name = "Exit"
    $buttonExit.Text = "Exit"
    $buttonExit.UseVisualStyleBackColor = $True
    $PremiseForm.Controls.Add($buttonExit)

    #TextBox results
    $txtBoxResults.DataBindings.DefaultDataSourceUpdateMode = 0
    $txtBoxResults.Location = New-Object System.Drawing.Point(5,460)
    $txtBoxResults.Size = New-Object System.Drawing.Size(840,240)
    $txtBoxResults.Name = "TextResults"
    $txtBoxResults.BackColor = [System.Drawing.Color]::White
    $txtBoxResults.BorderStyle = [System.Windows.Forms.BorderStyle]::Fixed3D
    $Font = New-Object System.Drawing.Font("Consolas",8)
    $txtBoxResults.Font = $Font
    $PremiseForm.Controls.Add($txtBoxResults)

    #dataGrid

    $dgResults.Anchor = 15
    $dgResults.DataBindings.DefaultDataSourceUpdateMode = 0
    $dgResults.DataMember = ""
    $dgResults.Location = New-Object System.Drawing.Point(5,460)
    $dgResults.Size = New-Object System.Drawing.Size(840,240)
    $dgResults.Name = "dgResults"
    $dgResults.ReadOnly = $True
    $dgResults.RowHeadersVisible = $False
    $dgResults.Visible = $False
    $dgResults.AllowUserToOrderColumns = $True
    $dgResults.AllowUserToResizeColumns = $True
    $PremiseForm.Controls.Add($dgResults)

    #endregion Generated Form Code

    # Show Form
    #Save the initial state of the form
    $InitialFormWindowState = $PremiseForm.WindowState
    #Init the OnLoad event to correct the initial state of the form
    $PremiseForm.add_Load($OnLoadMainWindow_StateCorrection)
    $PremiseForm.Add_Shown({$PremiseForm.Activate()})
    $PremiseForm.ShowDialog()| Out-Null
    #exit if 'Exit' button is pushed
    if($buttonExit.IsDisposed){return}

    } #End Function

    #Call the Function
    try {
        GenerateForm
    }
    finally {
        Stop-ModuleUpdate -RunspaceData $runspaceData
    }
}

function Unregister-EWsGuiAADAppData {
    <#
    .SYNOPSIS
    Function to unregister ClientID, TenantID and ClientSecret to the EWSGui powershell module.
     
    .DESCRIPTION
    Function to unregister ClientID, TenantID and ClientSecret to the EWSGui powershell module.
     
    .EXAMPLE
    PS C:\> Unregister-EWsGuiAADAppData
 
    The script will unregister these values in the EWSGui module to be used automatically.
    #>

    [CmdletBinding()]
    param (
        # Parameters
    )
    
    begin {

    }
    
    process {
        Write-PSFMessage -Level Important -Message "Unregistering ClientID, TenantID and ClientSecret strings from EWSGui Module."
        Unregister-PSFConfig -Module EWSGui
        remove-PSFConfig -Module ewsgui -Name clientID -Confirm:$false
        remove-PSFConfig -Module ewsgui -Name tenantID -Confirm:$false
        remove-PSFConfig -Module ewsgui -Name ClientSecret -Confirm:$false
    }
    
    end {
        
    }
}

<#
This is an example configuration file
 
By default, it is enough to have a single one of them,
however if you have enough configuration settings to justify having multiple copies of it,
feel totally free to split them into multiple files.
#>


<#
# Example Configuration
Set-PSFConfig -Module 'EWSGui' -Name 'Example.Setting' -Value 10 -Initialize -Validation 'integer' -Handler { } -Description "Example configuration setting. Your module can then use the setting using 'Get-PSFConfigValue'"
#>


Set-PSFConfig -Module 'EWSGui' -Name 'Import.DoDotSource' -Value $false -Initialize -Validation 'bool' -Description "Whether the module files should be dotsourced on import. By default, the files of this module are read as string value and invoked, which is faster but worse on debugging."
Set-PSFConfig -Module 'EWSGui' -Name 'Import.IndividualFiles' -Value $false -Initialize -Validation 'bool' -Description "Whether the module files should be imported individually. During the module build, all module code is compiled into few files, which are imported instead by default. Loading the compiled versions is faster, using the individual files is easier for debugging and testing out adjustments."
Set-PSFConfig -FullName PSFramework.Logging.FileSystem.ModernLog -Value $True -Validation 'bool' -Description "Enables the modern, more powereful version of the filesystem log, including headers and extra columns." -PassThru | Register-PSFConfig

<#
Stored scriptblocks are available in [PsfValidateScript()] attributes.
This makes it easier to centrally provide the same scriptblock multiple times,
without having to maintain it in separate locations.
 
It also prevents lengthy validation scriptblocks from making your parameter block
hard to read.
 
Set-PSFScriptblock -Name 'EWSGui.ScriptBlockName' -Scriptblock {
     
}
#>


<#
# Example:
Register-PSFTeppScriptblock -Name "EWSGui.alcohol" -ScriptBlock { 'Beer','Mead','Whiskey','Wine','Vodka','Rum (3y)', 'Rum (5y)', 'Rum (7y)' }
#>


<#
# Example:
Register-PSFTeppArgumentCompleter -Command Get-Alcohol -Parameter Type -Name EWSGui.alcohol
#>


New-PSFLicense -Product 'EWSGui' -Manufacturer 'agallego' -ProductVersion $script:ModuleVersion -ProductType Module -Name MIT -Version "1.0.0.0" -Date (Get-Date "2021-11-29") -Text @"
Copyright (c) 2021 agallego
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"@

#endregion Load compiled code