2016-02-08 150 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()語句的作業。否則它將無法工作。

我希望這個答案會幫助別人,因爲谷歌並沒有真正提供一個好的答案,這個(或我只是沒有找到一個很好的一個)