我正在开发一个自定义的PowerShell状态线,并实现了一些很酷的功能:电池监控,wifi监控等等。不幸的是,这些更新往往很慢,因为它们需要调用Get-NetAdapterStatistics,获取wmi对象等等。慢叫。我试图通过启动作业生成子进程以允许后台轮询和更新共享变量,但无法弄清楚如何执行此操作。我找到的最好的替代品是一种IPC(如这里所描述的:Pipelining between two SEPARATE Powershell processes),但如果可能的话,我更愿意坚持使用传统的共享变量。有没有办法做到这一点?我发现的最好的替代方法是将变量作为参数传递,但这不允许轮询。
为了放弃,我知道这并不是PowerShell的设计目标,但我仍然想知道这是否可行。或者是编写将返回状态行的c / c ++二进制文件的最佳选择?写入文件(这似乎可能很慢)?如果您能够,或者您需要更多信息,请告诉我可能有用的内容。谢谢。
更多信息:
Start-Job -Name testJob -Script {
$testVar = "asdf"
}
Write-Host $testVar
# should output asdf
有没有办法做到这一点?我正在尝试做一些工作并返回一个变量。这怎么可能?我发现的唯一可行方法是:
$pipe = New-Object System.IO.Pipes.NamedPipeClientStream '.',"testPipe",'In'
Start-Job -Name testJob -Script {
$pipe = New-Object System.IO.Pipes.NamedPipeServerStream "testPipe",'Out'
$pipe.WaitForConnection()
$sw = New-Object System.IO.StreamWriter $pipe
$sw.AutoFlush = $true
$sw.writeLine("foo")
While ($true) {
# do looping and polling, then print stuff
$sw.writeLine($pollResult)
}
$sw.Dispose()
$pipe.Dispose()
}
$pipe.Connect()
$sr = New-Object System.IO.StreamReader $pipe
#when necessary, read info
$output = $sr.ReadLine()
$sr.Dispose()
$pipe.Dispose()
最大的缺点是它有点小问题。最重要的是,当我关闭powershell窗口时,我不知道如何关闭IPC管道(因为这是一个状态线),我最终导致“管道泄漏”导致高CPU使用率和PowerShell进程运行的背景。这至少不是直接后台作业写入文件的情况。显然,管道应该在删除最后一个引用时关闭,但后台作业在打开时继续运行。这是因为当PowerShell会等待与管道相关的事情(等待管道连接,完成写入线路等)时,powershell会话将挂起到无法ctrl-c'd的程度。
谢谢,如果我可以添加更多信息,请告诉我。
更新:我已经尝试使用空文件作为控制标志(我认为它比为每个设置解析一个文件更快),但我正在尝试使用作业返回VCS信息(这将更容易返回,并且快点)。关于如何解决这个问题的任何想法?我很难过。
注意:我标记了这个C#,因为powershell使用C#的管道功能,我希望有知识的人可以提供帮助。
Boe Prox在几年前做了一个excellent writeup。他还用PoshRSJob模块扩展了它。使用此模块可以很容易地处理。
#Create a synchronized hashtable
$sync = [hashtable]::Synchronized(@{
Time = ''
Stop = $false
Updater = ''
})
#create 5 RSJobs
1..5 | Start-RSJob -ScriptBlock {
param($sync) #accept $sync as a param
$updater = [Guid]::NewGuid() #unique id per job
while(-not $sync.Stop) { #run until told not to
$sync.Time = Get-Date
$sync.Updater = $updater
start-sleep -Seconds 1
}
} -ArgumentList $sync #pass $sync as a param
运行这会产生5个工作:
Id Name State HasMoreData HasErrors Command
-- ---- ----- ----------- --------- -------
1 Job1 Running False False ...
2 Job2 Running False False ...
3 Job3 Running False False ...
4 Job4 Running False False ...
5 Job5 Running False False ...
然后,您可以检查父进程中的$ sync,并看到它是从这些作业不断更新的。请注意,这些不仅仅是字符串表示,而是完整的成熟对象。
PS C:\> $sync
Name Value
---- -----
Time 4/22/2019 11:58:35 AM
Stop False
Updater 9ab28c51-2941-4866-a064-165b1ceca673
PS C:\> $sync
Name Value
---- -----
Time 4/22/2019 11:58:37 AM
Stop False
Updater 113e78a8-1774-4cdf-9638-7235109f0a0d
要终止工作,我们设置$sync.Stop = $true
PS C:\> Get-RSJob
Id Name State HasMoreData HasErrors Command
-- ---- ----- ----------- --------- -------
1 Job1 Completed False False ...
2 Job2 Completed False False ...
3 Job3 Completed False False ...
4 Job4 Completed False False ...
5 Job5 Completed False False ...