Eran Avni
Eran Avni

Reputation: 25

PowerShell popup in form

Is there a way to bring a PoweR Shell popup to the front of the screen? i use this command to show the popup


$wshell = New-Object -ComObject Wscript.Shell 
$Output = $wshell.Popup("text" ,0,"header",0+64)

but when i use form and a button in the form bis supposed to bring up the popup it shows in the back behind the form the form itself opens in the center and not bringing to front as shows here

Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()

$Form                            = New-Object system.Windows.Forms.Form
$Form.ClientSize                 = '1370,720'
$Form.text                       = "Chame Wizard"
$Form.TopMost                    = $true
$Form.icon                       = "c:\script\chame.ico"
$FormImage = [system.drawing.image]::FromFile("c:\script\back2.jpg")
$Form.BackgroundImage = $FormImage
$Form.StartPosition = "CenterScreen"

i know i can use balloon popup but i want the user to press OK before the script continues. Thanks :-)

Upvotes: 2

Views: 8968

Answers (3)

HO LI Pin
HO LI Pin

Reputation: 1681

This 4 line of code allow Powershell display pop up message

Add-Type -AssemblyName PresentationFramework    
$message = "Pop Up body message"
$title = "Pop Up Title string"
[System.Windows.MessageBox]::Show($message , $title)

You can tweak the pop up by customize the 3rd , 4th parameter , example below will display "Yes" , "No" , "Cancel" button as Error Type pop up alert

$msgBoxInput = [System.Windows.MessageBox]::Show('PopUp Message','PopUp Title','YesNoCancel','Error')

if ($msgBoxInput -eq 'Yes') 
{
    Write-Host "You clicked OK Button" ; ## Do something 
} 
elseif ($msgBoxInput -eq 'No') 
{
    Write-Host "You clicked No Button" ; ## Do something 

}

Upvotes: 0

Ste
Ste

Reputation: 2293

Theos' answer is great but if you want the MessageBox to be modal and not allow any more interaction with the $Form then this is the way to go about it.

I've updated this to show how to show a modal messagebox with a $Form.Add_Load event handler should you need a modal message box on execution of the script.

Comments in the code on how to achieve this:

# I've added this as an answer here:
# Edit added the $Form.Add_Load event handler.
# https://stackoverflow.com/questions/59371640/powershell-popup-in-form/67368911#67368911

Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()

$Form               = New-Object system.Windows.Forms.Form
$Form.ClientSize    = '444,55'
$Form.StartPosition = "CenterScreen"
$Form.Text          = "..."
$Form.TopMost       = $true

$Btn                     = New-Object System.Windows.Forms.Button
$Btn.Height              = $Form.Height-39
$Btn.Text                = "DO NOT PRESS..."
$Btn.Width               = $Form.Width-15
$Form.Controls.Add($Btn)
$Btn.Add_Click({

  # To have a modal messagebox you need to have it called from a form and use: $this.ActiveForm as shown below.
  [System.Windows.Forms.MessageBox]::Show($this.ActiveForm, 'Not to!!', 'I Told You..', [Windows.Forms.MessageBoxButtons]::"OK", [Windows.Forms.MessageBoxIcon]::"Warning")

  })

# Here you can do an if statement and then fire the message box when the Form loads which will be modal also.
$Form.Add_Load({
  [System.Windows.Forms.MessageBox]::Show($this.ActiveForm, 'You can add the message box as an event handler to show a message when the form is loaded...', 'A Message on Form Load Event!!', [Windows.Forms.MessageBoxButtons]::"OK", [Windows.Forms.MessageBoxIcon]::"Warning")
  })

# This below needs to be added to focus the dialog when it opens after the $Form.
$Form.Add_Shown({$Form.Activate(); $Btn.Focus()})
$Form.ShowDialog()

Theos great function modified to accept a -Modal switch.

# Mod of Theos' answer here: https://stackoverflow.com/a/59378301/8262102
# Edit by Ste: Can now be shown modal to the parent form with the usage of the
# -Modal switch.

# Mod of Theos' answer here: https://stackoverflow.com/a/59378301/8262102
# Edit by Ste: Can now be shown modal to the parent form with the usage of the
# -Modal switch.

Function Show-MessageBox {

  [CmdletBinding()]

  Param (
    [Parameter(Mandatory = $false)]
    [string]$Title = 'MessageBox in PowerShell',

    [Parameter(Mandatory = $true)]
    [string]$Message,

    [Parameter(Mandatory = $false)]
    [ValidateSet('OK', 'OKCancel', 'AbortRetryIgnore', 'YesNoCancel', 'YesNo', 'RetryCancel')]
    [string]$Buttons = 'OKCancel',

    [Parameter(Mandatory = $false)]
    [ValidateSet('Error', 'Warning', 'Information', 'None', 'Question')]
    [string]$Icon = 'Information',

    [Parameter(Mandatory = $false)]
    [ValidateRange(1,3)]
    [int]$DefaultButton = 1,

    [Parameter(Mandatory = $false)]
    [Switch]$Modal = $false
    )

  # Determine the possible default button.
  if ($Buttons -eq 'OK') {
    $Default = 'Button1'
  }
  elseif (@('AbortRetryIgnore', 'YesNoCancel') -contains $Buttons) {
    $Default = 'Button{0}' -f [math]::Max([math]::Min($DefaultButton, 3), 1)
  }
  else {
    $Default = 'Button{0}' -f [math]::Max([math]::Min($DefaultButton, 2), 1)
  }

  # Create a new form to hold the object and set it properties for the main
  # FolderBrowserDialog form.

  Add-Type -AssemblyName System.Windows.Forms

  $MessageBoxParentForm         = New-Object System.Windows.Forms.Form
  $MessageBoxParentForm.TopMost = $Modal

  Add-Type -AssemblyName System.Windows.Forms
  [void][System.Windows.Forms.Application]::EnableVisualStyles()

  [System.Windows.Forms.MessageBox]::Show(($MessageBoxParentForm), $Message, $Title,
    [Windows.Forms.MessageBoxButtons]::$Buttons,
    [Windows.Forms.MessageBoxIcon]::$Icon,
    [Windows.Forms.MessageBoxDefaultButton]::$Default)

}

# Non-modal example.
# Show-MessageBox -Title 'Important message' -Message 'Hi there!' -Icon None -Buttons OKCancel

# Modal example.
Show-MessageBox -Modal -Title 'Important message' -Message 'Hi there!' -Icon Warning -Buttons OK

Upvotes: 0

Theo
Theo

Reputation: 61028

You can also use one of the overloaded methods of [System.Windows.Forms.MessageBox]::Show() which allows you to add the owner window in order to have the messagebox be topmost to that.

By using $null there, your messagebox will be topmost to all opened windows:

function Show-MessageBox {  
    [CmdletBinding()]  
    Param (   
        [Parameter(Mandatory = $false)]  
        [string]$Title = 'MessageBox in PowerShell',

        [Parameter(Mandatory = $true)]
        [string]$Message,  

        [Parameter(Mandatory = $false)]
        [ValidateSet('OK', 'OKCancel', 'AbortRetryIgnore', 'YesNoCancel', 'YesNo', 'RetryCancel')]
        [string]$Buttons = 'OKCancel',

        [Parameter(Mandatory = $false)]
        [ValidateSet('Error', 'Warning', 'Information', 'None', 'Question')]
        [string]$Icon = 'Information',

        [Parameter(Mandatory = $false)]
        [ValidateRange(1,3)]
        [int]$DefaultButton = 1
    )            

    # determine the possible default button
    if ($Buttons -eq 'OK') {
        $Default = 'Button1'
    }
    elseif (@('AbortRetryIgnore', 'YesNoCancel') -contains $Buttons) {
        $Default = 'Button{0}' -f [math]::Max([math]::Min($DefaultButton, 3), 1)
    }
    else {
        $Default = 'Button{0}' -f [math]::Max([math]::Min($DefaultButton, 2), 1)
    }

    Add-Type -AssemblyName System.Windows.Forms
    # added from tip by [Ste](https://stackoverflow.com/users/8262102/ste) so the 
    # button gets highlighted when the mouse hovers over it.
    [void][System.Windows.Forms.Application]::EnableVisualStyles()

    # Setting the first parameter 'owner' to $null lets he messagebox become topmost
    [System.Windows.Forms.MessageBox]::Show($null, $Message, $Title,   
                                            [Windows.Forms.MessageBoxButtons]::$Buttons,   
                                            [Windows.Forms.MessageBoxIcon]::$Icon,
                                            [Windows.Forms.MessageBoxDefaultButton]::$Default)
}

With this function in place, you call it like:

Show-MessageBox -Title 'Important message' -Message 'Hi there!' -Icon Information -Buttons OK

enter image description here


Edit

As asked by Ste, the above function shows the messagebox TopMost. That however does not mean it is Modal. It only means the box is shown on top when first displayed, but can be pushed to the background by activating other windows.

For a real Modal messagebox that cannot be pushed to the background, I use this:

function Show-MessageBox {
    [CmdletBinding()]
    param(
        [parameter(Mandatory = $true, Position = 0)]
        [string]$Message,

        [parameter(Mandatory = $false)]
        [string]$Title = 'MessageBox in PowerShell',

        [ValidateSet("OKOnly", "OKCancel", "AbortRetryIgnore", "YesNoCancel", "YesNo", "RetryCancel")]
        [string]$Buttons = "OKCancel",

        [ValidateSet("Critical", "Question", "Exclamation", "Information")]
        [string]$Icon = "Information"
    )
    Add-Type -AssemblyName Microsoft.VisualBasic

    [Microsoft.VisualBasic.Interaction]::MsgBox($Message, "$Buttons,SystemModal,$Icon", $Title)
}


Show-MessageBox -Title 'Important message' -Message 'Hi there!' -Icon Information -Buttons OKOnly

enter image description here

Upvotes: 3

Related Questions