我创建了一个使用WPF GUI的PowerShell脚本。它具有从组合框中选择服务器的选项(以后将添加更多服务器)。单击重新启动按钮可以重新启动所选的服务器。然后将在Button.Add_Click
中运行将检查重新引导过程的脚本,并且结果将显示在文本框中。
问题是GUI冻结,直到Button.Add_Click
完成,然后在文本框中显示信息。
我试图通过实现运行空间来解决此问题。但是现在我遇到了新的问题。
在ComboBox.add_SelectionChanged
部分中,我无法获取所选的组合框内容。我想将内容存储在变量$computer
中。
在Button.Add_Click
部分中,我无法写入文本框。当我使用$Global:uiHash.Window.Dispatcher.Invoke([action]
$Global:uiHash.TextBox.AppendText("Check that reboot is initiated properly
n“)},” Normal“)`时,GUI冻结。
这是完整的代码:
$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)){
休息
}
开始睡眠-第二个5
if($ i -eq $ max_iterations){
$ Global:uiHash.Window.Dispatcher.Invoke([操作] {$ Global:uiHash.TextBox.AppendText(“ $ computer在过去的$ timeout分钟内从未停机n")},"Normal")
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("Check that reboot is initiated properly
n”)},“ Normal”)< br />
$ Global:uiHash.Window.Dispatcher.Invoke([操作] {$ Global:uiHash.TextBox.AppendText(“ $ computer仍然在线;检查重新启动是否已正确启动`n”)},“ Normal”)
退出
}
}
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("$computer is offline now; monitoring for online status`n")},"Normal")
}其他{
$ Global:uiHash.Window.Dispatcher.Invoke([操作] {$ Global:uiHash.TextBox.AppendText(“ $计算机离线;监视在线状态n")},"Normal")
n”
$status = "offline
}
for($ i = 0; $ i -le $ max_iterations; $ i ++){
如果((ping-host -pc $ computer)){
休息
}
开始睡眠-第二个5
if($ i -eq $ max_iterations){
$ Global:uiHash.Window.Dispatcher.Invoke([action] {$ Global:uiHash.TextBox.AppendText(“您的计算机在过去的$ MAX_PINGTIME秒内从未恢复在线n")},"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无法上线;某些原因阻止了其启动`n”)},“ Normal”)
退出
}
}
$Global:uiHash.Window.Dispatcher.Invoke([action]
{$Global:uiHash.TextBox.AppendText("Your computer is Online Now; Task done;
exiting")},"Normal")
})
答案 0 :(得分:0)
GUI冻结的原因是您正在运行的作业在同一实例中。 由于GUI在同一实例中运行,因此必须等到所有代码运行完毕后,才能返回新的输入。
您可以尝试解决此问题,并在单击按钮作为作业时运行要执行的代码,这样,代码将在计算机上的新进程中运行,而不会阻止GUI在其中运行的会话。 / p>
这可以通过Start-Job cmdlet
完成