我最近开始创建包含GUI的Powershell脚本。
为了防止GUI冻结,我创建了一个后台作业,其中运行了我的函数“ xyz” ...
我想捕获一个特定的窗口标题。如果此窗口关闭,则应触发if。
现在,这个脚本的问题如下:
如果我运行脚本时未将其放在后台作业中,则会注意到if语句并返回我想要的值。
如果我运行脚本并将任务放入后台作业,则该作业不会停止并且不会识别if语句。
有人可以解决这个问题吗?
Function xyz {
$global:TitleArray = @("Termius - Hosts","Some Window Title","...")
$global:WindowClosed = $false
$global:TitleArray | Out-Host
$global:Job = start-job -Name FindGame {
Do {
(Get-Process | Where-Object {$_.MainWindowTitle -ne ""} | Select-Object MainWindowTitle) | % {
if($_.MainWindowTitle -in $global:TitleArray){
$global:WindowFound = $true
$global:FoundWindowName = $_.MainWindowTitle
do {
$WindowArray = @()
(Get-Process | Where-Object {$_.MainWindowTitle -ne ""} | Select-Object MainWindowTitle) | % {
$WindowArray += $_.MainWindowTitle
}
if($global:FoundWindowName -notin $WindowArray){
$global:WindowClosed = $true
}
Sleep 1
} while ($global:WindowClosed -ne $true)
}
if($global:WindowClosed){
$Global:FoundWindowName | Out-Host
exit
}
Sleep 1
}
} while ($true)
}
}
xyz
答案 0 :(得分:5)
PowerShell作业(类型为PSJob)在单独的进程中运行,因此它们无法访问调用程序环境,甚至无法访问Global范围内的变量。
要获取有关作业的信息,应在作业的脚本块中定义一个param()
块,然后使用-ArgumentList
的{{1}}参数发送值。请注意,这是值的一次传递。
要从作业中返回数据,只需像往常一样通过管道将其发送出去,然后访问数据就需要使用Start-Job
来确定作业是否“具有附加数据”,以及是否确实如此,您可以使用Get-Job
来检索该数据。
不幸的是,这一切意味着您仍然需要主线程来管理后台作业,从而无法达到目的。
您可以look into Register-ObjectEvent
instead,并将其与可能引发事件的某种.Net对象配对。这些似乎确实可以在进程中运行,但除此之外,它们还可以基于您可能真正感兴趣的事件而触发,而无需管理循环。
因此,最简单的方法也许只是为了结识,您可以look at a timer example where a timer object fires the event on an interval:
Receive-Job
但是Microsoft页面上的示例甚至包括监视来自WMI的流程创建事件,因此和/或流程退出事件(?)可能值得研究。