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 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:\> Method10 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 10" -Target $email } Function Method11 { <# .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:\> Method11 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 11" -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 Method12 { <# .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:\> Method12 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 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 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:\> Method13 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 13" -Target $email } Function Method14 { <# .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:\> Method14 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 14" -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 Method15 { <# .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:\> Method15 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 15" -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 15" $PremiseForm.Refresh() #Cleaning Variables $SmtpAddress = $null $finderFolder = $null $folderid = $null } } Function Method16 { <# .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:\> Method16 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(595,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 16" -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 Method1to5 { <# .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:\> Method1to5 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-5" -Target $email } Function Method6 { <# .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:\> Method6 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 6" -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 Method7 { <# .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:\> Method7 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 7" -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 Method8 { <# .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:\> Method8 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 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 = "Process finished with warnings/errors" } } Function Method9 { <# .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:\> Method9 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 9" -Target $email #> } 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 $($GalleryModule.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(190,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){Method1to5} elseif($radiobutton2.Checked){Method1to5} elseif($radiobutton3.Checked){Method1to5} elseif($radiobutton4.Checked){Method1to5} elseif($radiobutton5.Checked){Method1to5} elseif($radiobutton6.Checked){Method6} elseif($radiobutton7.Checked){Method7} elseif($radiobutton8.Checked){Method8} elseif($radiobutton9.Checked){Method9} elseif($radiobutton10.Checked){Method10} elseif($radiobutton11.Checked){Method11} elseif($radiobutton12.Checked){Method12} elseif($radiobutton13.Checked){Method13} elseif($radiobutton14.Checked){Method14} elseif($radiobutton15.Checked){Method15} elseif($radiobutton16.Checked){Method16} }) $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 |