I created a PowerShell script that uses a WPF GUI. It has the option to choose a server from a combobox (more servers will be added later). The chosen server can be rebooted by clicking on the reboot button. Then a script, that will check the reboot procedure, will run in Button.Add_Click
and the results will be shown in a textbox.
The problem is that the GUI freezes until Button.Add_Click
is finished and will then show the info in the textbox.
I tried to solve this by implementing a runspace. But now I run into new problems.
In the ComboBox.add_SelectionChanged
section I cannot get the selected combobox content. I want to store the content in a variable $computer
.
In the Button.Add_Click
section I can’t write to the textbox. When I use $Global:uiHash.Window.Dispatcher.Invoke([action]
$Global:uiHash.TextBox.AppendText("Check that reboot is initiated properly
n")},"Normal")` then the GUI freezes.
Here is the full code:
$Global:uiHash = [hashtable]::Synchronized(@{})
$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = "STA"
$newRunspace.ThreadOptions = "ReuseThread"
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable("uiHash",$Global:uiHash)
$psCmd = [PowerShell]::Create().AddScript({
$Global:uiHash.Error = $Error
Add-Type -AssemblyName PresentationFramework,PresentationCore,WindowsBase
$xaml = @"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="CSS Server Reboot" Height="450" Width="800">
<Grid>
<ComboBox Name="Server_Combobox" HorizontalAlignment="Left" Margin="240,107,0,0" VerticalAlignment="Top" Width="120">
<ComboBoxItem Name="Server1">10.15.12.148</ComboBoxItem>
</ComboBox>
<Label Name="Title_Label" Content="CSS – Console Quentris, Server Reboot
" HorizontalAlignment="Left" Margin="240,41,0,0" VerticalAlignment="Top" Height="34" Width="284" FontSize="16"/>
<Button Name="Reboot_Button" Content="Reboot" HorizontalAlignment="Left" Margin="449,107,0,0" VerticalAlignment="Top" Width="75"/>
<TextBox Name="Reboot_Textbox" Grid.Column="1" HorizontalAlignment="Left" Height="173" Margin="81,180,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="294"/>
</Grid>
"@
$Global:uiHash.Window=[Windows.Markup.XamlReader]::Parse($xaml )
$Global:uiHash.TextBox = $Global:uiHash.window.FindName("Reboot_Textbox")
$Global:uiHash.Button = $Global:uiHash.window.FindName("Reboot_Button")
$Global:uiHash.ComboBox = $Global:uiHash.window.FindName("Server_Combobox")
$Global:uiHash.Window.ShowDialog() | out-null
})
$psCmd.Runspace = $newRunspace
$handle = $psCmd.BeginInvoke()
Start-Sleep -Milliseconds 100
$computer = ""
$Global:uiHash.ComboBox.add_SelectionChanged({
$Script:computer = $Global:uiHash.Combobox.SelectedItem.Content
})
$Global:uiHash.Button.Add_Click({
$Username = 'xxxx'
$Password = 'xxxx'
$pass = ConvertTo-SecureString -AsPlainText $Password -Force
$SecureString = $pass
$MySecureCreds = New-Object -TypeName
System.Management.Automation.PSCredential -ArgumentList
$Username,$SecureString
Restart-Computer -ComputerName $computer -Force -Credential $MySecureCreds
$timeout=5
$MAX_PINGTIME = $timeout * 60
$max_iterations = $MAX_PINGTIME/5
$Notification_timeout = 10 # in seconds
function ping-host {
param($pc)
$status = Get-WmiObject -Class Win32_PingStatus -Filter "Address='$pc'"
if( $status.statuscode -eq 0) {
return 1
} else {
return 0
}
}
if(ping-host -pc $computer) {
$status = "online`n"
for ($i=0; $i -le $max_iterations; $i++) {
if (!(ping-host -pc $computer )) {
break
}
Start-Sleep -Seconds 5
if($i -eq $max_iterations) {
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("$computer never went down in last $timeout minutesn")},"Normal")
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("Check that reboot is initiated properly
n")},"Normal")
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("$computer is still ONLINE; Check that reboot is initiated properly`n")},"Normal")
exit
}
}
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("$computer is offline now; monitoring for online status`n")},"Normal")
} else {
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("$computer is offline; Monitoring for online statusn")},"Normal")
n"
$status = "offline
}
for ($i=0; $i -le $max_iterations; $i++) {
if ((ping-host -pc $computer )) {
break
}
Start-Sleep -Seconds 5
if($i -eq $max_iterations) {
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("Your computer never came back online in last $MAX_PINGTIME secondsn")},"Normal")
n")},"Normal")
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("Check that nothing is preventing starup
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("$Computer is NOT coming online; Something is preventing its startup`n")},"Normal")
exit
}
}
$Global:uiHash.Window.Dispatcher.Invoke([action]
{$Global:uiHash.TextBox.AppendText("Your computer is Online Now; Task done;
exiting")},"Normal")
})