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()