Hi All,
I’m trying to tidy up my code and one part is to create a function or module for my runspace creation to reduce repetition of code.
If I attempt to import the XAML and related code into the function, the code executes, but no GUI.
If I past the XAML and related code into the function it all works normally
I know there are issues with adding a script and XAML, but there must be a workaround to this?
Thanks
James
#Create a synchronised hashtable to share variables between runspaces if required
If($sync.count -lt 1){$sync = [hashtable]::Synchronized(@{})}
#Dynamically generate runspaces and related control variables
Function createRunspace {
param(
$shortName,
$code,
$debug
)
#name of runspace set manually or obtained from code
$runspaceName = $shortName + "CPRunspace"
$runspaceCmd = $shortName + "Cmd"
$runspaceInvoke = $shortName + "Invoke"
$runspaceClose = $shortName + "Close"
#define variable if required
If($debug){
$path = $sync.path = $PSScriptRoot
$sync.PCUser = $env:USERNAME
$sync.alertFontSize = 16
$sync.popupDuration = 10 #How long in seconds should the extend popup stay on screen
}Else{$path = $sync.path}
#If runspace isnt already running, create and run custom code within it
$activeRunspaces = Get-Runspace
If((Get-Runspace).name -notcontains $runspaceName){
#create dynamically named runspace
New-Variable -Name $runspaceName -PassThru -Force -Value ([runspacefactory]::CreateRunspace())
(Get-Variable -Name $runspaceName -ValueOnly).ApartmentState = "STA"
(Get-Variable -Name $runspaceName -ValueOnly).ThreadOptions = "ReuseThread"
(Get-Variable -Name $runspaceName -ValueOnly).Name = "$runspaceName"
(Get-Variable -Name $runspaceName -ValueOnly).open()
(Get-Variable -Name $runspaceName -ValueOnly).SessionStateProxy.SetVariable("sync",$sync)
#script template that allows us to pass through the custom code and any other required local variables
$scriptTemplate = {
#local Variables to pass into Runspace
$ParamList = @{
logName = $logName
debug = $debug
logging = $logging
code = $code
}
[PowerShell]::Create().AddScript({
Param ($logName, $debug, $logging, $code) #pass variables into runspace
[pscustomobject]@{
logName = $logName
debug = $debug
logging = $logging
code = $code
}
#unique code to run inside new runspace
.$code
}).AddParameters($ParamList)
}
#create dynamically named script variable
New-Variable -Name $runspaceCmd -PassThru -Force -Value ( .$scriptTemplate )
#Invoke script to run in the new Runspace
(Get-Variable -Name $runspaceCmd -ValueOnly).Runspace = (Get-Variable -Name $runspaceName -ValueOnly)
$runspaceInvoke = (Get-Variable -Name $runspaceCmd -ValueOnly).BeginInvoke(),"Background"
Start-Sleep -Milliseconds 200
}
}
$shortName = "incident" #runspace shortname
$debug = $true #debugging?
#code to run inside the new runspace
$code = {
Add-Type -AssemblyName PresentationFramework
$guiPosition = @"
WindowStartupLocation="CenterScreen"
"@
$guiTitleBar = @"
<Label Name="incidentTitle" Content="Report Incident" FontWeight="Normal" Background="red" Foreground="White" Width="Auto" HorizontalContentAlignment="Center"/>
"@
$guiBody = @"
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
<RowDefinition Height="10" />
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Label Name="Report" Grid.Row="0" Content="Select the Incident Severity" FontWeight="Normal" Foreground="Black" Width="Auto" Margin="5,5,5,0"/>
<ComboBox Name="incidentSeverity" Grid.Row="1" Width="Auto" Margin="5,5,5,5"/>
<Label Name="Notes" Grid.Row="3" Content="Incident Notes" FontWeight="Normal" Foreground="Black" Width="Auto" Margin="5,5,5,0"/>
<TextBox Name="incidentNotes" Grid.Row="4" TextWrapping="Wrap" Width="Auto" Margin="5,5,5,5"/>
"@
$guiButtons = @"
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Button Name="btnIncident" Content="Report Incident w/o Screenshot" Grid.Row="0" Background="#f5f5f5" FontWeight="normal" BorderBrush="{x:Null}" BorderThickness = "0" Margin="5,15,5,5" Width="Auto"/>
<Button Name="btnScreenshot" Content="Report Incident with Screenshot" Grid.Row="1" FontWeight="Normal" Background="#f5f5f5" BorderBrush="{x:Null}" BorderThickness = "0" Margin="5,15,5,5" Width="Auto"/>
"@
#load gui style
."$($sync.Path)\guiStyle.ps1"
#Create GUI
$incidentXAML=(New-Object System.Xml.XmlNodeReader $guiStyle)
$sync.incidentWindow =[Windows.Markup.XamlReader]::Load($incidentXAML)
$sync.incidentClose = $false
[System.Media.SystemSounds]::Exclamation.Play()
#show dialog window, wrapped in an async variable to handle errors
$incidentAsync = $sync.incidentWindow.Dispatcher.InvokeAsync({
$sync.incidentWindow.ShowDialog() | Out-Null
})
$incidentAsync.Wait() | Out-Null
#show dialog window, wrapped in an async variable to handle errors
}
#create the runspace with custom code
createRunspace -shortName "shortName" -code $code -debug $true