XAML issue - Creating a function

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?



#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 {

    #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
        $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

                Param ($logName, $debug, $logging, $code) #pass variables into runspace
                    logName = $logName
                    debug = $debug
                    logging = $logging
                    code = $code
                #unique code to run inside new runspace 


        #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 = @" 

    $guiTitleBar = @"
        <Label Name="incidentTitle" Content="Report Incident" FontWeight="Normal" Background="red" Foreground="White" Width="Auto" HorizontalContentAlignment="Center"/>

    $guiBody = @"
            <RowDefinition Height="1*" />
            <RowDefinition Height="1*" />
            <RowDefinition Height="10" />
            <RowDefinition Height="1*" />
            <RowDefinition Height="1*" />
        <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 = @"
            <RowDefinition Height="1*" />
            <RowDefinition Height="1*" />

        <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

    #Create GUI
    $incidentXAML=(New-Object System.Xml.XmlNodeReader $guiStyle)
    $sync.incidentWindow =[Windows.Markup.XamlReader]::Load($incidentXAML)
    $sync.incidentClose = $false

    #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


So if I replace line 59 with the contents of $code at line 78, it all works swimmingly, but that reduces the effectiveness of the function

I can save the contents of $code at line 78 into a script .ps1 file and import it at line 59 and that works fine too

It’s only if I create a subscript of that code and then try and import it to the function that it doesn’t work




here’s the guiStyle.ps1 script contents if you need to run my code above

[xml]$guiStyle = $null

[xml]$guiStyle = @"  
    x:Name="Window" Title="" SizeToContent="WidthAndHeight" $guiPosition WindowStyle="None" ResizeMode="NoResize" AllowsTransparency="True" Background="Transparent" Opacity="1" Topmost="True" ShowInTaskbar="False">
        <Border x:Name="MainBorder" Margin="10" CornerRadius="8" BorderThickness="0" BorderBrush="Black" Padding="0" >
                <DropShadowEffect x:Name="DSE" Color="Black" Direction="270" BlurRadius="20" ShadowDepth="3" Opacity="0.6" />
                <EventTrigger RoutedEvent="Window.Loaded">
                            <DoubleAnimation Storyboard.TargetName="DSE" Storyboard.TargetProperty="ShadowDepth" From="0" To="3" Duration="0:0:1" AutoReverse="False" />
                            <DoubleAnimation Storyboard.TargetName="DSE" Storyboard.TargetProperty="BlurRadius" From="0" To="20" Duration="0:0:1" AutoReverse="False" />
                <Border Name="Mask" CornerRadius="8" Background="White" />
                <Grid x:Name="Grid" Background="White">
                    <VisualBrush Visual="{Binding ElementName=Mask}"/>
                    <StackPanel Name="StackPanel">
                        <Grid Margin="0,0,0,0" HorizontalAlignment="Center" Width="Auto">
                            <StackPanel HorizontalAlignment="Left" Height="Auto" VerticalAlignment="Top" Width="Auto ">
                                <Grid Height="Auto" VerticalAlignment="Top" Width="Auto">

                                <Grid Height="Auto" VerticalAlignment="Top" Width="Auto" Background="White">

                                <Grid Height="Auto" VerticalAlignment="Top" Width="Auto" Background="White">