简体   繁体   English

在Powershell中,在文本框中显示服务器重新启动检查脚本,将冻结WPF GUI

[英]In Powershell, displaying a server restart check script in the textbox, freezes the WPF GUI

I created a PowerShell script that uses a WPF GUI. 我创建了使用WPF GUI的PowerShell脚本。 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. 然后,将在Button.Add_Click运行用于检查重新启动过程的脚本,结果将显示在文本框中。

The problem is that the GUI freezes until Button.Add_Click is finished and will then show the info in the textbox. 问题在于GUI冻结,直到Button.Add_Click完成,然后将在文本框中显示信息。

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. ComboBox.add_SelectionChanged部分中,我无法获取所选的组合框内容。 I want to store the content in a variable $computer . 我要将内容存储在变量$computer

In the Button.Add_Click section I can't write to the textbox. Button.Add_Click部分中,我无法写入文本框。 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. 当我使用$Global:uiHash.Window.Dispatcher.Invoke([action] $Global:uiHash.TextBox.AppendText("Check that reboot is initiated properly n”)},“ Normal”)`时,GUI冻结。

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&#xD;&#xA;" 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++) { 对于($ i = 0; $ i -le $ max_iterations; $ i ++){
if (!(ping-host -pc $computer )) { 如果(!(ping-host -pc $ computer)){
break 打破
} }
Start-Sleep -Seconds 5 开始睡眠-第二个5
if($i -eq $max_iterations) { if($ i -eq $ max_iterations){
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("$computer never went down in last $timeout minutes n")},"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在最近的$ timeout分钟内永不停机n")},"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") $ Global:uiHash.Window.Dispatcher.Invoke([操作] {$ Global:uiHash.TextBox.AppendText(“ $ computer仍然在线;检查重新启动是否已正确启动`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 status n")},"Normal")
$status = "offline
$ Global:uiHash.Window.Dispatcher.Invoke([操作] {$ Global:uiHash.TextBox.AppendText(“ $计算机离线;监视在线状态n")},"Normal")
$status = "offline
n")},"Normal")
$status = "offline
n")},"Normal")
$status = "offline
n"
n")},"Normal")
$status = "offline
n”

} }

for ($i=0; $i -le $max_iterations; $i++) { 对于($ i = 0; $ i -le $ max_iterations; $ i ++){
if ((ping-host -pc $computer )) { 如果((ping-host -pc $ computer)){
break 打破
} }

Start-Sleep -Seconds 5 开始睡眠-第二个5
if($i -eq $max_iterations) { 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 seconds 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(“您的计算机在最近的$ MAX_PINGTIME秒内从不恢复在线n")},"Normal")
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("Check that nothing is preventing starup
n")},"Normal")
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("Check that nothing is preventing starup
n")},"Normal")
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("Check that nothing is preventing starup
n")},"Normal")
n")},"Normal")
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("Check that nothing is preventing starup
n”)},“ Normal”)

$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.TextBox.AppendText("$Computer is NOT coming online; Something is preventing its startup`n")},"Normal") $ Global:uiHash.Window.Dispatcher.Invoke([action] {$ Global:uiHash.TextBox.AppendText(“ $ Computer无法上线;某些原因阻止了其启动`n”)},“ Normal”)
exit 出口
} }

}            

 $Global:uiHash.Window.Dispatcher.Invoke([action]  
 {$Global:uiHash.TextBox.AppendText("Your computer is Online Now; Task done; 
 exiting")},"Normal")            


 })

The reason that the GUI freeze is that the job you are running is in the same instance. GUI冻结的原因是您正在运行的作业在同一实例中。 Since the GUI runs in the same instance it will have to wait until whatever code is running is done before it can go back to taking new input. 由于GUI在同一实例中运行,因此必须等到所有代码运行完毕后,才能返回新的输入。

You could try and solve this running the code you want to execute when you click the button as a job, this way the code will run in a new process on the machine and not block the session the GUI is running in. 您可以尝试解决此问题,并在单击按钮作为作业时运行要执行的代码,这样,代码将在计算机上的新进程中运行,而不会阻止GUI在其中运行的会话。

This can be done with the Start-Job cmdlet 这可以通过Start-Job cmdlet完成

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM