2

The original script/tool so far is 1000+ lines so I made a mock that represents my problem.

What this code basically does is create a Parent Thread with a GUI and its Start Button creates Child Threads that copies and executes files on remote computers. I want those Child Threads to update the Parent Thread's textbox with results. In the code, I've marked my attempts.

I've read about creating the GUI in a child thread and manipulating it through the parent thread but if I were to do that, I think I would have to move all the Functions and Events, that pertain to the GUI, to that child thread. And then the Start button (Child Thread Creator) would create a 2nd Gen Child Thread? It just put me in a loop, so I couldn't use that method. Or I could have the Child GUI thread somehow initiate processes in the Parent Thread? idk... is it possible to create a GUI's functions/events in the parent thread but executed from the child thread? idk...

Please provide any advice or solutions that I can consider to accomplish this.

EDIT: To recap the problem is that the child threads do not update the parent threads textbox.

#GUI
[XML]$XAML =
@"
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Name="Window" Title="Some tool you've never heard of" Height="450" Width="450" ResizeMode="CanMinimize">
    <Grid>
        <TextBox Name="Results" IsReadOnly="True" Margin="5,5,5,75" TextWrapping="Wrap" Background="Black" Foreground="White"/>
        <Button Name="Start" Content="Start" Margin="5,350,5,5" Cursor="Hand"/>
    </Grid>
</Window>
"@

[System.Void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')

$GUI = [Windows.Markup.XamlReader]::Load((New-Object System.Xml.XmlNodeReader $XAML))

ForEach ($Node in ($XAML.SelectNodes("//*[@Name]")))
{
    Set-Variable -Name "$($Node.Name)" -Value $GUI.FindName($Node.Name) -Scope Global
}

#Sync Hash Table - Attempt 2
$Global:SyncUIHash = [hashtable]::Synchronized(@{})
$Global:SyncUIHash.Window = $Window
$Global:SyncUIHash.Results = $Results

#RunSpacePool
$RunSpacePool = [RunSpaceFactory]::CreateRunspacePool(1,5)
$RunSpacePool.ApartmentState = "STA"
$RunSpacePool.Open()

#GUI Events
$Start.Add_Click({Start-Function})

#Functions
Function Start-Function
{
    ($PowerShell = [Powershell]::Create()).RunSpacePool = $RunspacePool

    $Parameters = @{
        Computer = "ComputerName"
        FileToExecute = "FilePath to file that will be executed"
        Arguments = "Arguments to be used on FileToExecute"
        TempDir = "Remote Computer's TempDir to Copy To"
        Results = $Results #Does not Work - Attempt 1
        SyncUIHash = $Global:SyncUIHash #Does not work - Attempt 3
    }

    [System.Void]$PowerShell.AddScript({
        Param (
            $Computer,
            $FileToExecute,
            $Arguments,
            $TempDir,
            $Results, #Does not work - Attempt 1
            $SyncUIHash #Does not work - Attempt 3
        )
        #Basically: Copy File to Remote Computer then Execute File

        $Results.Text += "Results of whole process." #Does not work - Attempt 1

        $SyncUIHash.Results.Text += "Results of whole process." # Does not work - Attempt 2 & 3

    }).AddParameters($Parameters)

    $PowerShell.BeginInvoke()
}

#Shows GUI
[System.Void] $GUI.ShowDialog()
  • Can you elaborate on your problem. What _does not work_? You have provided some code that seems to have a problem but you have not described the problem. – Martin Liversage Nov 10 '17 at 23:12
  • The problem is that the child threads do not update the parent threads textbox, basically. The main post has been updated as well. – Kyle Hewitt Nov 10 '17 at 23:44
  • It is not possible to update the GUI objects held by one thread from any other thread. That is by design to avoid a lot of inherent problems. However, you can still access those GUI objects from any thread. To update them, you will need to restore control back to the parent thread and have the parent thread update the GUI. – Sid Nov 11 '17 at 02:42
  • 1
    @RohinSidharth _It is not possible to update the GUI objects held by one thread from any other thread._ What's wwith pipelines and events? Sure it is in fact not updated by _another_ thread, but it's initiated by them. – Clijsters Nov 11 '17 at 11:33
  • 1
    Look at this :[PowerShell and WPF: Writing Data to a UI From a Different Runspace](https://learn-powershell.net/2012/10/14/powershell-and-wpf-writing-data-to-a-ui-from-a-different-runspace/) – Manu Nov 11 '17 at 19:00
  • @Manu I was able to get what I needed using a modified version of it, thanks! – Kyle Hewitt Nov 12 '17 at 02:18

0 Answers0