2016-02-08 109 views
0

这可能是一个难以回答的问题。我写了一个脚本来检查进程的响应属性。以可视化的脚本正在运行,我创建了一个窗体窗体,你可以看到哪个进程被监视。脚本完美运行,但我无法用我的winform做任何事情。无法最小化或关闭它,只要将光标移动到窗体,我的鼠标光标就会切换到沙漏符号。任何想法为什么?为什么我的WindowsForm在执行循环时没有响应

在WinForm也没有响应,当我注释掉while循环

这里是我的代码:

if ($ShowWindowsForm){ 
    $window = New-Object System.Windows.Forms.Form 
    $window.text = "Process Watcher" 
    $window.size = New-Object System.Drawing.Size(350,100) 
    $window.location = New-Object System.Drawing.Size(100,100) 
    $icon = [system.drawing.icon]::ExtractAssociatedIcon($PSHOME + "\powershell.exe") 
    $window.Icon = $Icon 
    $text = New-Object System.Windows.Forms.Label 
    $text.Text = "Folgender Prozess wird überwacht:`n$target.exe" 
    $text.location = New-Object System.Drawing.Size(10,10) 
    $text.AutoSize = $true 
    $window.Controls.Add($text) 
    $window.Show() 
} 
while (1) { 
    sleep -Milliseconds 100 
    if(!((get-process $target).Responding -eq $true)) { 
    #do stuff 
} 
+2

http://stackoverflow.com/questions/10794455/ powershell-freezing-gui –

+0

thx,将我的问题标记为重复 – SimonS

+4

很简单,实际上:一次只能在单个线程上发生一件事。你正在UI线程上运行一个循环,这会阻止任何UI的同时发生。这意味着你的应用程序变得愚蠢(变得无法响应)。解决方案是在后台线程上完成所有的处理。不确定Powershell是否具有类似内置的功能。如果没有,那么您应该使用为GUI编程设计的语言(如C#或VB.NET)来执行此操作。请注意,链接的问题可能是重复的,但答案是*糟糕的*建议。 –

回答

2

我得到了答案,现在,如果有人跑进了同样的问题,因为我有。

首先,如果你只是创建一个GUI并做一些处理,它们使用相同的线程。例如:

# Windows Form  
$window = New-Object System.Windows.Forms.Form 
$window.text = "Process Watcher" 
$window.size = New-Object System.Drawing.Size(350,100) 
$window.location = New-Object System.Drawing.Size(100,100) 
$window.ShowDialog() 

# Processing 
while (1) { # Do Stuff } 

PowerShell中现在将显示$window因为.ShowDialog()方法,但Windows窗体($window)将不会响应。这是因为你在显示Windows窗体对话框的同一线程中运行一个循环。

所以我们需要为循环创建一个后台任务,所以它有一个线程。这就是PowerShell的Start-Job cmdlet的用途。

假设您正在监视一个进程,并且想要在Windows窗体中将其可视化。您的代码如下所示:

$target = "firefox" 

# Job 
Start-Job -argumentlist $target { 
    param($target) 
    while ((get-process $target).Responding) {Sleep -Milliseconds 100} 
    if (!(get-process $target).Responding) {<# Do Stuff #>} 
} 

# Windows Form  
$window = New-Object System.Windows.Forms.Form 
$window.text = "Process Watcher" 
$window.size = New-Object System.Drawing.Size(350,100) 
$window.location = New-Object System.Drawing.Size(100,100) 
$window.ShowDialog() 

使用此代码,您的Windows窗体负责,并且您的循环在后台执行。我还希望通过此代码示例展示的是,您必须将您在作业脚本块之外声明的变量传递给-argumentlist参数和param()语句的作业。否则它将无法工作。

我希望这个答案会帮助别人,因为谷歌并没有真正提供一个好的答案,这个(或我只是没有找到一个很好的一个)