Advertisement
Yevrag35

Example Async WinForm

Nov 24th, 2019
513
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Add-Type -AssemblyName System.Windows.Forms
  2.  
  3. # Defining a synchronized hashtable allows us to add and retrieve objects in a 'thread-safe' manner.
  4. $ht = [hashtable]::Synchronized(@{})
  5.  
  6. # Creates a runspace that is attached to a newly-created PowerShell instance.
  7. Function New-Runspace()
  8. {
  9.     $rs = [runspacefactory]::CreateRunspace()
  10.     $rs.ApartmentState = "STA"
  11.     $rs.ThreadOptions = "ReuseThread"
  12.     $rs.Open()
  13.     $rs
  14. }
  15.  
  16. # New-PowerShell creates a PowerShell instance within the specified runspace and runs the supplied ScriptBlock.
  17. Function New-PowerShell([scriptblock] $ScriptBlock, [runspace] $Runspace)
  18. {
  19.     $ps = [powershell]::Create().AddScript($ScriptBlock)
  20.     $ps.Runspace = $Runspace
  21.     $ps.BeginInvoke()
  22. }
  23.  
  24. # The main form that is displayed.
  25. $form = New-Object System.Windows.Forms.Form -Property @{
  26.     Height = 150
  27.     Width = 600
  28. }
  29.  
  30. # This TextBox is where your 'systeminfo.exe' results will go.
  31. # As soon as the systeminfo text is added, this TextBox and the
  32. # Form will resize themselves to fit the content.
  33. $statusBox = New-Object System.Windows.Forms.TextBox -Property @{
  34.     Height = 30
  35.     Width = 580
  36.     Location = "10, 50"
  37.     MultiLine = $true
  38.     ScrollBars = [System.Windows.Forms.ScrollBars]::Both
  39.     WordWrap = $false
  40.     Add_TextChanged = {
  41.  
  42.         $count = $statusBox.Lines.Length
  43.         $possibleHeight = $count * $statusBox.Font.Height
  44.         if ($possibleHeight -gt 800)
  45.         {
  46.             $possibleHeight = 800
  47.         }
  48.         $statusBox.Height = $possibleHeight
  49.         $form.Height = $possibleHeight + 100
  50.  
  51.     }
  52. }
  53. $ht.Add("StatusBox", $statusBox)    # Add $statusBox to the 'synchronized' hashtable so it can be called safely
  54.                                     # from within a runspace.
  55.  
  56. # This is the button that starts the 'systeminfo.exe' process.
  57. # Notice, because it will run the 'systeminfo.exe' process in a separate thread,
  58. # the GUI remains responsive.  You can even click the "DummyButton" all day long while
  59. # the operation is running.
  60. $button = New-Object System.Windows.Forms.Button -Property @{
  61.     Text = "Get System Info"
  62.     Width = 150
  63.     Location = "20, 10"
  64.     Name = "MyButton"
  65.     # This is the Click Event handler that calls 'systeminfo.exe' asynchronously.
  66.     Add_Click = {
  67.         $rs = New-Runspace
  68.         $rs.SessionStateProxy.SetVariable("ht", $ht)    # We add the synchronized hashtable to the InitialSessionState.
  69.                                                         # This allows us to reference $ht from within the runspace.
  70.  
  71.         # $code represents the scriptblock that calls 'systeminfo.exe'
  72.         $code = {
  73.             $message = systeminfo.exe       # Run the systeminfo.exe like normal.
  74.                                             # We do NOT pipe it to 'Out-String' as we want
  75.                                             # to be able to retain and query the line count.
  76.  
  77.             $ht.StatusBox.Lines = $message  # Add the entire message to the StatusBox's Lines property.
  78.                                             # We are referencing it from the synchronized hashtable.
  79.         }
  80.         New-PowerShell -ScriptBlock $code -Runspace $rs
  81.     }
  82. }
  83.  
  84. # This is just a dummy button object that you can click to show
  85. # that the GUI remains responsive while 'systeminfo.exe' is running
  86. # in the background.
  87. $dummyButton = New-Object System.Windows.Forms.Button -Property @{
  88.     Text = "Dummy Button"
  89.     Width = 100
  90.     Location = "180, 10"
  91.     Name = "DummyButton"
  92. }
  93.  
  94. $form.Controls.AddRange(@($button, $dummyButton, $statusBox))
  95. $form.ShowDialog()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement