2

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 :-)

Eran Avni
  • 25
  • 1
  • 7

3 Answers3

2

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

Theo
  • 57,719
  • 8
  • 24
  • 41
  • The only thing I'd add is `[void][System.Windows.Forms.Application]::EnableVisualStyles()` so that the button is highlighted once you hoover over them. Thanks for this. – Ste Apr 21 '21 at 10:29
  • Thanks @Ste I have added that in the answer. – Theo Apr 21 '21 at 10:37
  • No worries, I did notice that the MessageBox is not topmost. Is that the same as modal where it is always on top or different? – Ste Apr 21 '21 at 10:44
  • @Ste I have added code for a real **modal** messagebox. The difference is that code #1 shows on top, but can be pushed to the background. Code #2 shows a messagebox in real Modal, which cannot be pushed back. – Theo Apr 21 '21 at 13:45
  • Thanks for taking the time to do that. I assume that to go modal the message box has to be `[Microsoft.VisualBasic.Interaction]::MsgBox...`? – Ste Apr 21 '21 at 20:50
  • I found a way to make the message box modal in your first example. It needs to be called from a `$Form`. Then from any control within that `$Form` you can use `[System.Windows.Forms.MessageBox]::Show($this.ActiveForm,"Finished processing", "Process finished")` I'll post my answer for that. – Ste May 03 '21 at 12:24
0

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
Ste
  • 1,729
  • 1
  • 17
  • 27
0

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 

}
HO LI Pin
  • 1,441
  • 13
  • 13