Launch-GetMailboxGUI.ps1
<#PSScriptInfo .VERSION 1.0 .GUID b5592ee1-dc40-4e2e-aa14-a819b595ceb4 .AUTHOR sammy .COMPANYNAME .COPYRIGHT .TAGS .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES .PRIVATEDATA #> <# .DESCRIPTION test #> <# .NOTES This is a script to demonstrate the usage of Graphical User Interface (GUI) with PowerShell. This script requires: - PowerShell v3 minium - Exchange Management Tools (or being logged on Exchange Online on the current PowerShell session) These above dependencies are checked when the script launches. .LINK https://github.com/SammyKrosoft/Exchange-Get-Mailboxes-GUI #> $Version = "1.0" <#Version History v1.00 - added PSSCriptInfo for publishing on PSGallery v0.97 - made window bigger - added Copy to Clipboard button for mailboxes list - added ServerName and database info v0.96 - added icon, made window a bit bigger v0.95 - fixed Arbitration mailbox SIR and Quota functions v0.92 - Added Arbitration mailbox check box v0.91 - Added ability to sort each columns in List quota action ... #> #region FUNCTIONS other than Form events Function IsPSV3 { <# .DESCRIPTION Just printing Powershell version and returning "true" if powershell version is Powershell v3 or more recent, and "false" if it's version 2. .OUTPUTS Returns $true or $false .EXAMPLE IsPSVersionV3 #> $PowerShellMajorVersion = $PSVersionTable.PSVersion.Major $msgPowershellMajorVersion = "You're running Powershell v$PowerShellMajorVersion" Write-Host $msgPowershellMajorVersion -BackgroundColor blue -ForegroundColor yellow If($PowerShellMajorVersion -le 2){ Write-Host "Sorry, PowerShell v3 or more is required. Exiting." Return $false Exit } Else { Write-Host "You have PowerShell v3 or later, great !" -BackgroundColor blue -ForegroundColor yellow Return $true } } Function Test-ExchTools(){ <# .SYNOPSIS This small function will just check if you have Exchange tools installed or available on the current PowerShell session. .DESCRIPTION The presence of Exchange tools are checked by trying to execute "Get-ExBanner", one of the basic Exchange cmdlets that runs when the Exchange Management Shell is called. Just use Test-ExchTools in your script to make the script exit if not launched from an Exchange tools PowerShell session... .EXAMPLE Test-ExchTools => will exit the script/program si Exchange tools are not installed #> Try { Get-command Get-MAilbox -ErrorAction Stop $ExchInstalledStatus = $true $Message = "Exchange tools are present !" Write-Host $Message -ForegroundColor Blue -BackgroundColor Red } Catch [System.SystemException] { $ExchInstalledStatus = $false $Message = "Exchange Tools are not present ! This script/tool need these. Exiting..." Write-Host $Message -ForegroundColor red -BackgroundColor Blue # Add-Type -AssemblyName presentationframework, presentationcore # Option #4 - a message, a title, buttons, and an icon # More info : https://msdn.microsoft.com/en-us/library/system.windows.messageboximage.aspx $msg = "You must run this tool from an Exchange-enabled PowerShell console like Exchange Management Console or a PowerShell session where you imported an Exchange session." $Title = "Error - No Exchange Tools available !" $Button = "Ok" $Icon = "Error" [System.Windows.MessageBox]::Show($msg,$Title, $Button, $icon) Exit } Return $ExchInstalledStatus } Function Run-Action{ $SelectedAction = $wpf.comboSelectAction.SelectedItem.Content Switch ($SelectedAction) { #Region Disable Mailbox *********************************************************** "Disable Mailbox" { Write-host "Displaying Info" Write-Host "Listing selected mailbox names:" $SelectedITems = $wpf.GridView.SelectedItems $List = @() $SelectedItems | Foreach{ $List += ("""") + $($_.Alias) + ("""") } $List = $List -join "," $Command = "$List | Disable-Mailbox" WRite-Host "About to execute action on $($SelectedItems.Count) mailboxes..." Write-Host "About to run $Command" } #endregion #End of the Disabled Mailbox region #region List Quotas "List Quotas" { Write-host "Displaying Mailbox SIR and retention settings status" $SelectedITems = $wpf.GridView.SelectedItems Write-host "Displaying Mailbox Single Item Recovery and retention settings status for $($SelectedItems.count) items..." $List = @() $SelectedItems | Foreach { $List += $_.primarySMTPAddress.tostring() } #$List = $List -join "," Function Get-MailboxQuotas { [CmdLetBinding()] Param( [Parameter(Mandatory = $False, Position = 1)][string[]]$List, [Parameter(Mandatory = $False, Position = 2)][switch]$Arbitration ) #Initiating stopwatch to measure the time it takes to retrieve mailboxes $stopwatch = [system.diagnostics.stopwatch]::StartNew() If ($Arbitration){ $QueryMailboxFeaturesStd = $List | get-mailbox -Arbitration | Select DisplayName,Name,ServerName,Database,*quota*,OrganizationalUnit } Else { $QueryMailboxFeaturesStd = $List | get-mailbox | Select DisplayName,Name,ServerName,Database,*quota*,OrganizationalUnit } $QueryMailboxFeatures = @() Foreach ($mailbox in $QueryMailboxFeaturesStd){ $objTemp = $mailbox if ($($objTemp.OrganizationalUnit) -match "prod.outlook.com"){ $CloudMailbox = $True }else{ $CloudMailbox = $false } #<optional> - Removing OrganizationalUnit information ... $ObjTemp = $ObjTemp | Select DisplayName, Database, UseDatabaseQuotaDefaults, ProhibitSendQuota, ProhibitSendReceiveQuota, IssueWarningQuota, RulesQuota, CalendarLoggingQuota, RecoverableItemsQuota, RecoverableItemsWarningQuota, ArchiveQuota, ArchiveWarningQuota if ($CloudMailbox){ $objTemp | add-Member -NotePropertyName DatabaseProhibitSRQuota -NotePropertyValue "Cloud mailbox (no DB Quota info)" $ObjTemp | Add-Member -NotePropertyName DatabaseSendQuota -NotePropertyValue "Cloud mailbox (no DB Quota info)" $ObjTemp | Add-Member -NotePropertyName DatabaseWarningQuota -NotePropertyValue "Cloud mailbox (no DB Quota info)" } Else { $objTemp | add-Member -NotePropertyName DatabaseProhibitSRQuota -NotePropertyValue $((Get-MailboxDatabase $($Mailbox.Database)).ProhibitSendReceiveQuota) $ObjTemp | Add-Member -NotePropertyName DatabaseSendQuota -NotePropertyValue $((Get-MailboxDatabase $($Mailbox.Database)).ProhibitSendQuota) $ObjTemp | Add-Member -NotePropertyName DatabaseWarningQuota -NotePropertyValue $((Get-MailboxDatabase $($Mailbox.Database)).IssueWarningQuota) } $QueryMailboxFeatures += $objTemp } [System.Collections.IENumerable]$MailboxFeatures = @($QueryMailboxFeatures) Write-host $($MailboxFeatures | ft | out-string) #Stopping stopwatch $stopwatch.Stop() $msg = "`n`nInstruction took $([math]::round($($StopWatch.Elapsed.TotalSeconds),2)) seconds ..." Write-Host $msg $msg = $null $StopWatch = $null #region Get-MailboxFeaturesView Form definition # Load a WPF GUI from a XAML file build with Visual Studio Add-Type -AssemblyName presentationframework, presentationcore $wpf = @{ } # NOTE: Either load from a XAML file or paste the XAML file content in a "Here String" #$inputXML = Get-Content -Path ".\WPFGUIinTenLines\MainWindow.xaml" $inputXML = @" <Window x:Name="frmMbxQuotaStatus" x:Class="Get_CASMAilboxFeaturesWPF.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Get_CASMAilboxFeaturesWPF" mc:Ignorable="d" Title="Mailboxes Quotas settings status" Height="450" Width="872.145" ResizeMode="NoResize"> <Grid> <DataGrid x:Name="DataGrid" HorizontalAlignment="Left" Height="326" Margin="10,10,-59,0" VerticalAlignment="Top" Width="844" IsReadOnly="True"/> <Button x:Name="btnClose" Content="Close" HorizontalAlignment="Left" Margin="748,352,0,0" VerticalAlignment="Top" Width="106" Height="46"/> <Button x:Name="btnClipboard" Content="Copy to clipboard" HorizontalAlignment="Left" Margin="10,352,0,0" VerticalAlignment="Top" Width="174" Height="46"/> </Grid> </Window> "@ $inputXMLClean = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace 'x:Class=".*?"','' -replace 'd:DesignHeight="\d*?"','' -replace 'd:DesignWidth="\d*?"','' [xml]$xaml = $inputXMLClean $reader = New-Object System.Xml.XmlNodeReader $xaml $tempform = [Windows.Markup.XamlReader]::Load($reader) $namedNodes = $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") $namedNodes | ForEach-Object {$wpf.Add($_.Name, $tempform.FindName($_.Name))} #Get the form name to be used as parameter in functions external to form... $FormName = $NamedNodes[0].Name #Define events functions #region Load, Draw (render) and closing form events #Things to load when the WPF form is loaded aka in memory $wpf.$FormName.Add_Loaded({ #Update-Cmd $wpf.DataGrid.ItemsSource = $MailboxFeatures $wpf.DataGrid.Columns | Foreach { $_.CanUserSort = $true } }) #Things to load when the WPF form is rendered aka drawn on screen $wpf.$FormName.Add_ContentRendered({ #Update-Cmd }) $wpf.$FormName.add_Closing({ $msg = "Closed the MBX SIR and retention settings status list window" write-host $msg }) $wpf.btnClipboard.add_Click({ $CSVClip = $mailboxFeatures | ConvertTo-CSV -NoTypeInformation $CSVClip | clip.exe $title = "Copied !" $msg = "Data copied to the clipboard ! `n`rUse CTRL+V on Notepad or on Excel !" [System.Windows.MessageBox]::Show($msg,$title, "OK","Asterisk") }) $wpf.btnClose.add_Click({ $wpf.$FormName.Close() }) #endregion Load, Draw and closing form events #End of load, draw and closing form events #HINT: to update progress bar and/or label during WPF Form treatment, add the following: # ... to re-draw the form and then show updated controls in realtime ... $wpf.$FormName.Dispatcher.Invoke("Render",[action][scriptblock]{}) # Load the form: # Older way >>>>> $wpf.MyFormName.ShowDialog() | Out-Null >>>>> generates crash if run multiple times # Newer way >>>>> avoiding crashes after a couple of launches in PowerShell... # USing method from https://gist.github.com/altrive/6227237 to avoid crashing Powershell after we re-run the script after some inactivity time or if we run it several times consecutively... $async = $wpf.$FormName.Dispatcher.InvokeAsync({ $wpf.$FormName.ShowDialog() | Out-Null }) $async.Wait() | Out-Null #endregion # end of Form definition for Get-MailboxFeaturesView } if ($wpf.chkArbitrationOnly.IsChecked){ Get-MailboxQuotas $List -Arbitration } Else { Get-MailboxQuotas $List } } #endregion #End of the List Quotas region #region Single Item Recovery Status "List Single Item Recovery status" { Write-host "Displaying Mailbox SIR and retention settings status" $SelectedITems = $wpf.GridView.SelectedItems Write-host "Displaying Mailbox Single Item Recovery and retention settings status for $($SelectedItems.count) items..." $List = @() $SelectedItems | Foreach { $List += $_.primarySMTPAddress.tostring() } #$List = $List -join "," Function Get-MailboxSIRView { [CmdLetBinding()] Param( [Parameter(Mandatory = $False, Position = 1)][string[]]$List, [Parameter(Mandatory = $False, Position = 2)][switch]$Arbitration ) #Initiating stopwatch to measure the time it takes to retrieve mailboxes $stopwatch = [system.diagnostics.stopwatch]::StartNew() If ($Arbitration){ $QueryMailboxFeatures = $List | get-mailbox -Arbitration | Select DisplayName,Name,*item*,OrganizationalUnit } Else { $QueryMailboxFeatures = $List | Get-Mailbox | Select DisplayName,Name, *item*, OrganizationalUnit } [System.Collections.IENumerable]$MailboxFeatures = @($QueryMailboxFeatures) Write-host $($MailboxFeatures | ft | out-string) #Stopping stopwatch $stopwatch.Stop() $msg = "`n`nInstruction took $([math]::round($($StopWatch.Elapsed.TotalSeconds),2)) seconds ..." Write-Host $msg $msg = $null $StopWatch = $null #region Get-MailboxFeaturesView Form definition # Load a WPF GUI from a XAML file build with Visual Studio Add-Type -AssemblyName presentationframework, presentationcore $wpf = @{ } # NOTE: Either load from a XAML file or paste the XAML file content in a "Here String" #$inputXML = Get-Content -Path ".\WPFGUIinTenLines\MainWindow.xaml" $inputXML = @" <Window x:Name="frmMbxSIRStatus" x:Class="Get_CASMAilboxFeaturesWPF.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Get_CASMAilboxFeaturesWPF" mc:Ignorable="d" Title="Mailboxes Single Item Recovery and Retention settings status" Height="450" Width="872.145" ResizeMode="NoResize"> <Grid> <DataGrid x:Name="DataGridCASMbx" HorizontalAlignment="Left" Height="326" Margin="10,10,-59,0" VerticalAlignment="Top" Width="844" IsReadOnly="True"/> <Button x:Name="btnClose" Content="Close" HorizontalAlignment="Left" Margin="748,352,0,0" VerticalAlignment="Top" Width="106" Height="46"/> <Button x:Name="btnClipboard" Content="Copy to clipboard" HorizontalAlignment="Left" Margin="10,352,0,0" VerticalAlignment="Top" Width="174" Height="46"/> </Grid> </Window> "@ $inputXMLClean = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace 'x:Class=".*?"','' -replace 'd:DesignHeight="\d*?"','' -replace 'd:DesignWidth="\d*?"','' [xml]$xaml = $inputXMLClean $reader = New-Object System.Xml.XmlNodeReader $xaml $tempform = [Windows.Markup.XamlReader]::Load($reader) $namedNodes = $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") $namedNodes | ForEach-Object {$wpf.Add($_.Name, $tempform.FindName($_.Name))} #Get the form name to be used as parameter in functions external to form... $FormName = $NamedNodes[0].Name #Define events functions #region Load, Draw (render) and closing form events #Things to load when the WPF form is loaded aka in memory $wpf.$FormName.Add_Loaded({ #Update-Cmd $wpf.DataGridCASMbx.ItemsSource = $MailboxFeatures }) #Things to load when the WPF form is rendered aka drawn on screen $wpf.$FormName.Add_ContentRendered({ #Update-Cmd }) $wpf.$FormName.add_Closing({ $msg = "Closed the MBX SIR and retention settings status list window" write-host $msg }) $wpf.btnClipboard.add_Click({ $CSVClip = $mailboxFeatures | ConvertTo-CSV -NoTypeInformation $CSVClip | clip.exe $title = "Copied !" $msg = "Data copied to the clipboard ! `n`rUse CTRL+V on Notepad or on Excel !" [System.Windows.MessageBox]::Show($msg,$title, "OK","Asterisk") }) $wpf.btnClose.add_Click({ $wpf.$FormName.Close() }) #endregion Load, Draw and closing form events #End of load, draw and closing form events #HINT: to update progress bar and/or label during WPF Form treatment, add the following: # ... to re-draw the form and then show updated controls in realtime ... $wpf.$FormName.Dispatcher.Invoke("Render",[action][scriptblock]{}) # Load the form: # Older way >>>>> $wpf.MyFormName.ShowDialog() | Out-Null >>>>> generates crash if run multiple times # Newer way >>>>> avoiding crashes after a couple of launches in PowerShell... # USing method from https://gist.github.com/altrive/6227237 to avoid crashing Powershell after we re-run the script after some inactivity time or if we run it several times consecutively... $async = $wpf.$FormName.Dispatcher.InvokeAsync({ $wpf.$FormName.ShowDialog() | Out-Null }) $async.Wait() | Out-Null #endregion # end of Form definition for Get-MailboxFeaturesView } If ($wpf.chkArbitrationOnly.IsChecked){ Get-MailboxSIRView $List -Arbitration } Else { Get-MailboxSIRView $List } } #endregion #End of the Single Item Recovery status region #region List Mailbox Features "List Mailbox Features" { if ($wpf.chkArbitrationOnly.IsChecked){ # Option #4 - a message, a title, buttons, and an icon # More info : https://msdn.microsoft.com/en-us/library/system.windows.messageboximage.aspx $msg = "Arbitration mailboxes is checked - cannot get mailbox features for Arbitration mailboxes" $Title = "Error - Arbitration mailboxes don't get features" $Button = "Ok" $Icon = "Error" [System.Windows.MessageBox]::Show($msg,$Title, $Button, $icon) Return } Write-host "Displaying Mailbox Features" $SelectedITems = $wpf.GridView.SelectedItems Write-host "Displaying Mailbox Features for $($SelectedItems.count) items..." $List = @() $SelectedItems | Foreach { $List += $_.primarySMTPAddress.tostring() } #$List = $List -join "," Function Get-MailboxFeaturesView { [CmdLetBinding()] Param( [Parameter(Mandatory = $False, Position = 1)][string[]]$List ) #Initiating stopwatch to measure the time it takes to retrieve mailboxes $stopwatch = [system.diagnostics.stopwatch]::StartNew() $QueryMailboxFeatures = $List | Get-CASMAilbox | Select DisplayName, *enabled, *MAPIblock* [System.Collections.IENumerable]$MailboxFeatures = @($QueryMailboxFeatures) Write-host $($MailboxFeatures | ft DisplayName, ActiveSyncEnabled,OWAEnabled,ECPEnabled,MAPIEnabled,MAPIBlockOutlookRpcHttp,MapiHttpEnabled -a | out-string) #Stopping stopwatch $stopwatch.Stop() $msg = "`n`nInstruction took $([math]::round($($StopWatch.Elapsed.TotalSeconds),2)) seconds..." Write-Host $msg $msg = $null $StopWatch = $null #region Get-MailboxFeaturesView Form definition # Load a WPF GUI from a XAML file build with Visual Studio Add-Type -AssemblyName presentationframework, presentationcore $wpf = @{ } # NOTE: Either load from a XAML file or paste the XAML file content in a "Here String" #$inputXML = Get-Content -Path ".\WPFGUIinTenLines\MainWindow.xaml" $inputXML = @" <Window x:Name="frmCASMBOXProps" x:Class="Get_CASMAilboxFeaturesWPF.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Get_CASMAilboxFeaturesWPF" mc:Ignorable="d" Title="Mailbox features enabled and blocked status" Height="450" Width="872.145" ResizeMode="NoResize"> <Grid> <DataGrid x:Name="DataGridCASMbx" HorizontalAlignment="Left" Height="326" Margin="10,10,-59,0" VerticalAlignment="Top" Width="844" IsReadOnly="True"/> <Button x:Name="btnClose" Content="Close" HorizontalAlignment="Left" Margin="748,352,0,0" VerticalAlignment="Top" Width="106" Height="46"/> <Button x:Name="btnClipboard" Content="Copy to clipboard" HorizontalAlignment="Left" Margin="10,352,0,0" VerticalAlignment="Top" Width="174" Height="46"/> </Grid> </Window> "@ $inputXMLClean = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace 'x:Class=".*?"','' -replace 'd:DesignHeight="\d*?"','' -replace 'd:DesignWidth="\d*?"','' [xml]$xaml = $inputXMLClean $reader = New-Object System.Xml.XmlNodeReader $xaml $tempform = [Windows.Markup.XamlReader]::Load($reader) $namedNodes = $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") $namedNodes | ForEach-Object {$wpf.Add($_.Name, $tempform.FindName($_.Name))} #Get the form name to be used as parameter in functions external to form... $FormName = $NamedNodes[0].Name #Define events functions #region Load, Draw (render) and closing form events #Things to load when the WPF form is loaded aka in memory $wpf.$FormName.Add_Loaded({ #Update-Cmd $wpf.DataGridCASMbx.ItemsSource = $MailboxFeatures }) #Things to load when the WPF form is rendered aka drawn on screen $wpf.$FormName.Add_ContentRendered({ #Update-Cmd }) $wpf.$FormName.add_Closing({ $msg = "Closed the MBX features list window" write-host $msg }) $wpf.btnClipboard.add_Click({ $CSVClip = $mailboxFeatures | ConvertTo-CSV -NoTypeInformation $CSVClip | clip.exe $title = "Copied !" $msg = "Data copied to the clipboard ! `n`rUse CTRL+V on Notepad or on Excel !" [System.Windows.MessageBox]::Show($msg,$title, "OK","Asterisk") }) $wpf.btnClose.add_Click({ $wpf.$FormName.Close() }) #endregion Load, Draw and closing form events #End of load, draw and closing form events #HINT: to update progress bar and/or label during WPF Form treatment, add the following: # ... to re-draw the form and then show updated controls in realtime ... $wpf.$FormName.Dispatcher.Invoke("Render",[action][scriptblock]{}) # Load the form: # Older way >>>>> $wpf.MyFormName.ShowDialog() | Out-Null >>>>> generates crash if run multiple times # Newer way >>>>> avoiding crashes after a couple of launches in PowerShell... # USing method from https://gist.github.com/altrive/6227237 to avoid crashing Powershell after we re-run the script after some inactivity time or if we run it several times consecutively... $async = $wpf.$FormName.Dispatcher.InvokeAsync({ $wpf.$FormName.ShowDialog() | Out-Null }) $async.Wait() | Out-Null #endregion # end of Form definition for Get-MailboxFeaturesView } Get-MailboxFeaturesView $List } #endregion #End of the List Mailbox Features region } } Function Update-Label ($msg) { $wpf.lblStatus.Content = $msg $Wpf.$FormName.Dispatcher.Invoke("Render",[action][scriptblock]{}) } Function Working-Label { # Trick to enable a Label to update during work : # Follow with "Dispatcher.Invoke("Render",[action][scriptblobk]{})" or [action][scriptblock]::create({}) $wpf.$FormName.IsEnabled = $False $wpf.lblStatus.Content = "Working ..." $wpf.lblStatus.ForeGround = [System.Windows.Media.Brushes]::Red $wpf.lblStatus.BackGround = [System.Windows.Media.Brushes]::Blue $Wpf.$FormName.Dispatcher.Invoke("Render",[action][scriptblock]{}) } Function Ready-Label{ $wpf.$FormName.IsEnabled = $True $wpf.lblStatus.Content = "Ready !" $wpf.lblStatus.ForeGround = [System.Windows.Media.Brushes]::Green $wpf.lblStatus.BackGround = [System.Windows.Media.Brushes]::Yellow $Wpf.$FormName.Dispatcher.Invoke("Render",[action][scriptblock]{}) } Function Update-MainCommandLine { If ($wpf.chkArbitrationOnly.IsChecked){ $commandLine = "Get-Mailbox -ResultSize Unlimited -Arbitration -ErrorAction Stop" } Else { If ($wpf.txtMailboxString.text -eq ""){ $SearchSubstring = ("*") } Else { $SearchSubstring = ("*") + ($wpf.txtMailboxString.text) + ("*") } If ($wpf.chkUnlimited.IsChecked){ $ResultSize = "Unlimited" } Else { $ResultSize = $wpf.txtResultSize.Text } $chkIncludeDiscovery = $false If ($chkIncludeDiscovery){ $commandLine = "Get-Mailbox -ResultSize $ResultSize -Identity $SearchSubstring | Select Name,Alias,DisplayName,primarySMTPAddress,ServerName,Database" } Else { $commandLine = "Get-Mailbox -ResultSize $ResultSize -Identity $SearchSubstring -Filter {RecipientTypeDetails -ne `"DiscoveryMailbox`"} | Select Name,Alias,DisplayName,primarySMTPAddress,ServerName,Database" } } $wpf.txtMainCommand.Text = $CommandLine } $lblabout_Click = { $Language = "EN" switch ($Language) { "EN" { $systemst = "QXV0aG9yOiBTYW0gRHJleQ0Kc2FtZHJleUBtaWNyb3NvZnQuY29tDQpzYW1teUBob3RtYWlsLmZyDQpNaWNyb3NvZnQgRW` 5naW5lZXIgc2luY2UgT2N0IDE5OTkNCjE5OTktMjAwMDogUHJlc2FsZXMgRW5naW5lZXIgKEZyYW5jZSkNCjIwMDAtMjAwMzogU3VwcG9yd` CBFbmdpbmVlciAoRnJhbmNlKQ0KMjAwMy0yMDA2OiB2ZXJ5IGZpcnN0IFBGRSBpbiBGcmFuY2UNCjIwMDYtMjAwOTogTUNTIENvbnN1bHRhb` nQgKEZyYW5jZSkNCjIwMDktMjAxMDogVEFNIChGcmFuY2UpDQoyMDEwLW5vdyA6IENvbnN1bHRhbnQgKENhbmFkYSkNCk11c2ljaWFuLCBjb` 21wb3NlciAoS2V5Ym9hcmQsIEd1aXRhcikNClBsYW5lIHBpbG90IHNpbmNlIDE5OTUNCkZvciBTaGFyZWQgU2VydmljZXMgQ2FuYWRh" } "FR" { $systemst = "QXV0ZXVyOiBTYW0gRHJleQ0Kc2FtZHJleUBtaWNyb3NvZnQuY29tDQpzYW1teUBob3RtYWlsLmZyDQpJbmfDqW5pZXVyIGNo` ZXogTWljcm9zb2Z0IGRlcHVpcyBPY3QgMTk5OQ0KMTk5OS0yMDAwOiBJbmfDqW5pZXVyIEF2YW50LVZlbnRlIChGcmFuY2UpDQoyMDAwLTIwMD` M6IFNww6ljaWFsaXN0ZSBUZWNobmlxdWUgKEZyYW5jZSkNCjIwMDMtMjAwNjogUHJlbWllciBQRkUgZW4gRnJhbmNlDQoyMDA2LTIwMDk6IENv` bnN1bHRhbnQgTUNTIChGcmFuY2UpDQoyMDA5LTIwMTA6IFJlc3BvbnNhYmxlIFRlY2huaXF1ZSBkZSBDb21wdGUgKEZyYW5jZSkNCjIwMTAtMjA` xNiA6IENvbnN1bHRhbnQgKENhbmFkYSkNCk11c2ljaWVuLCBjb21wb3NpdGV1ciAoQ2xhdmllciwgR3VpdGFyZSkNCkJyZXZldCBkZSBQaWxvdGU` gUHJpdsOpIGRlcHVpcyAxOTk1DQpQb3VyIFNlcnZpY2VzIFBhcnRhZ8OpcyBDYW5hZGE=" } } $systemst = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($systemst)) # Option #4 - a message, a title, buttons, and an icon # More info : https://msdn.microsoft.com/en-us/library/system.windows.messageboximage.aspx $msg = $systemst $Title = $wpf.$FormName.Title $Button = "Ok" $Icon = "Information" [System.Windows.MessageBox]::Show($msg,$Title, $Button, $icon) } Function Get-Mailboxes { If ($wpf.chkUnlimited.IsChecked){ Write-host "Unlimited specified ... ignoring Resultsize number..." } Else { If ($([int]$wpf.txtResultSize.Text) -gt 1000) {Write-Host "$($wpf.txtResultSize.Text) is greater than 1000 ..."} Else {write-host "$($wpf.txtResultSize.Text) is less than 1000"} } If ($([int]$wpf.txtResultSize.Text) -gt 1000 -or $wpf.chkUnlimited.IsChecked){ # Option #4 - a message, a title, buttons, and an icon # More info : https://msdn.microsoft.com/en-us/library/system.windows.messageboximage.aspx if ($wpf.chkUnlimited.IsChecked) { $Specified = $wpf.chkUnlimited.Content } Else { $Specified = "$($wpf.txtResultSize.Text), which is more than 1000" } $msg = "WARNING: You specified -> $Specified <- for the Resultsize, mailbox collection can take a LOT of time, Continue ? (Y/N)" $Title = "Question..." $Button = "YesNo" $Icon = "Question" $Answer = [System.Windows.MessageBox]::Show($msg,$Title, $Button, $icon) If($Answer -eq "No"){Return} } Try { #Initiating stopwatch to measure the time it takes to retrieve mailboxes $stopwatch = [system.diagnostics.stopwatch]::StartNew() #Getting the command line from the text box where it's generated $commandLine = $wpf.txtMainCommand.text #Invoking the command line and storing in a variable $Mailboxes = invoke-expression $CommandLine $NewMailboxesObj = @() Foreach ($objTemp in $Mailboxes){ If ($($objTemp.OrganizationalUnit) -match "prod.outlook.com"){ $objtemp | Add-Member -NotePropertyName Location -NotePropertyValue "Cloud" } Else { $objtemp | Add-Member -NotePropertyName Location -NotePropertyValue "On-prem" } $NewMailboxesObj += $objtemp } $Mailboxes = $NewMailboxesObj | Select Name,Alias,DisplayName,primarySMTPAddress, RecipientTypeDetails,Location,ServerName,Database #Stopping stopwatch $stopwatch.Stop() $msg = "`n`nInstruction took $([math]::round($($StopWatch.Elapsed.TotalSeconds),2)) seconds to retrieve $($Mailboxes.count) mailboxes..." Write-Host $msg $msg = $null $StopWatch = $null #Populating the GridView [System.Collections.IENumerable]$Results = @($Mailboxes) $wpf.GridView.ItemsSource = $Results $wpf.GridView.Columns | Foreach { $_.CanUserSort = $true } $wpf.lblNbItemsInGrid.Content = $($Results.Count) } Catch { $Mailboxes = $null $wpf.GridView.ItemsSource = $null write-host "ZERO MAILBOXES" $wpf.lblNbItemsInGrid.Content = 0 } } #endregion #======================================================== #region WPF form definition and load controls #======================================================== # Load a WPF GUI from a XAML file build with Visual Studio Add-Type -AssemblyName presentationframework, presentationcore $wpf = @{} # NOTE: Either load from a XAML file or paste the XAML file content in a "Here String" # $inputXML = Get-Content -Path "C:\Users\Kamehameha\Documents\GitHub\PowerShell\Get-EventsFromEventLog\VisualStudio2017WPFDesign\Launch-EventsCollector-WPF\Launch-EventsCollector-WPF\MainWindow.xaml" $inputXML = @" <Window x:Name="WForm" x:Class="GridView_WPF.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:GridView_WPF" mc:Ignorable="d" Title="Search Mailboxes" Height="722.39" Width="1026.5" ResizeMode="NoResize"> <Grid> <DataGrid x:Name="GridView" HorizontalAlignment="Left" Height="425" Margin="353,10,0,0" VerticalAlignment="Top" Width="641"/> <TextBox x:Name="txtMailboxString" HorizontalAlignment="Left" Height="23" Margin="10,67,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="338"/> <Label Content="Search for mailbox (substring of alias, e-mail address, 
display name, ...)" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,11,0,0" Height="51" Width="302"/> <Button x:Name="btnRun" Content="Search" HorizontalAlignment="Left" Margin="10,95,0,0" VerticalAlignment="Top" Width="75" Height="32"> <Button.Effect> <DropShadowEffect/> </Button.Effect> </Button> <Label x:Name="lblStatus" Content="Ready !" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,658,0,0" Width="1010" FontStyle="Italic" FontWeight="Bold"> </Label> <Button x:Name="btnAction" Content="Run on selected" Margin="360,596,0,0" IsEnabled="False" HorizontalAlignment="Left" VerticalAlignment="Top"> <Button.Effect> <DropShadowEffect/> </Button.Effect> </Button> <ComboBox x:Name="comboSelectAction" HorizontalAlignment="Left" Margin="360,534,0,0" VerticalAlignment="Top" Height="30" SelectedIndex="0" IsEnabled="False" TextOptions.TextFormattingMode="Display"> <ComboBox.Effect> <DropShadowEffect/> </ComboBox.Effect> <ComboBoxItem Content="List Mailbox Features"/> <ComboBoxItem Content="List Single Item Recovery status"/> <ComboBoxItem Content="List Quotas"/> <ComboBoxItem Content="Disable Mailbox"/> </ComboBox> <Label x:Name="lblNbItemsInGrid" Content="0" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="506,440,0,0" Width="66"/> <Label Content="Number of Items in Grid:" HorizontalAlignment="Left" Margin="353,440,0,0" VerticalAlignment="Top" Width="148"/> <Label Content="Selected:" HorizontalAlignment="Left" Margin="353,471,0,0" VerticalAlignment="Top"/> <Label x:Name="lblNumberItemsSelected" Content="0" HorizontalAlignment="Left" Margin="460,471,0,0" VerticalAlignment="Top" Width="67"/> <TextBox x:Name="txtResultSize" HorizontalAlignment="Left" Height="23" Margin="224,98,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="124" Text="100"/> <TextBlock HorizontalAlignment="Left" Margin="95,95,0,0" TextWrapping="Wrap" Text="ResultSize (aka Nb of mailboxes to display):" VerticalAlignment="Top" Width="124"/> <Label Content="Status:" HorizontalAlignment="Left" Margin="10,627,0,0" VerticalAlignment="Top"/> <TextBox x:Name="txtMainCommand" HorizontalAlignment="Left" Height="132" Margin="10,200,0,0" TextWrapping="Wrap" Text="Get-Mailbox command to be run..." VerticalAlignment="Top" Width="338" IsReadOnly="True"/> <Rectangle HorizontalAlignment="Left" Height="26" Margin="353,440,0,0" VerticalAlignment="Top" Width="232"> <Rectangle.Stroke> <SolidColorBrush Color="{DynamicResource {x:Static SystemColors.ActiveBorderColorKey}}"/> </Rectangle.Stroke> </Rectangle> <Rectangle HorizontalAlignment="Left" Height="26" Margin="353,471,0,0" VerticalAlignment="Top" Width="174"> <Rectangle.Stroke> <SolidColorBrush Color="{DynamicResource {x:Static SystemColors.ActiveBorderColorKey}}"/> </Rectangle.Stroke> </Rectangle> <Label Content="The command run when clicking on the Search button is:" HorizontalAlignment="Left" Margin="10,174,0,0" VerticalAlignment="Top" Width="338" FontStyle="Italic"/> <CheckBox x:Name="chkUnlimited" Content="Unlimited" HorizontalAlignment="Left" Margin="223,126,0,0" VerticalAlignment="Top"/> <Label x:Name="lblAbout" Content="." HorizontalAlignment="Left" Margin="999,0,0,0" VerticalAlignment="Top" Height="22" Width="21"/> <CheckBox x:Name="chkArbitrationOnly" Content="Arbitration only" HorizontalAlignment="Left" Margin="10,149,0,0" VerticalAlignment="Top"/> <Button x:Name="btnClipboard" Content="Copy all above items to clipboard" HorizontalAlignment="Left" Margin="590,442,0,0" VerticalAlignment="Top" Width="202" IsEnabled="False" Height="22"> <Button.Effect> <DropShadowEffect/> </Button.Effect> </Button> <Label Content="#1 - Choose what you wish to see about the selected" HorizontalAlignment="Left" Margin="353,508,0,0" VerticalAlignment="Top"/> <Label Content="#2 - Run the above selected action on selected items" HorizontalAlignment="Left" Margin="353,570,0,0" VerticalAlignment="Top"/> <Border BorderBrush="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}" BorderThickness="1" HorizontalAlignment="Left" Height="126" Margin="353,508,0,0" VerticalAlignment="Top" Width="304"/> </Grid> </Window> "@ $inputXMLClean = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace 'x:Class=".*?"','' -replace 'd:DesignHeight="\d*?"','' -replace 'd:DesignWidth="\d*?"','' [xml]$xaml = $inputXMLClean $reader = New-Object System.Xml.XmlNodeReader $xaml $tempform = [Windows.Markup.XamlReader]::Load($reader) $namedNodes = $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") $namedNodes | ForEach-Object {$wpf.Add($_.Name, $tempform.FindName($_.Name))} #Get the form name to be used as parameter in functions external to form... $FormName = $NamedNodes[0].Name #Cloud icon #$Base64icon = "/9j/4AAQSkZJRgABAQEAYABgAAD/4QBmRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAAExAAIAAAAQAAAATgAAAAAAAABgAAAAAQAAAGAAAAABcGFpbnQubmV0IDQuMS40AP/bAEMAAgEBAgEBAgICAgICAgIDBQMDAwMDBgQEAwUHBgcHBwYHBwgJCwkICAoIBwcKDQoKCwwMDAwHCQ4PDQwOCwwMDP/bAEMBAgICAwMDBgMDBgwIBwgMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDP/AABEIACAAIAMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AP3A/aW/aV8I/skfB3VPHXjjUv7N0LSgoYonmTXMrHCQxJ1eRjwB06kkKCR+VH/BRv8A4L32f7TX7Pem+DfgXH418P8AiLxVqD2mrm4tRBqEVqoUJFA0EkgLTs+Mo24CJ1IG8E73/B0p8X1bTvhP4Fs9TtpB59/rGp2Mc6tLE6JBHbPJGDlQVludpYDPzY6Gvz8+BHjm8/Zc/Zu1b4kaDMbHx14s1iTwp4e1ROLjRbeCCKfUriBv4J2F1ZQrIuGRJZ8EEgj964B4JwTy2jnOJg6laUvci3aOjaV1Z3Ss5t9krJ7P8v4o4kxKxlTL6MuWnGPvSSu9Um7aruorzer7eifsH/tWfFj/AIJcftQ+G5PGWn+NPDPhHxFdRrr2ia7Z3FpHe2kjBXukimUZkj3b1dRkldpO1iD/AEZo4kQMpDKwyCOhFfzHfCv9t2XXPDep+Evjd/wlnxU8C3bDULS0m1phqOmahGQyS211MJGhSVd8UygEMkpYDeiEfuN/wSs/4KWeEv8AgoJ8Lb230fR7zwtr3gxILW+0e7vReMsDKVhmjn2oZVbYwJKqwZeRgqW5/FjI8VNQzJ0LOOlScbcrTtyO1+a97p3T6a7G3AuZ0Y82DVW6lrGL3W/Mu1tmrPvpufhH4Zmuv25v26/tni/ULzZ408QTajrVyDumt7JS884jzwDHbxuqL0GxRwBXP/tJ/tO6t+0Vq2n27WGl+HfCPhvzYPDfh7TLVIbTRbdyuUBUB5ZG2IXlkLO7DJPYfpRe/wDBDH4lfCL/AIKOr4o8H2Ol6x8K9W1O6dp1v4obnSLO+jlhmjaGQqXMKzvt2bt6ovRiVH5Z/GP4N+JPgH8S9Y8I+LNKutH13Q7l7a5t54yvKkgOpI+ZGxlXHDKQQSDX6xkOcZXmWIjLBzjJQpwcYpq8L8ylp0aSinpdLTZu/wALmmAxuDpNYiLTlOV30lazWvVXu13focvX2R/wQ5/bP0P9jP8AbRjuvFC3Q0Hxtp//AAjU08TDZp80tzbvFcyA9Y1MbK2OQshYZxg/HGxvQ/lXT/Bb4Ua58cPiz4d8I+HbO5vNa8QX8NlaxwoWZWdgN5x0VRlix4UKScAE172dYHD43AVcLinanKLu9rLe/wAtzzctxNXD4qnWoK8k1Zd/L57H/9k=" #Exchange Management Shell icon $Base64Icon = "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNBNAaMQAAAT/SURBVEhLnZV5TNNnGMfBYwOnmLA5TcTFRDz2xw4TDE6NDvHgCttUnM5MZIkynTcCRbEgyKmIZhDEDpkOSGBTBrI5dYCb8OtBixQo0BZb2tKWaltBBJSj3z1lYOSwjr3JNynh7ffzvs/zfZ/ajV4A7Ivq211ZRWrX5Wn1rk4sxnXpOZFb/G0NNmU3YFGcEC5RjPPQ9tcvDqN2TvxTFfwZpzF4Lrsq2InF27/352asv1iHBXEiOIQxsD/Ghf1RBnYhDN4IZeB0ZAKA5DuaQrfUGrwXK8S0cB4mkYk9yWo2nqwAu4kAEu9obBqO1v8EVI5rNp6GARn3tNodVxr1X10dqx2k038o9NnlSocRAPsQLqbQ5xlhXMxlC/Fh8n14fF8Lh1DeGEBQnswy+RiDSa/QVBLtcxwFYFCv68Tzfgt6+wfQNzCAZ339mBtVNQZQLjdLV1wQt71JIVgQK0K2QI8bEiPpEXw4Eky1Hmo8gNrcjfaePvxUZUBSWSsSSzWYGcEfA9hf0Bzsx5Fkr6EbXhe3IV/UhiyeHgpjFw4VKih9NgAtph6suFBLf1M8h4xHA3bnyS2L46tBEUfkb0rMYfMx66QAJfXG1wOMT3uRTCffnS/HslTxCMgwYFeuzLL8vBh7C2SYzRYM7pkXXYUymRkBV5qoBzYAFgvQ3TuAJ8/6cOqmarBpowGRJUrLuyd4mBXJR2COFNt+bIBrjBAHf5HD+QSf3hP31YBOMr4jNeFmgwl76Bb24wDCC5XzfS9JBo0cQyvBYXTI4urwDplbfWwC/u1B3QvTlzUM+LZAZlmWch9uKdX4hMroSOPkYoUGOVV6zKepMNkW4GFnLyJuKOGVKcFKSok178MAR4rfknX7jm7PUlnej2lCxDUtlidK4RIhxgen6nD5rgHbM2VwCRdhyaqvD4wCcKEyd6F/wAJT13O6STeqNU/oodFphgDzjtdjS3oPNqc/xaGcDmw9b4JPQhs2xrZiQ0wL/E8/gHe0FB60LyC+EWNu8MXlJrBKWpB2T4vCWiPuykwjAEtj1fA/34Odl7pQrXyKmAIj/BP08I7VwPuUAhvYUqw7UYe1rBocyJCPBFg1hcwcaKq+FcHDTErJ25Rt64Qd/B9pddIj+Kd24vPUDnBKH0Pa2ol9ma3wIfONUXIylwyafxoqRNYt/ViALU0Pq4LnGSP8Ujrgd8aEbal6lIofo1HVgS+TpNhwshGe1AuPMBE86R3wGtsnBphNX16fbITvWTN8kwzwidNiT7oKyrYuCOVGMq/F2vBqrCVzr3ABtlhTlPaXFtNZ3BdlsKWF7CZ4EcAvwQDfOB32ZGhRzDejVmFGWlEzndxqLoDHkUocTpfgSL7a0S5XoA9yiRYETQ3hBu3Kk5q86fEsShBhGo3sl3/drLn+KLoZPokP6eQ6HM8xgC/rwE2aogczGuDJuk/mQjKnPh38G5d/VyOfIcDLK4dv+DjkV4X7qtQa9xksrvu5Mm11WLESfj9IsDi+BitjlfCJ1+HSbRNaDN3ILVWBfVWO6xUGlPAf4hpVY2ecgAB3kZAr2xwFTBqyHn8x6nbnNL5hTmCBck5Ynirwm3QdxVGFvHI9kmjI+bLrEHS2AZySB8i51QxOsRQB7Er4RTDYFMldOGTz39Z3mW3+W1N02BitgBeVan0klSWcmhpKdQ/hUWkqsOZQOVYfKMfhNDGSciUEsLP7B/agGS/3eWk6AAAAAElFTkSuQmCC" # Create a streaming image by streaming the base64 string to a bitmap streamsource $bitmap = New-Object System.Windows.Media.Imaging.BitmapImage $bitmap.BeginInit() $bitmap.StreamSource = [System.IO.MemoryStream][System.Convert]::FromBase64String($Base64icon) $bitmap.EndInit() $bitmap.Freeze() # This is the icon in the upper left hand corner of the app $wpf.$FormName.Icon = $bitmap #======================================================== # END of WPF form definition and load controls #endregion #======================================================== #======================================================== #region WPF EVENTS definition #======================================================== #region Buttons $wpf.btnRun.add_Click({ Working-Label Get-Mailboxes if (($wpf.lblNbItemsInGrid.Content) -eq 0){ $wpf.btnClipboard.IsEnabled = $false } Else { $wpf.btnClipboard.IsEnabled = $true } Ready-Label }) $wpf.btnAction.add_Click({ Working-Label Run-Action Ready-Label }) $wpf.btnClipboard.add_Click({ $CSVClip = $wpf.GridView.ItemsSource | ConvertTo-CSV -NoTypeInformation $CSVClip | clip.exe $title = "Copied !" $msg = "Data copied to the clipboard ! `n`rUse CTRL+V on Notepad or on Excel !" [System.Windows.MessageBox]::Show($msg,$title, "OK","Asterisk") }) # End of Buttons region #endregion #region Load, Draw (render) and closing form events #Things to load when the WPF form is loaded aka in memory $Wpf.$FormName.Add_Loaded({ Ready-Label Update-MainCommandLine $wpf.$FormName.Title += " - v$Version" }) #Things to load when the WPF form is rendered aka drawn on screen $Wpf.$FormName.Add_ContentRendered({ write-host "rendered" }) $Wpf.$FormName.add_Closing({ $msg = "bye bye !" write-host $msg }) $wpf.lblAbout.Add_MouseLeftButtonDown($lblabout_Click) # End of load, draw and closing form events #endregion #region Text Changed events $wpf.GridView.add_SelectionChanged({ $Selected = $wpf.GridView.SelectedItems.count If ($Selected -eq 0) { $wpf.btnAction.IsEnabled = $false $wpf.comboSelectAction.IsEnabled = $false } ElseIf ($Selected -gt 0) { $wpf.btnAction.IsEnabled = $true $wpf.comboSelectAction.IsEnabled = $true } $wpf.lblNumberItemsSelected.Content = $Selected }) $wpf.txtMailboxString.add_TextChanged({ Update-MainCommandLine }) $wpf.txtResultSize.add_TextChanged({ Update-MainCommandLine }) $wpf.chkUnlimited.add_Click({ Update-MainCommandLine If ($wpf.chkUnlimited.IsChecked){ $wpf.txtResultSize.IsEnabled = $false } Else { $wpf.txtResultSize.IsEnabled = $true } }) $wpf.chkArbitrationOnly.add_Click({ Update-MainCommandLine If ($Wpf.chkArbitrationOnly.IsChecked){ $wpf.txtMailboxString.IsEnabled = $false $wpf.txtResultSize.IsEnabled = $false $wpf.chkUnlimited.IsEnabled = $false } Else { $wpf.txtMailboxString.IsEnabled = $true $wpf.txtResultSize.IsEnabled = $true $wpf.chkUnlimited.IsEnabled = $true } }) #End of Text Changed events #endregion #endregion #======================================================= #End of Events from the WPF form #endregion #======================================================= IsPSV3 | out-null Test-ExchTools | out-null # Load the form: # Older way >>>>> $wpf.MyFormName.ShowDialog() | Out-Null >>>>> generates crash if run multiple times # Newer way >>>>> avoiding crashes after a couple of launches in PowerShell... # USing method from https://gist.github.com/altrive/6227237 to avoid crashing Powershell after we re-run the script after some inactivity time or if we run it several times consecutively... $async = $wpf.$FormName.Dispatcher.InvokeAsync({ $wpf.$FormName.ShowDialog() | Out-Null }) $async.Wait() | Out-Null |