Author Posts

May 30, 2017 at 11:08 pm

Hey guys,

Been struggling to get my head round this for a few weeks now so I'm finally giving in and asking for help!

I'm creating a GUI using WPF, formatted as XML, and I'm trying to use PoshRSJob for backgrounding tasks, etc, with a Synchronized Hashtable to share data between runspaces...

I'm struggling to understand how I need to format things – I'll show you what I have so far.

I have this to load the App.xaml file generated by Visual Studio and I'm fairly sure this is OK:

function Get-XamlObject
{
	[CmdletBinding()]
	param (
		[Parameter(Position = 0,
				   Mandatory = $true,
				   ValuefromPipelineByPropertyName = $true,
				   ValuefromPipeline = $true)]
		[Alias("FullName")]
		[System.String[]]$Path
	)

	BEGIN
	{
		Set-StrictMode -Version Latest

		$wpfObjects = @{ }
		Add-Type -AssemblyName presentationframework, presentationcore

	} #BEGIN

	PROCESS
	{
		try
		{
			foreach ($xamlFile in $Path)
			{
				#Change content of Xaml file to be a set of powershell GUI objects
				$inputXML = Get-Content -Path $xamlFile -ErrorAction Stop
				$inputXMLClean = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace 'x:Class=".*?"', '' -replace 'd:DesignHeight="\d*?"', '' -replace 'd:DesignWidth="\d*?"', ''
				[xml]$xaml = $inputXMLClean
				$reader = New-Object System.Xml.XmlNodeReader $xaml -ErrorAction Stop
				$tempform = [Windows.Markup.XamlReader]::Load($reader)

				#Grab named objects from tree and put in a flat structure
				$namedNodes = $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]")
				$namedNodes | ForEach-Object {

					$wpfObjects.Add($_.Name, $tempform.FindName($_.Name))

				} #foreach-object
			} #foreach xamlpath
		} #try
		catch
		{
			throw $error[0]
		} #catch
	} #PROCESS

	END
	{
		Write-Output $wpfObjects
	} #END
}

$path = '*path to folder containing xaml files*'

This is where I'm not so sure... I'll comment the code with what I'm trying to do with each section – hoping someone can tell me where I'm going wrong!

#creating the hashtable
$SyncHash = [hashtable]::Synchronized(@{})

#adding the xaml code to the hashtable just created
$syncHash.wpf = Get-ChildItem -Path $path -Filter *.xaml -file | Where-Object { $_.Name -ne 'App.xaml' } | Get-XamlObject

#scriptblock for RSJob (not really understanding what needs to be put in here and what doesn't)
$ScriptBlock = {
    Param($SyncHash)
    #something to do with setting the hashtable to the syncroot properly (?)
    [System.Threading.Monitor]::Enter($SyncHash.SyncRoot)

    [pscustomobject] @{

#I have various functions like this to show different pages, calculate things, etc, this is just an example of the kind of thing that they do
function Get-Results {
    $script:syncHash.home_Grid.Visibility = 'Collapsed'
    $script:syncHash.processing_Grid.Visibility = 'Collapsed'
    $script:syncHash.results_Grid.Visibility = 'Visible'
}

function Update-ProgressBar {
    while ($script:syncHash.displayThreatLevel -lt $script:syncHash.threatLevel) {
        Write-Output $script:syncHash.displayThreatLevel $script:syncHash.threatLevel
        $script:syncHash.displayThreatLevel += 1
        Start-Sleep -Milliseconds 100
        Display-ThreatLevel
    }
}

    $SyncHash.Email_Check.ShowDialog() | Out-Null

    [System.Threading.Monitor]::Exit($SyncHash.SyncRoot)
    }
}

Start-RSJob -Name {$_} -ScriptBlock $ScriptBlock -ArgumentList $wpf -FunctionsToLoad Get-Home |
Wait-RSJob -ShowProgress

May 31, 2017 at 11:50 am

Here is my test

During operation, the UI responsiveness leaves much to be desired due to Dispatcher.Invoke()
🙁

may be callbacks should be implemented through System.Windows.Threading.DispatcherTimer