0

Lately I've been messing around with WinForms GUI run in its own runspace. What I'm trying to accomplish is to Update text property of button via click event of another button. Code seen below.

$syncHash = [hashtable]::Synchronized(@{})

$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = "STA"
$newRunspace.ThreadOptions = "ReuseThread"         
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash) 
         
$psCmd = [PowerShell]::Create().AddScript({ 
  
$syncHash.main2 = New-Object System.Windows.Forms.Form
$syncHash.main2.Icon = $icon3
$syncHash.main2.ClientSize = '220,200'
$syncHash.main2.MinimizeBox = $false
$syncHash.main2.MaximizeBox = $false
$syncHash.main2.Text = 'Options'  
$syncHash.main2.AutoSize = $false  
$syncHash.main2.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
$syncHash.main2.TopMost = $true
 
$syncHash.label1 = New-Object System.Windows.Forms.Label
$syncHash.label1.Location = New-Object System.Drawing.Point(10,10)
$syncHash.label1.Text = 'Button Name'
$syncHash.label1.BorderStyle = [System.Windows.Forms.BorderStyle]::Fixed3D
$syncHash.label1.TextAlign = 'MiddleCenter'
$syncHash.label1.Size = New-Object System.Drawing.Size(100,30)
 
$syncHash.label2 = New-Object System.Windows.Forms.Label
$syncHash.label2.Location = New-Object System.Drawing.Point(10,41)
$syncHash.label2.Text = $settings.buttons.1
$syncHash.label2.BorderStyle = [System.Windows.Forms.BorderStyle]::Fixed3D
$syncHash.label2.TextAlign = 'MiddleCenter'
$syncHash.label2.Size = New-Object System.Drawing.Size(100,30)

$syncHash.label3 = New-Object System.Windows.Forms.Label
$syncHash.label3.Location = New-Object System.Drawing.Point(10,71)
$syncHash.label3.Text = $settings.buttons.2
$syncHash.label3.BorderStyle = [System.Windows.Forms.BorderStyle]::Fixed3D
$syncHash.label3.TextAlign = 'MiddleCenter'
$syncHash.label3.Size = New-Object System.Drawing.Size(100,30)
 
$syncHash.label4 = New-Object System.Windows.Forms.Label
$syncHash.label4.Location = New-Object System.Drawing.Point(111,10)
$syncHash.label4.Text = 'Text to Copy'
$syncHash.label4.BorderStyle = [System.Windows.Forms.BorderStyle]::Fixed3D
$syncHash.label4.TextAlign = 'MiddleLeft'
$syncHash.label4.Size = New-Object System.Drawing.Size(100,30)

$syncHash.label5 = New-Object System.Windows.Forms.TextBox
$syncHash.label5.Location = New-Object System.Drawing.Point(111,41)
$syncHash.label5.Text = $settings.Text.1
$syncHash.label5.BorderStyle = [System.Windows.Forms.BorderStyle]::Fixed3D
$syncHash.label5.Multiline = $true
$syncHash.label5.Size = New-Object System.Drawing.Size(100,30)
 
$syncHash.label6 = [System.Windows.Forms.TextBox]::new()
$syncHash.label6.Location = [System.Drawing.Point]::new(111,71)
$syncHash.label6.BorderStyle = [System.Windows.Forms.BorderStyle]::Fixed3D
$syncHash.label6.Text = [PSCredential]::new(0, ($settings.Text.2|ConvertTo-SecureString)).GetNetworkCredential().Password
$syncHash.label6.Multiline = $true
$syncHash.label6.Size = [System.Drawing.Size]::new(100,30)
 
$syncHash.button1 = New-Object System.Windows.Forms.Button
$syncHash.button1.Text = 'Save'
$syncHash.button1.Location = New-Object System.Drawing.Point (10,101)
$syncHash.button1.Size = New-Object System.Drawing.Size (100,30)
 
$syncHash.button2 = New-Object System.Windows.Forms.Button
$syncHash.button2.Text = 'Close'
$syncHash.button2.Location = New-Object System.Drawing.Point (111,101)
$syncHash.button2.Size = New-Object System.Drawing.Size (100,30)




$button1.Add_Click({


$syncHash.button2.Text = "ASD"

})

$syncHash.button2.Add_Click({
$syncHash.main2.Close()|out-null
})

$syncHash.main2.Controls.AddRange(@(
$syncHash.label1, 
$syncHash.label2, 
$syncHash.label3, 
$syncHash.label4, 
$syncHash.label5, 
$syncHash.label6,
$syncHash.button1, 
$syncHash.button2)) 
$syncHash.main2.ShowDialog()
})
$psCmd.Runspace = $newRunspace
$data = $psCmd.BeginInvoke()

This does nothing in the runspace.

$syncHash.button2.Text = "ASD"

However, if I run a version of the code, where no synchronised hashtable is used and avery object is saved in ot's own variable (i.e $main2 = New-Object System.Windows.Forms.Form instead of $syncHash.main2 = New-Object System.Windows.Forms.Form). Button Click works and the text changes. What's more frustrationg is that if I update $syncHash.button2.Text from outside of runspace (i.e. from terminal in ISE) it magically works. Please help

[EDIT] I tried using a function that uses [ref] accelerator, hoping it would update the value, but that also does nothing.

3
  • 1
    Does this answer your question? stackoverflow.com/questions/72724246/… Commented Dec 19, 2023 at 12:48
  • Yes and no. You solutions shows me how to accomplish what I want, just not the way I wanted it. Thank you Commented Dec 19, 2023 at 14:25
  • 1
    Recommendation is to run GUI app in the main thread and actions / event handlers in a separated runspace, seem to be opposed as what you're doing Commented Dec 19, 2023 at 14:28

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.