为什么我的 WindowsForm 在执行循环时没有响应

Sim*_*onS 4 powershell winforms

这可能是一个很难回答的问题。我写了一个脚本来检查进程的响应属性。为了可视化脚本正在运行,我创建了一个 Windows 窗体,您可以在其中查看正在监视的进程。该脚本运行良好,但我无法对我的 winform 执行任何操作。无法最小化或关闭它,一旦我将光标移动到 windowsform,我的鼠标光标就会切换到沙漏符号。任何想法为什么?

当我注释掉 while 循环时,winform 也没有响应

这是我的代码:

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
}
Run Code Online (Sandbox Code Playgroud)

Sim*_*onS 5

我现在得到了答案,如果有人遇到和我一样的问题。

首先,如果你只是创建一个 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 }
Run Code Online (Sandbox Code Playgroud)

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

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

假设您正在监视一个进程,并希望在 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()
Run Code Online (Sandbox Code Playgroud)

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

我希望这个答案能帮助某人,因为谷歌并没有真正给出一个好的答案(或者我只是没有找到一个好的答案)