Change InvokeRequired to True

Ask questions about creating Graphical User Interfaces (GUI) in PowerShell and using WinForms controls.
Forum rules
Do not post any licensing information in this forum.

Any code longer than three lines should be added as code using the 'Select Code' dropdown menu or attached as a file.
Post Reply
User avatar
Bender2010
Posts: 3
Joined: Thu Mar 22, 2018 8:03 am

Change InvokeRequired to True

Post by Bender2010 » Fri Nov 22, 2019 3:40 am

Hello,

I have a GUI with a label which is not visible ($false). I would like to visible the item with BeginInvoke(). So long the task is running, the item is visible and when finished not.

When I have understand, then I must change InvokeRequired to True, so I could change objects outsite my task.
https://docs.microsoft.com/en-us/dotnet ... keRequired

How I could change this settings for my label and other items? When I do this in my script ($label.InvokeRequired = $true), it´s not working while it´s a read only property.

PowerShell Studio 2019. 5.6.170
64 Bit

Best thanks for your assitent

Code: Select all

	# Runspace 
	$runspaceSpace = [RunspaceFactory]::CreateRunspace()
	$runspaceSpace.ApartmentState = 'STA'
	$runspaceSpace.ThreadOptions = 'UseNewThread'
	$runspaceSpace.Open()
	
	# PSInstance
	$PsInstanceSpace = [PowerShell]::Create()
	$PsInstanceSpace.Runspace = $runspace
	
	# Space
	$PsInstanceSpace.Runspace.SessionStateProxy.SetVariable("labelSpaceStatus", $labelSpaceStatus)
	$PsInstanceSpace.Runspace.SessionStateProxy.SetVariable("labelSpaceOK", $labelSpaceOK)
	$PsInstanceSpace.Runspace.SessionStateProxy.SetVariable("labelSpaceX", $labelSpaceX)
	$PsInstanceSpace.Runspace.SessionStateProxy.SetVariable("progressbarSpace", $progressbarSpace)
	
	#$labelSpaceOK.InvokeRequired = $true
	#$labelSpaceX.InvokeRequired = $true
	
	[void]$PsInstanceSpace.AddScript({
			#Place Code Here
			If ((Get-WMIObject -Class Win32_Logicaldisk -Namespace Root\CIMV2 -Filter "deviceid='C:'").FreeSpace -gt 31457280000)
			{
				$labelSpaceStatus.Text = "Success"
				$labelSpaceOK.Visible = $true #Show my label now
				$labelSpaceX.Visible = $false
			}
			else
			{
				$labelSpaceStatus.Text = "Failed"
				$labelSpaceOK.Visible = $false
				$labelSpaceX.Visible = $true
			}
			[System.Windows.Forms.MessageBox]::Show("Script is running", "Running")
			$progressbarSpace.Visible = $false
			$PsInstanceSpace.EndInvoke()
			$PsInstanceSpace.Dispose()
			$runspaceSpace.Close()
			[System.GC]::Collect()
		}).BeginInvoke()

jvierra
Posts: 14016
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: Change InvokeRequired to True

Post by jvierra » Fri Nov 22, 2019 3:58 am

Invoke is not required to change properties. It is only required for calling delegates. Just set the property. The synchash will handle threading issues.

You must use a synchash and not just assigned variables.

jvierra
Posts: 14016
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: Change InvokeRequired to True

Post by jvierra » Fri Nov 22, 2019 4:51 am

Here is the way to create a basic invokable script that builds and manages the runspace for you with correct default values and a synchash.

Since the "Visible" property is not really a simple property you would have tocreate a delegate that can calll the "Show()" method on the control. I can't remember the syntax for that in PowerShell right now.

The "InvokeRequired" is not needed here and is not a settable property. It is used so a thread can decide whether to directly access a control or if an "Invoke" is required.

See attached demo for how to code this.
Attachments
Demo-SimpleRunspace.psf
(31.69 KiB) Downloaded 9 times

jvierra
Posts: 14016
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: Change InvokeRequired to True

Post by jvierra » Fri Nov 22, 2019 5:02 am

Ok. I remembered the trick with PS. Here is how to call a delegate from a runspace and set the visible property to true.

Code: Select all

$buttonStart_Click={
    $synchash = @{
        Label = $label1
        Show = [action]{$label1.Visible = $true}
    }
    $psscript = {
        $synchash.Label.Invoke($synchash.Show)
        1..100 |
            ForEach-Object{
                $synchash.Label.Text = "$_ Runspace here"
                sleep 1
            }
    }
    
    # create a new PowerShell runspace
    $ps = [PowerShell]::Create()
    $ps.Runspace.SessionStateProxy.SetVariable('synchash',$synchash)
    $ps.AddScript($psscript)
    $ps.BeginInvoke()
}

jvierra
Posts: 14016
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: Change InvokeRequired to True

Post by jvierra » Fri Nov 22, 2019 6:46 pm

Here is a full example of how to manage a runspace including how to detect when it is complete and how to detect errors.
Attachments
Demo-SimpleRunspace2.psf
(32.72 KiB) Downloaded 8 times

Post Reply