Adam Wifi
Adam Wifi

Reputation: 1

Powershell Form not closing

I am fairly new to PowerShell and Forms. I have a form I am trying to use outlook app from, Everything works as expected, the e-mail goes out as it should however powershell remains open in the background, so I am tryiing to figure out what I am missing or not doing right. Your help and knowledge is greatly appreciated.

 Copy-Item -Path C:\temp\logo.jpg "$env:USERPROFILE\logo.jpg"
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
 
# Create the form
$form = New-Object System.Windows.Forms.Form
$form.Text = "Logo Information System"
$form.Size = New-Object System.Drawing.Size(500, 350)
$form.FormBorderStyle = "FixedDialog"
$form.ControlBox = $false
$form.StartPosition = "CenterScreen"
$form.BackColor = "Black"
 
# Load and set the image in the title bar
$icon = [System.Drawing.Image]::FromFile("$env:USERPROFILE\logo.jpg")
$pictureBox = New-Object System.Windows.Forms.PictureBox
$pictureBox.Image = $icon
$pictureBox.Size = New-Object System.Drawing.Size(94, 94)
$pictureBox.Location = New-Object System.Drawing.Point(10, 10)
$form.Controls.Add($pictureBox)
 
# Title label
$titleLabel = New-Object System.Windows.Forms.Label
$titleLabel.Text = "Windows 11 Upgrade Notification"
$titleLabel.Font = New-Object System.Drawing.Font("Arial", 14, [System.Drawing.FontStyle]::Bold)
$titleLabel.ForeColor = "Red"
$titleLabel.BackColor = "Black"
$titleLabel.AutoSize = $true
$titleLabel.Location = New-Object System.Drawing.Point(120, 40)
$form.Controls.Add($titleLabel)
 
# Message Box
$msgLabel = New-Object System.Windows.Forms.Label
$msgLabel.Text = "Add here anything?"
$msgLabel.Font = New-Object System.Drawing.Font("Arial", 10, [System.Drawing.FontStyle]::Bold)
$msgLabel.ForeColor = "Red"
$msgLabel.BackColor = "Black"
$msgLabel.AutoSize = $true
$msgLabel.Location = New-Object System.Drawing.Point(120, 70)
$form.Controls.Add($msgLabel)
 
# Text Box (Centered)
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Multiline = $true
$textBox.ReadOnly = $true
$textBox.Text = "Windows 11 is being rolled out in your environment. Please select an option below."
$textBox.Font = New-Object System.Drawing.Font("Arial", 12)
$textBox.Size = New-Object System.Drawing.Size(460, 100)
$textBox.Location = New-Object System.Drawing.Point(10, 110)
$textBox.TextAlign = "Center"
$form.Controls.Add($textBox)
 
# Buttons
$btnStartUpgrade = New-Object System.Windows.Forms.Button
$btnStartUpgrade.Text = "Upgrade Tonight"
$btnStartUpgrade.Font = New-Object System.Drawing.Font("Arial", 10, [System.Drawing.FontStyle]::Bold)
$btnStartUpgrade.ForeColor = "Black"
$btnStartUpgrade.BackColor = "Green"
$btnStartUpgrade.Size = New-Object System.Drawing.Size(220, 40)
$btnStartUpgrade.Location = New-Object System.Drawing.Point(10, 240)
$btnStartUpgrade.Add_Click({ Start-Process "mailto:[email protected]?subject=Upgrade Confirmation Notification&body=$env:computername would like to upgrade to Windows 11 tonight at 20:00 followed by an immediate reboot."
})
$form.Controls.Add($btnStartUpgrade)
#
$btnOptOut = New-Object System.Windows.Forms.Button
$btnOptOut.Text = "Opt-Out of Win 11 upgrade"
$btnOptOut.Font = New-Object System.Drawing.Font("Arial", 10, [System.Drawing.FontStyle]::Bold)
$btnOptOut.ForeColor = "Black"
$btnOptOut.BackColor = "Yellow"
$btnOptOut.Size = New-Object System.Drawing.Size(220, 40)
$btnOptOut.Location = New-Object System.Drawing.Point(250, 240)
$btnOptOut.Add_Click({
    "Start-Process mailto:[email protected]?subject=Opt-Out Request&body=$env:computername would like to opt out of the Windows 11 upgrade."
})
$form.Controls.Add($btnOptOut)
 
# Show the form
$form.ShowDialog()

Upvotes: 0

Views: 93

Answers (1)

mklement0
mklement0

Reputation: 439812

Preface:

  • If your issue is simply about how to close your WinForms form after clicking a button:

    • Add the following to your script, just before the $form.ShowDialog() call:

      $form.CancelButton = $btnOptOut
      $form.AcceptButton = $btnStartUpgrade
      $btnStartUpgrade.DialogResult = 'OK'
      
    • As as result, clicking either button will implicitly close your form after the event handler has executed, the blocking $form.ShowDialog() will return, and execution of your script will resume; once your script exits (which with your sample code would be immediately, given that there are no statements after this call); if your PowerShell session was started in a way that only runs your script, it will end along with your script, causing the associated (blue by default) console window to close also (see also the next section).

      • Note that this also enables keyboard support: ESC triggers a click on the button stored in the .CancelButton property, whereas ENTER "clicks" the button stored in .AcceptButton.

      • However, if you'd rather not enable these keyboard shortcuts, you can manually close your form from inside each button event-handler script block, by placing $form.Close() at the end of each, as Luuk suggests.
        In that case, the the $form.ShowDialog() call will invariably return the Cancel enumeration value, irrespective of which button was pressed (see next point).

    • Irrespective of whether you use the mouse or the keyboard to press these buttons, the $form.ShowDialog() method call will report the respective enumeration value indicating which button was used to close the form, i.e. either Cancel or OK

  • By contrast, the section below addresses how to hide the console window associated with the PowerShell session that runs your script.


  • PowerShell must remain running for as long as your WinForms forms is being displayed in order for event processing to work.

  • However, you can hide the PowerShell console window (this assumes that your script was launched directly from outside an existing console window, such as via a shortcut file):

    • From inside your script, by placing the following command at the point where you'd like the console window to be hidden.

      # Dummy powershell.exe call that hides the caller's console window.
      $null = powershell.exe -windowstyle hidden -?
      
    • Alternatively, if you want to prevent creation of a console window for your script to begin with, you need a GUI(-subsystem) helper application (with the in-script technique above, even if you place the command to hide the console window at the very start of the script, the window will still initially be created visibly, causing a brief flash):

      • See the bottom section of this answer for an overview of available techniques; it also links to a future enhancement that will allow applications designed for it to situationally decide whether to allocate a console or not.

When you close the WinForms form, control is returned to your PowerShell script and execution resumes with statements after $form.ShowDialog() - if any (none in your sample code).

If your script was launched directly, exiting the script will also exit the hosting powershell.exe process (or, pwsh.exe, if you're using PowerShell (Core) 7).

Upvotes: 0

Related Questions