In PowerShell Form.Show() does not work right, but Form.ShowDialog() does In PowerShell Form.Show() does not work right, but Form.ShowDialog() does powershell powershell

In PowerShell Form.Show() does not work right, but Form.ShowDialog() does


First Answer Why it appends.

In a Windows graphic program the thread which create a Window must loop in a message pump in order to redistribute (translate) messages coming from the user action to events in his Windows.

In a modal window, the modal code that handles the window display runs its own message pump loop and doesn't return until the window is closed. That's why the code after ShowDialog() won't execute until the window is closed.

Show(), just ask to show the Window, but if there is no pump loop to manage the messages coming from user action, it just freezes.

Second a simple way to have two threads

The CmdLet start-job use another thread from the pool allocated by Powershell so it makes the dialog non-modal, and it does not freeze.

function goForm{  [void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")  $file = (get-item 'C:\temp\jpb.png')  #$file = (get-item "c:\image.jpg")  $img = [System.Drawing.Image]::Fromfile($file);  # This tip from http://stackoverflow.com/questions/3358372/windows-forms-look-different-in-powershell-and-powershell-ise-why/3359274#3359274  [System.Windows.Forms.Application]::EnableVisualStyles();  $form = new-object Windows.Forms.Form  $form.Text = "Image Viewer"  $form.Width = $img.Size.Width;  $form.Height =  $img.Size.Height;  $pictureBox = new-object Windows.Forms.PictureBox  $pictureBox.Width =  $img.Size.Width;  $pictureBox.Height =  $img.Size.Height;  $pictureBox.Image = $img;  $form.controls.add($pictureBox)  $form.Add_Shown( { $form.Activate() } )  $form.ShowDialog()}Clear-Hoststart-job $function:goForm$name = Read-Host "What is you name"Write-Host "your name is $name"


There are ways to make this work, but nothing is worth spending five hours explaining on an open forum. There are other free, shrink-wrapped ways to do this on powershell. Most notably with the free WPF powershell toolkit: Show-UI at http://showui.codeplex.com/ (previously known as WPK and/or PowerBoots - they are merged now.)


If your goal is actually to not block the interactive console when an image is shown then you still can use the script as it is with ShowDialog but you should start it using, for example, Start-Job. Thus, the dialog is still modal but it blocks execution in another runspace. The main runspace still can be used for invoking other commands.

Caveats: 1) You should close all opened dialogs before closing the interactive console. 2) If you care, you should remove completed jobs yourself (when a dialog is closed a job that started it still exists).

I use a similar approach in my custom host and it works fine. I also tested it with the script from your link. I changed it slightly so that it is called show-image.ps1 and accepts a file path as a parameter.

This command shows an image and blocks the calling runspace:

show-image.ps1 C:\TEMP\_110513_055058\test.png

This command shows an image and does not block the calling runspace:

Start-Job { show-image.ps1 $args[0] } -ArgumentList C:\TEMP\_110513_055058\test.png