none
Help with a basic RunSpace form RRS feed

  • Question

  • Hello all,

    I am trying (unsuccessfully) to get my head round Runspaces.

    The most basic and straightforward explanation and example I have found is this, which is what I have worked from.

    I have created a very basic GUI of a simple script I wrote to restart a couple of services on my server.

    I have then retrofitted the Runspace code based on the layout of the link.

    What really confuses me is that it was working yesterday, but now isn't !

    On the first run of the code I get this error : 

    Exception calling "Run" with "1" argument(s): "Cannot access a disposed object.
    Object name: 'Form'."
    At C:\Users\Damian\source\repos\RestartEmby\RestartEmby\bin\Release\MainForm.ps1:152 char:1
    + [Windows.Forms.Application]::Run($MainForm)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : ObjectDisposedException
    

    And on the second run I get this :

    Exception calling "Run" with "1" argument(s): "Starting a second message loop on a single thread is not a valid operation. Use Form.ShowDialog instead."
    At C:\Users\Damian\source\repos\RestartEmby\RestartEmby\bin\Release\MainForm.ps1:153 char:1
    + [Windows.Forms.Application]::Run($MainForm)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : InvalidOperationException
    
     

    If I use ShowDialog as suggested, I get this error :

    Exception calling "ShowDialog" with "0" argument(s): "Cannot access a disposed object.
    Object name: 'Form'."
    At C:\Users\Damian\source\repos\RestartEmby\RestartEmby\bin\Release\MainForm.ps1:152 char:1
    + $MainForm.ShowDialog()
    + ~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : ObjectDisposedException
    

    The complete code :

    [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
    [Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null
    Add-Type -AssemblyName System.Windows.Forms
    
    
    $sync = [Hashtable]::Synchronized(@{})
    
    $restartemby = {
    
    	$rsjob = [PowerShell]::Create().AddScript({
    	$sync.startbutton.Enabled = $false
    	$server = "@#*&%$£#@"
    	$svc1 = (Get-Service -ComputerName $server -Name emby)
        $svc2 = (Get-Service -ComputerName $server -Name DVBVRecorder)
    	$svc1name = "Emby"
    	$svc2name = "DVBVRecorder"
        $sync.rtb.SelectionColor = "Orange"
    	$sync.rtb.AppendText("Connecting to Server: $server`r`n")
    	$sync.rtb.SelectionColor = "Green"
    	$sync.rtb.AppendText("$svc1name service is $($svc1.Status)`r`n")
    	$sync.rtb.SelectionColor = "Green"
    	$sync.rtb.AppendText("$svc2name service is $($svc2.Status)`r`n")
    	$sync.rtb.Refresh()
    	$sync.rtb.SelectionColor = "Red"
    	$sync.rtb.AppendText("Stopping $svc1name `r`n")
    	$svc1.Stop()
    	$sync.rtb.SelectionColor = "Red"
    	$sync.rtb.AppendText("Stopping $svc2name `r`n")
    	$svc2.Stop()
        Start-Sleep -s 3
        $svc1.Refresh()
        $svc2.Refresh()
    	$sync.rtb.SelectionColor = "Orange"
        $sync.rtb.AppendText("$svc1name service is $($svc1.Status)`r`n")
    	$sync.rtb.SelectionColor = "Orange"
    	$sync.rtb.AppendText("$svc2name service is $($svc2.Status)`r`n")
    	$sync.rtb.Refresh()
        $sync.rtb.SelectionColor = "Green"
    	$sync.rtb.AppendText("Deleting Emby Server Logs`r`n")
    	$sync.rtb.Refresh()
        Remove-Item \\$server\C$\Users\Administrator\AppData\Roaming\Emby-Server\logs\* -recurse
        Start-Sleep -s 1
    	$sync.rtb.SelectionColor = "Orange"
    	$sync.rtb.AppendText("Starting $svc2name `r`n")
    	$sync.rtb.Refresh()
    	$svc2.Start()
    	Start-Sleep -s 5
        $svc2.Refresh()
    	$sync.rtb.SelectionColor = "Green"
    	$sync.rtb.AppendText("$svc2name service is $($svc2.Status)`r`n")
    	$sync.rtb.Refresh()
    	Start-Sleep -s 1
    	$sync.rtb.SelectionColor = "Orange"
    	$sync.rtb.AppendText("Starting $svc1name `r`n")
    	$sync.rtb.Refresh()
    	$svc1.Start()
        Start-Sleep -s 5
        $svc1.Refresh()
    	$sync.rtb.SelectionColor = "Green"
    	$sync.rtb.AppendText("$svc1name service is $($svc1.Status)`r`n")
    	$sync.rtb.Refresh()
    	$sync.rtb.SelectionColor = "Green"
    	$sync.rtb.AppendText("Finished")
    	$sync.rtb.Refresh()
    
    	$sync.startbutton.Enabled = $true
    	})
    
    	$runspace = [RunspaceFactory]::CreateRunspace()
    	$runspace.ApartmentState = "STA"
    	$runspace.ThreadOptions = "ReuseThread"
    	$runspace.Open()
    	$runspace.SessionStateProxy.SetVariable("sync", $sync)
      
    	$rsjob.Runspace = $runspace
    	$rsjob.BeginInvoke()
    }
    
    
    
    $formfonts = (New-Object -TypeName System.Drawing.Font -ArgumentList @('Segoe UI Semibold', [System.Single]9.25, [System.Drawing.FontStyle]::Regular, [System.Drawing.GraphicsUnit]::Point, [System.Byte][System.Byte]0))
    $formcolour = [System.Drawing.Color]::LightGoldenrodYellow
    
    $MainForm = New-Object -TypeName System.Windows.Forms.Form	
    $button_start = (New-Object -TypeName System.Windows.Forms.Button)
    $button_exit = (New-Object -TypeName System.Windows.Forms.Button)
    $panel1 = (New-Object -TypeName System.Windows.Forms.Panel)
    $richTextBox1 = (New-Object -TypeName System.Windows.Forms.RichTextBox)
    $MainForm.BackColor = $formcolour
    $MainForm.Font = $formfonts
    #
    #button_start
    #
    $button_start.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
    $button_start.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]120,[System.Int32]22))
    $button_start.Name = [string]'button_start'
    $button_start.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]136,[System.Int32]26))
    $button_start.TabIndex = [System.Int32]0
    $button_start.Text = [string]'Start'
    $button_start.UseVisualStyleBackColor = $true
    $button_start.add_Click($restartemby)
    #
    #button_exit
    #
    $button_exit.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
    $button_exit.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]12,[System.Int32]299))
    $button_exit.Name = [string]'button_exit'
    $button_exit.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]48,[System.Int32]28))
    $button_exit.TabIndex = [System.Int32]1
    $button_exit.Text = [string]'Exit'
    $button_exit.UseVisualStyleBackColor = $true
    $button_exit.add_Click($MainForm.Close())
    #
    #panel1
    #
    $panel1.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
    $panel1.Controls.Add($richTextBox1)
    $panel1.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]46,[System.Int32]66))
    $panel1.Name = [string]'panel1'
    $panel1.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]288,[System.Int32]217))
    $panel1.TabIndex = [System.Int32]2
    #
    #richTextBox1
    #
    $richTextBox1.BorderStyle = [System.Windows.Forms.BorderStyle]::None
    $richTextBox1.Dock = [System.Windows.Forms.DockStyle]::Fill
    $richTextBox1.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]0,[System.Int32]0))
    $richTextBox1.Name = [string]'richTextBox1'
    $richTextBox1.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]286,[System.Int32]215))
    $richTextBox1.TabIndex = [System.Int32]0
    $richTextBox1.Text = [string]''
    #
    #MainForm
    #
    $sync.panel = $panel1
    $sync.rtb = $richTextBox1
    $sync.startbutton = $button_start
    $sync.exitbutton = $button_exit
    $MainForm.AcceptButton = $button_start
    $MainForm.CancelButton = $button_exit
    $MainForm.ClientSize = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]381,[System.Int32]339))
    $MainForm.Controls.Add($sync.panel)
    $MainForm.Controls.Add($sync.startbutton)
    $MainForm.Controls.Add($sync.exitbutton)
    $MainForm.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle
    $MainForm.MaximizeBox = $false
    $MainForm.Name = [string]'MainForm'
    $MainForm.SizeGripStyle = [System.Windows.Forms.SizeGripStyle]::Hide
    $MainForm.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
    $MainForm.Text = [string]'Restart Emby & DBV'
    
    #$MainForm.ShowDialog()
    [Windows.Forms.Application]::Run($MainForm)

    Please can someone explain to me what I'm doing wrong here ?

    And is the linked example a good method for me to follow (assuming I can get it to work again)

    Many thanks

    Damian

    • Moved by Bill_Stewart Friday, January 26, 2018 3:18 PM This is not "teach me event-driven programming in a forum" forum
    Wednesday, December 6, 2017 2:15 PM

Answers

  • To learn runspaces don't use a form since you also do not understand how forms work.  You are trying to mix two very difficult technologies.  THis will frustrate you if you are not a programmer.

    Here is an example of how to build a form and call a runspace that writes to the form.

    $script = {
        $server = "@#*&%$£#@"
        $rtb = $sync.RTB
    
        Try{
            $rtb.SelectionColor = "Green"
            $rtb.AppendText("Connecting to Server: $server`n")
            $svc1, $svc2 = Get-Service Emby, DVBVRecorder -ComputerName $server -ErrorAction Stop
            
            $rtb.SelectionColor = "Green"
            $rtb.AppendText("$svc1name service is $($svc1.Status)`n")
            $rtb.SelectionColor = "Green"
            $rtb.AppendText("$svc2name service is $($svc2.Status)`n")
            $rtb.SelectionColor = "Red"
            $rtb.AppendText("Stopping $svc1name `r`n")
            $svc1.Stop()
            $rtb.SelectionColor = "Red"
            $rtb.AppendText("Stopping $svc2name `r`n")
            $svc2.Stop()
            Start-Sleep -Seconds 3
            
            $rtb.SelectionColor = "Orange"
            $rtb.AppendText("$svc1name service is $($svc1.Status)`n")
            $rtb.SelectionColor = "Orange"
            $rtb.AppendText("$svc2name service is $($svc2.Status)`n")
            $rtb.SelectionColor = "Green"
            $rtb.AppendText("Deleting Emby Server Logs`n")
            Remove-Item \\$server\C$\Users\Administrator\AppData\Roaming\Emby-Server\logs\* -recurse
            Start-Sleep -Seconds 1
            
            $rtb.SelectionColor = "Orange"
            $rtb.AppendText("Starting $svc2name `n")
            $svc2.Start()
            Start-Sleep -Seconds 5
            
            $svc2.Refresh()
            $rtb.SelectionColor = "Green"
            $rtb.AppendText("$svc2name service is $($svc2.Status)`n")
            Start-Sleep -Seconds 1
            
            $rtb.SelectionColor = "Orange"
            $rtb.AppendText("Starting $svc1name `n")
            $svc1.Start()
            Start-Sleep -Seconds 5
            
            $rtb.SelectionColor = "Green"
            $rtb.AppendText("$svc1name service is $($svc1.Status)`n")
        }
        Catch{
            $rtb.SelectionColor = "Red"
            $rtb.AppendText("$_ `n")
        }
            
        $rtb.SelectionColor = "Green"
        $rtb.AppendText("Finished`n")
        $sync.SB.Enabled = $true
    }
    
    function Start-RSJob {
        
        $sync = [Hashtable]::Synchronized(@{ RTB = $rtb; SB = $buttonStart })
        
        $rsjob = [PowerShell]::Create().AddScript($script)
        
        $runspace = [RunspaceFactory]::CreateRunspace()
        $runspace.ApartmentState = "STA"
        $runspace.ThreadOptions = "ReuseThread"
        $runspace.Open()
        $runspace.SessionStateProxy.SetVariable("sync", $sync)
        
        $rsjob.Runspace = $runspace
        $rsjob.BeginInvoke()
        
    }
    
    
    
    
    Add-Type -AssemblyName System.Windows.Forms
    
    $buttonStartClick = {
        $this.Enabled = $false
        Start-RSJob
    }
    
    $form = New-Object System.Windows.Forms.Form
    $buttonStart = New-Object System.Windows.Forms.Button
    $form.Controls.Add($buttonStart)
    $buttonExit = New-Object System.Windows.Forms.Button
    $form.Controls.Add($buttonExit)
    $rtb = New-Object System.Windows.Forms.RichTextBox
    $form.Controls.Add($rtb)
    
    # Mainform
    $form.ClientSize = '381,339'
    $form.FormBorderStyle = 'FixedSingle'
    $form.MaximizeBox = $false
    $form.Name = 'MainForm'
    $form.StartPosition = 'CenterScreen'
    $form.Text = 'Restart Emby & DBV'
    $form.BackColor = 'LightGoldenrodYellow'
    $form.Font = 'Segoe UI Semibold 9.25'
    
    #
    #button_start
    #
    $buttonStart.FlatStyle = 'Flat'
    $buttonStart.Location = '120, 22'
    $buttonStart.Name = 'button_start'
    $buttonStart.Size = '136, 26'
    $buttonStart.TabIndex = 0
    $buttonStart.Text = 'Start'
    $buttonStart.add_Click({
            $this.Enabled = $false
            Start-RSJob
        })
    #
    #button_exit
    #
    $buttonExit.Location = '12,299'
    $buttonExit.Name = 'button_exit'
    $buttonExit.Size = '48,28'
    $buttonExit.TabIndex = 1
    $buttonExit.Text = 'Exit'
    $buttonExit.DialogResult = 'Ok'
    
    #
    #richTextBox1
    #
    $rtb.Location = '10,60'
    $rtb.Width = $form.ClientSize.Width - 20
    $rtb.Height = $form.ClientSize.Height - 100
    $rtb.Name = 'rtb'
    
    $form.ShowDialog()
    


    \_(ツ)_/

    • Marked as answer by DamianBz Sunday, August 19, 2018 4:24 PM
    Wednesday, December 6, 2017 7:20 PM

All replies

  • Why do you think you need a runspace for a form?


    \_(ツ)_/

    Wednesday, December 6, 2017 5:51 PM
  • In PowerShell you cannot use "Run" with a dialog.  PS is not a multithreaded environment and run requires startup code that is not available.


    \_(ツ)_/

    Wednesday, December 6, 2017 5:53 PM
  • Here is the correct way to build and display your form.

    Add-Type -AssemblyName System.Windows.Forms
    
    $MainForm = New-Object System.Windows.Forms.Form
    $button_start = New-Object System.Windows.Forms.Button
    $MainForm.Controls.Add($button_start)
    $button_exit = New-Object System.Windows.Forms.Button
    $MainForm.Controls.Add($button_exit)
    $panel1 = New-Object System.Windows.Forms.Panel
    $MainForm.Controls.Add($panel1)
    $richTextBox1 = New-Object System.Windows.Forms.RichTextBox
    
    # Mainform
    $MainForm.ClientSize = '381,339'
    $MainForm.FormBorderStyle = 'FixedSingle'
    $MainForm.MaximizeBox = $false
    $MainForm.Name = 'MainForm'
    $MainForm.StartPosition = 'CenterScreen'
    $MainForm.Text = 'Restart Emby & DBV'
    $MainForm.BackColor = 'LightGoldenrodYellow'
    $MainForm.Font = 'Segoe UI Semibold 9.25'
    
    #
    #button_start
    #
    $button_start.FlatStyle = 'Flat'
    $button_start.Location = '120, 22'
    $button_start.Name = 'button_start'
    $button_start.Size = '136, 26'
    $button_start.TabIndex = 0
    $button_start.Text = [string]'Start'
    $button_start.UseVisualStyleBackColor = $true
    #$button_start.add_Click($restartemby)
    #
    #button_exit
    #
    $button_exit.Location = '12,299'
    $button_exit.Name = 'button_exit'
    $button_exit.Size = '48,28'
    $button_exit.TabIndex = 1
    $button_exit.Text = 'Exit'
    $button_exit.DialogResult = 'Ok'
    #
    #panel1
    #
    $panel1.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
    $panel1.Controls.Add($richTextBox1)
    $panel1.Location = '46,66'
    $panel1.Name = 'panel1'
    $panel1.Size = '288,217'
    $panel1.TabIndex = 2
    #
    #richTextBox1
    #
    $richTextBox1.Dock = 'Fill'
    $richTextBox1.Name = 'richTextBox1'
    
    $MainForm.ShowDialog()
    

    Adding a runspace does not add anything here.  Just run your script in the button code.

    To learn more about forms with PowerShell see the following.

    https://info.sapien.com/index.php/guis


    \_(ツ)_/

    Wednesday, December 6, 2017 6:14 PM
  • For what you are trying to do just use a timer that polls the services and writes to the RTB.  This will allow the form to stay active.


    \_(ツ)_/


    • Edited by jrv Wednesday, December 6, 2017 6:34 PM
    Wednesday, December 6, 2017 6:20 PM
  • Hi jrv ...

    I'm REALLY confused by your questions !!

    I've read many pages about making more responsive GUI forms, that allow the GUI and the actual working code to run in separate instances of powershell to stop the GUI from locking up when running.

    Some of which I'm fairly sure YOU wrote or provided examples !

    And as I said in my first post, I am using this basic GUI as a test so that I can implement this into a couple of much larger and more complicated scripts that really need this as they lock\freeze when running long tasks.

    And actually the basic script shown above was immediately unresponsive as soon as it started to run. 

    I also don't understand your other comment ... as the script that I linked to, and the 3 others that I have as examples all work. but you seem to be suggesting that this is not possible ??

    Can you clarify what you are saying to me ? as I'm not sure if you are saying that the way I have this code written is wrong, or that what I'm trying to achieve is not possible, which goes against everything that I have read from Boe Prox and other articles from the "hey scripting guy" site plus many others.

    Thanks

    Damian

    Wednesday, December 6, 2017 6:41 PM
  • Hi jrv,

    Sorry, I think you are missing the point here !

    I'm using this as a learning exercise, to understand how Runspaces work, and how to code them :)

    I'm certainly not an expert, but have successfully written 6 or so fully functioning GUI's with powershell.

    But it's the Runspace thing that I want to learn about and integrate into some of my scripts because some of them have very time consuming processes that are looking up AD and SCCM with 10K + records and as far as I have read, would be best suited to running from a separate process.

    Cheers

    Damian

    Wednesday, December 6, 2017 6:56 PM
  • To learn runspaces don't use a form since you also do not understand how forms work.  You are trying to mix two very difficult technologies.  THis will frustrate you if you are not a programmer.

    Here is an example of how to build a form and call a runspace that writes to the form.

    $script = {
        $server = "@#*&%$£#@"
        $rtb = $sync.RTB
    
        Try{
            $rtb.SelectionColor = "Green"
            $rtb.AppendText("Connecting to Server: $server`n")
            $svc1, $svc2 = Get-Service Emby, DVBVRecorder -ComputerName $server -ErrorAction Stop
            
            $rtb.SelectionColor = "Green"
            $rtb.AppendText("$svc1name service is $($svc1.Status)`n")
            $rtb.SelectionColor = "Green"
            $rtb.AppendText("$svc2name service is $($svc2.Status)`n")
            $rtb.SelectionColor = "Red"
            $rtb.AppendText("Stopping $svc1name `r`n")
            $svc1.Stop()
            $rtb.SelectionColor = "Red"
            $rtb.AppendText("Stopping $svc2name `r`n")
            $svc2.Stop()
            Start-Sleep -Seconds 3
            
            $rtb.SelectionColor = "Orange"
            $rtb.AppendText("$svc1name service is $($svc1.Status)`n")
            $rtb.SelectionColor = "Orange"
            $rtb.AppendText("$svc2name service is $($svc2.Status)`n")
            $rtb.SelectionColor = "Green"
            $rtb.AppendText("Deleting Emby Server Logs`n")
            Remove-Item \\$server\C$\Users\Administrator\AppData\Roaming\Emby-Server\logs\* -recurse
            Start-Sleep -Seconds 1
            
            $rtb.SelectionColor = "Orange"
            $rtb.AppendText("Starting $svc2name `n")
            $svc2.Start()
            Start-Sleep -Seconds 5
            
            $svc2.Refresh()
            $rtb.SelectionColor = "Green"
            $rtb.AppendText("$svc2name service is $($svc2.Status)`n")
            Start-Sleep -Seconds 1
            
            $rtb.SelectionColor = "Orange"
            $rtb.AppendText("Starting $svc1name `n")
            $svc1.Start()
            Start-Sleep -Seconds 5
            
            $rtb.SelectionColor = "Green"
            $rtb.AppendText("$svc1name service is $($svc1.Status)`n")
        }
        Catch{
            $rtb.SelectionColor = "Red"
            $rtb.AppendText("$_ `n")
        }
            
        $rtb.SelectionColor = "Green"
        $rtb.AppendText("Finished`n")
        $sync.SB.Enabled = $true
    }
    
    function Start-RSJob {
        
        $sync = [Hashtable]::Synchronized(@{ RTB = $rtb; SB = $buttonStart })
        
        $rsjob = [PowerShell]::Create().AddScript($script)
        
        $runspace = [RunspaceFactory]::CreateRunspace()
        $runspace.ApartmentState = "STA"
        $runspace.ThreadOptions = "ReuseThread"
        $runspace.Open()
        $runspace.SessionStateProxy.SetVariable("sync", $sync)
        
        $rsjob.Runspace = $runspace
        $rsjob.BeginInvoke()
        
    }
    
    
    
    
    Add-Type -AssemblyName System.Windows.Forms
    
    $buttonStartClick = {
        $this.Enabled = $false
        Start-RSJob
    }
    
    $form = New-Object System.Windows.Forms.Form
    $buttonStart = New-Object System.Windows.Forms.Button
    $form.Controls.Add($buttonStart)
    $buttonExit = New-Object System.Windows.Forms.Button
    $form.Controls.Add($buttonExit)
    $rtb = New-Object System.Windows.Forms.RichTextBox
    $form.Controls.Add($rtb)
    
    # Mainform
    $form.ClientSize = '381,339'
    $form.FormBorderStyle = 'FixedSingle'
    $form.MaximizeBox = $false
    $form.Name = 'MainForm'
    $form.StartPosition = 'CenterScreen'
    $form.Text = 'Restart Emby & DBV'
    $form.BackColor = 'LightGoldenrodYellow'
    $form.Font = 'Segoe UI Semibold 9.25'
    
    #
    #button_start
    #
    $buttonStart.FlatStyle = 'Flat'
    $buttonStart.Location = '120, 22'
    $buttonStart.Name = 'button_start'
    $buttonStart.Size = '136, 26'
    $buttonStart.TabIndex = 0
    $buttonStart.Text = 'Start'
    $buttonStart.add_Click({
            $this.Enabled = $false
            Start-RSJob
        })
    #
    #button_exit
    #
    $buttonExit.Location = '12,299'
    $buttonExit.Name = 'button_exit'
    $buttonExit.Size = '48,28'
    $buttonExit.TabIndex = 1
    $buttonExit.Text = 'Exit'
    $buttonExit.DialogResult = 'Ok'
    
    #
    #richTextBox1
    #
    $rtb.Location = '10,60'
    $rtb.Width = $form.ClientSize.Width - 20
    $rtb.Height = $form.ClientSize.Height - 100
    $rtb.Name = 'rtb'
    
    $form.ShowDialog()
    


    \_(ツ)_/

    • Marked as answer by DamianBz Sunday, August 19, 2018 4:24 PM
    Wednesday, December 6, 2017 7:20 PM
  • OK thanks, I'm going to work through this now.

    Why do you say that I don't understand forms ?

    This was created with Visual Studio 2017 & powershell tools pro - admittedly VS seems to use a different format (I don't fully understand why it seems to add loads of extra code when it doesn't seem to be needed) but I use it to create the physical form stuff, then use the POSH tools to build it into a single .ps1 file, which I then work on in Visual Studio Code.

    Thanks

    Damian  

    Wednesday, December 6, 2017 7:34 PM
  • You coded a form using someone's concept of how to convert C# forms to PowerShell.  The method I used eliminates half of the code.  You aslo didn't know which properties to set on controls or how a dialog is closed.

    Look very carefully at how I changed what you were doing. 

    You also set a control to "fill" but also added size and location. "Fill" does not use size and location.

    Forms are not simple but if you actually learn how Microsoft has designed them to be programmed they are actually quite easy to use.  Without a good understanding of forms you will write much more code and not really understand what is required and what is default.

    The changes I made will help point you to a simpler approach.  If you knew forms you would also understand why "Run" won't work correctly.


    \_(ツ)_/

    Wednesday, December 6, 2017 7:40 PM
  • Thanks jrv,

    Actually i did wonder why there were size settings in the rtb, but that was what was there from VS !

    Also I did have the exit button using the DialogResult method, but for some reason it wasn't wotking when I added the Runspace code.

    I guess this is the pitfall of trying to learn something purely from the internet .. not all of the info out there is correct !

    I'm going through your version now, trying to understand each stage.

    ...

    Actually... could I check something with you ..

    Under the $buttonStart region :

    $buttonStart.add_Click({
            $this.Enabled = $false
            Start-RSJob
        })

    you have Start-RSJob

    But further up :

    Add-Type -AssemblyName System.Windows.Forms
    
    $buttonStartClick = {
        $this.Enabled = $false
        Start-RSJob
    }

    There is another Start-RSJob ?

    Should there be two ? 

    My guess is that the one above is not needed ?

    Sorry, I feel embarrassed to be picking here, as you are the one that knows his stuff ! :) and i'm the numpty here !

    Cheers

    Damian

    Wednesday, December 6, 2017 8:11 PM
  • Download the trial version of Sapien PSS and build with it.  Dump the code to a PS1 and look at how they generate forms code.  It is neat, clean and simple and will help you to understand how forms work.

    https://www.sapien.com/software/trial_versions


    \_(ツ)_/


    • Edited by jrv Wednesday, December 6, 2017 8:28 PM
    Wednesday, December 6, 2017 8:27 PM
  • Yes i did try that a while ago, but before I could really get good use out of it .. it expired !

    And I can't justify spending that amount of money when A) I'm doing this off my own back - so company won't pay for it. B) Visual Studio CE is free (i did pay for the POSH tools) I just need to learn how to use it better. And C) all the devs at work use VS, so I want to be able to write apps to help my team, and other teams automate certain procedures or processes, and be able to get them passed by our apps guys for wider use.

    Don't get me wrong, i'd love to have the Sapien product - to be able to do the GUI, write the code and then package it up in one program would be great ! 

    Cheers

    Damian

    Wednesday, December 6, 2017 10:40 PM
  • Unfortunately VS does not create good forms for PowerShell use as it assumes code behind and sets up forms and not pure dialogs.  It will just slow you down.

    When I don't have PSS I just use notepad and copy a basic template as a starter then add controls. Of course I have a very good understanding of what each property, method and event is and how the whole work together.

    For anything more than a trivial form PSS becomes necessary.

    Good luck.  I hope frustration doesn't get to you before you become experienced in forms coding.  I would just use VS and C# as it can do anything that PS can do.

     


    \_(ツ)_/

    Wednesday, December 6, 2017 10:56 PM