gpt4 book ai didi

shell - PowerShell 异步计时器事件在测试控制台之外不起作用

转载 作者:行者123 更新时间:2023-12-04 15:00:26 25 4
gpt4 key购买 nike

我有一个 PowerShell 脚本,它使用异步计时器事件(后台进程)来测量在采取适当措施之前特定条件发生的时间。
当我在 PowerGUI 中运行脚本时,这工作得很好,但是当我使用点源运行脚本或通过批处理文件运行它时,定时器事件操作不会触发。

这是一个代码片段。

$timer = New-Object System.Timers.Timer
$timer.Interval = 10000
$timer.AutoReset = $true
$timeout = 0

$action = {
"timeout: $timeout" | Add-Content $loglocation
<more stuff here>
$timer.stop()
}
$start = Register-ObjectEvent -InputObject $timer -SourceIdentifier TimerElapsed -EventName Elapsed -Action $action

$timer.start()

while(1)
{
<do some testing here>
}

所以当它工作时,我会看到每10秒写入日志的“超时:XX”输出。但这仅在编辑器中运行时才会发生。当我通过批处理文件运行它时,没有任何 react (尽管我可以确认 while 循环处理正常)。

所以我的问题是,当我在 PowerGUI 中运行脚本与通过命令行运行脚本时,为什么我的体验不同?我的想法是作用域或并行线程可能存在问题,但我不确定问题是什么。此外,我没有在任何函数或循环中运行这些事件。

最佳答案

调用脚本文件时,$action 脚本块使用调用者的作用域(父作用域)执行,而不是脚本文件的作用域(子作用域)。因此,脚本文件中定义的变量在 $action 脚本块中不可用,除非它们被定义为使用全局范围或点源(这将使它们在全局范围内可用)。见 this wonderful article想要查询更多的信息。

假设以下代码包含在名为 test.ps1 的文件中。

$timer = New-Object System.Timers.Timer
$timer.Interval = 10000
$timer.AutoReset = $false

$timeout = 100
$location = 'SomeLocation'
$sourceIdentifier = 'SomeIdentifier'

$action = {
Write-Host "Timer Event Elapsed. Timeout: $timeout, Location: $location, SourceIdentifier: $sourceIdentifier"
$timer.stop()
Unregister-Event $sourceIdentifier
}

$start = Register-ObjectEvent -InputObject $timer -SourceIdentifier $sourceIdentifier -EventName Elapsed -Action $action

$timer.start()

while(1)
{
Write-Host "Looping..."
Start-Sleep -s 5
}

从 powershell 控制台调用时,执行 $action 脚本块时,它使用的变量将没有值。
./test.ps1

Timer Event Elapsed. Timeout: , Location: , SourceIdentifier:

如果您在调用脚本之前定义了 $action 脚本块中使用的变量,则这些值将在操作执行时可用:
$timeout = 5; $location = "SomeLocation"; $sourceIdentifier = "SomeSI"
./test.ps1

Timer Event Elapsed. Timeout: 5, Location: SomeLocation, SourceIdentifier: SomeSI

如果您点源脚本,脚本中定义的变量将在当前范围内可用,因此当操作执行时,这些值将可用:
. ./test.ps1

Timer Event Elapsed. Timeout: 100, Location: SomeLocation, SourceIdentifier: SomeIdentifier

如果变量已在脚本文件的全局范围内声明:
$global:timeout = 100
$global:location = 'SomeLocation'
$global:sourceIdentifier = 'SomeIdentifier'

然后当 $action 脚本块在父作用域中执行时,这些值将可用:
./test.ps1

Timer Event Elapsed. Timeout: 100, Location: SomeLocation, SourceIdentifier: SomeIdentifier

关于shell - PowerShell 异步计时器事件在测试控制台之外不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16901754/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com