Show opup with timeout and focus

I would like to show popup with some information and auto close it if no respond from user but also I want to bring the message on top of everything else.

I try this but message was hidden behind other windows and even i put 30 Seconds but message was display for 40-45 Seconds.

$sh = New-Object -ComObject “Wscript.Shell”
$intButton = $sh.Popup(“Testing”,30,“Title”,0+64)

What is the best message to user to user with auto close and bring message front of all widnows

A little more involved but you could use system.windows.forms. i.e.

Add-Type -AssemblyName system.windows.forms
Add-Type -AssemblyName system.drawing

$form = New-Object System.Windows.Forms.Form
$form.Text = "Hello World"
$label = New-Object System.Windows.Forms.Label
$label.Text = "Here is my message"
$label.Size = New-Object System.Drawing.Size(200,20)
$form.Controls.Add($label)


$form.Show()
Start-Sleep -Seconds 3
$form.Close()

See example/docs here: Creating a Custom Input Box - PowerShell | Microsoft Docs

1 Like

I try following script but it wont let me click on ok and I want do things if any press ok

function ShowMsg ($timeout,$message)

{
Add-Type -AssemblyName system.windows.forms
Add-Type -AssemblyName system.drawing

$form = New-Object System.Windows.Forms.Form
$form.Text = "Company Name"
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'

$label = New-Object System.Windows.Forms.Label
$label.Text = $message
$label.Size = New-Object System.Drawing.Size(200,20)
$form.Controls.Add($label)

#add button to form
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(75,120)
$okButton.Size = New-Object System.Drawing.Size(75,23)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)


$form.Topmost = $true
$result = $form.ShowDialog()

$form.Show()
Start-Sleep 30
$form.Close()

return $result

}

$timeout = 30

$r = ShowMsg -message “This is the message you will see on the window`nMessage on new line” -timeout $timeout

if ($r -eq [System.Windows.Forms.DialogResult]::OK)
{
Write-Host “Press ok now”

}

Also its possible to put new line in message and resize windows depending on message

ShowDialog is meant to prompt a user and then go away after the user chooses or cancels. You do not want to close the form when using it. When hard coding sizes such as the label, keep that in mind when wanting to show multiple lines of text. I’ve increased the height to 40.

function ShowMsg ($timeout,$message)
{
Add-Type -AssemblyName system.windows.forms
Add-Type -AssemblyName system.drawing

$form = New-Object System.Windows.Forms.Form
$form.Text = "Company Name"
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'

$label = New-Object System.Windows.Forms.label
$label.Text = $message
$label.Size = New-Object System.Drawing.Size(200,40)
$form.Controls.Add($label)

#add button to form
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(75,120)
$okButton.Size = New-Object System.Drawing.Size(75,23)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)


$form.Topmost = $true
$form.ShowDialog()

$form.Dispose()
}

$timeout = 30

$r = ShowMsg -message “This is the message you will see on the window`nMessage on new line” -timeout $timeout

if ($r -eq [System.Windows.Forms.DialogResult]::OK)
{
Write-Host “Press ok now”

}

I would like to close the message box if the user clicks on OK or auto close it if no one clicks on OK after 5 minutes or 1 hour

What i’m trying to do is ask user an question but give them time to respond, if no respond is given in time then close the box and move on to next question

The complication is after ShowDialog() method the PowerShell code will hang until the form is closed, so you can’t use Start-Sleep because once the form is open it will never get to that line of code. There is a way however. There is a form control called timer (system.windows.forms.timer). It can call code at a specified interval (in milliseconds). Here’s the docs: Timer Class (System.Windows.Forms) | Microsoft Docs

Here is an example of how you could use it for your requirements.

function ShowMsg ($timeout,$message)
{
Add-Type -AssemblyName system.windows.forms
Add-Type -AssemblyName system.drawing

$form = New-Object System.Windows.Forms.Form
$form.Text = "Company Name"
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'

$label = New-Object System.Windows.Forms.label
$label.Text = $message
$label.Size = New-Object System.Drawing.Size(200,40)
$form.Controls.Add($label)

#add button to form
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(75,120)
$okButton.Size = New-Object System.Drawing.Size(75,23)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)

$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = $timeout * 1000
$timer.add_tick({$form.Close()})
$timer.Start()

$form.Topmost = $true
$form.ShowDialog()

$form.Dispose()
}

$timeout = 30

ShowMsg -message “This is the message you will see on the window`nMessage on new line” -timeout $timeout

1 Like

Thank you that did what I need but its keep closing when I click on an empty space on dekstop or application or inside the message. also if I run the code more then 5 times then it keep showing message cancel on the output

$timeout = 10

ShowMsg -message “This is the message you will see on the window`nMessage on new line” -timeout $timeout

Cancel

I can’t seem to duplicate that issue. There are a couple things you should add to “fix” some erroneous behavior that could happen with the example code I gave you.

  1. Even though the form is closed the timer may still be running, so add code to disable it when the form is closed.
$form.add_formclosed({$timer.Enabled = $false})
  1. If the form “times out” then you should return control back.
$timer.add_tick({$form.Close(); return })

The function ShowMsg returns either Cancel or Ok depending on if the user clicked Ok or the form timed out. Use it as you like or if you don’t then pipe the output to null.

#use the result
$result = ShowMsg -message “This is the message you will see on the window`nMessage on new line” -timeout $timeout 
if ($result -eq [System.Windows.Forms.DialogResult]::ok) {
    Write-Host "You clicked ok"
}
else {
    Write-Host "Message timed out"
}

#don't use the result
ShowMsg -message “This is the message you will see on the window`nMessage on new line” -timeout $timeout | Out-Null

Here’s an updated example:

function ShowMsg ($timeout,$message)
{
Add-Type -AssemblyName system.windows.forms
Add-Type -AssemblyName system.drawing

$form = New-Object System.Windows.Forms.Form
$form.Text = "Company Name"
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'

$label = New-Object System.Windows.Forms.label
$label.Text = $message
$label.Size = New-Object System.Drawing.Size(200,40)
$form.Controls.Add($label)

#add button to form
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(75,120)
$okButton.Size = New-Object System.Drawing.Size(75,23)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)

$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = $timeout * 1000
$timer.add_tick({$form.Close(); return })
$timer.Start()

$form.Topmost = $true
$form.add_formclosed({$timer.Enabled = $false})
$form.ShowDialog()

$form.Dispose()
}

$timeout = 30

#use the result
$result = ShowMsg -message “This is the message you will see on the window`nMessage on new line” -timeout $timeout 
if ($result -eq [System.Windows.Forms.DialogResult]::ok) {
    Write-Host "You clicked ok"
}
else {
    Write-Host "Message timed out"
}

#don't use the result
ShowMsg -message “This is the message you will see on the window`nMessage on new line” -timeout $timeout | Out-Null


Thank you so much its working, I did add the $timer.Dispose() to fix the auto close problem