I'm attempting to make a function that will allow me to popup a please wait message run some more script then close the popup
Function Popup-Message {
param ([switch]$show,[switch]$close)
Add-Type -AssemblyName System.Windows.Forms
# Build Form
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Test"
$objForm.Size = New-Object System.Drawing.Size(220,100)
# Add Label
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(80,20)
$objLabel.Size = New-Object System.Drawing.Size(100,20)
$objLabel.Text = "Hi there!"
$objForm.Controls.Add($objLabel)
If ($show)
{
$objForm.Show() | Out-Null
$global:test = "Show"
}
If ($close)
{
# destroy form
$objForm.Close() | Out-Null
$global:test = "Close"
}
}
I can then get the popup to display by:
Popup-Message -show
At this point I can see the $test variable as Show
But when I try to close the window with:
Popup-Message -close
But the popup window will not close If I look at $test again it will show as Close
I'm assuming this has something to do with keeping the function in the Global Scope but I can't figure out how to do this with the form
kpogue's helpful answer explains your problem well and offers a solution that is effective, but suboptimal due to relying on global variables.
Let me suggest a different approach, where you use a function to simply define the form and return that definition, on which you can call the
.Show()
and.Close()
methods as needed, but note that the.Show()
method is overridden viaAdd-Member
to include a call to[System.Windows.Forms.Application]::DoEvents()
, so as to ensure that the form is properly drawn.You can then use the function as follows:
Note:
Once you call
.Close()
, the form instance stored in$form
is disposed of and cannot be reused - simply callNew-PopupForm
again to create a new instance.If the PowerShell session running your script exits, any pop-up windows created in the session close automatically.
Caveats:
Note that, due to use of the
.Show()
method (without additional effort), the user won't be able to interact with the pop-up window, notably not even in order to move the window or close it manually.ControlBox = $false
above removes the window's close button and system menu so as to make it obvious that no interaction is possible.[System.Windows.Forms.Cursor]::Hide()
serves the same purpose..Show()
, as discussed in the last bullet point.By contrast,
.ShowDialog()
would allow interaction, but blocks further execution of your script until the window is closed by the user.If you need to combine the two approaches - allowing the user to interact with the window while continuing to do processing in your PowerShell script - you need to call
[System.Windows.Forms.Application]::DoEvents()
in a loop, as shown in this answer.[System.Windows.Forms.Cursor]::Hide()
call from the function.