Paul Wendler
Paul Wendler

Reputation: 335

Non modal form creation in powershell function

Is there a way in Powershell 2 to create a non-modal Windows.Form / Dialog? The form should be created within a function and stay open until closed manually. The execution of the function however must continue. It should even be possible, to have the form stay open, even if the execution of any scripts was finished and the user returns back to the interactive mode.

I have tried like that, but it doesn't even creates the form with start-job. Calling makeform directly, however works like expected.

function makeform { 
        [void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
        [System.Windows.Forms.Application]::EnableVisualStyles();

        $form = New-Object Windows.Forms.Form
        $form.Text = 'Test Form'

        $form.Add_Shown({$form.Activate()})
        $form.ShowDialog()
}

function show  {
    start-job { makeform }
}

show  # does show nothing :| (expected the form to appear) 

start-job { makeform } -Name 'myjob' # expect the form to appear here - but it doesn't either :| 
Write-Host "Cont..."
# simulate some long running task 
[Threading.Thread]::Sleep(10000)

Wait-job myjob
Remove-job myjob
Write-Host "Done..."
Get-Job

I am running Powershell 2 with .NET 4 (via config) in case it is important. Thanks a lot!

Upvotes: 1

Views: 4829

Answers (1)

latkin
latkin

Reputation: 16792

The job approach is correct, but you have a bug. Jobs run in a totally new scope and don't inherit any variables or function defined in your current scope. Thus the function makeform is unknown to your job. You can verify here:

Start-Job { makeform } | Wait-Job | Receive-Job

A few workarounds:

Declare makeform in a scriptblock, and pass that block as the -InitializationScript

$lib = {
  function makeform {     
          [void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")    
          [System.Windows.Forms.Application]::EnableVisualStyles();    

          $form = New-Object Windows.Forms.Form    
          $form.Text = 'Test Form'    

          $form.Add_Shown({$form.Activate()})    
          $form.ShowDialog()    
  }
}

Start-Job { makeform } -InitializationScript $lib

Or you can pass the scriptblock of the makeform function itself as the content of the job:

Start-Job $function:makeform

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

Upvotes: 1

Related Questions