【问题标题】:VSCode & Powershell: How to stop script and unregister object?VSCode & Powershell:如何停止脚本和注销对象?
【发布时间】:2022-01-26 02:14:30
【问题描述】:

我有一个运行良好的 sn-p。它注册一个objectevent如下(sn-p):

Register-ObjectEvent $Watcher -EventName Created -SourceIdentifier FileCreated -Action {

它工作正常,但我似乎无法让脚本完全停止并取消注册。当我使用“正常”方法停止代码时(如下所列),当我重新运行代码时(通过 F5)我得到错误:

Register-ObjectEvent : Cannot subscribe to the specified event. A subscriber with the source identifier 'FileCreated' already exists.

(到目前为止)我可以取消注册的唯一方法是终止 powershell.exe 进程,这也会终止 VSCode 中的 powershell 运行时间(抛出错误,强制手动重启)。

我按 F5 开始代码

为了停止代码,我试过了:

  • Shift-F5
  • Ctrl-C(在 powershell 终端区域)

除了上面描述的以外,没有任何作用。

我错过了什么?

【问题讨论】:

  • 你会想打电话给Unregister-Event -SourceIdentifier FileCreated
  • @MathiasR.Jessen 这会去哪里?在一些最终阻止整个应用程序? (我在哪里可以看到如何构建这样的“常驻”脚本的示例,以便我可以看到在哪里放置出口清理?)

标签: powershell visual-studio-code


【解决方案1】:

仅用于调试目的,您经常强制停止脚本,有 2 个选项。要么手动运行unregister-Event 行,以便取消注册事件,要么在脚本顶部附近添加类似的内容。 (至少在Register-ObjectEvent 之前)

Unregister-Event -SourceIdentifier FileCreated -EA 0

-EA 0-ErrorAction SilentlyContinue 相同,当您在新会话中且该事件尚未注册时,将防止脚本引发错误。

注意:这不应出现在您的生产脚本中,仅作为调试帮助。 (如果您想保留它,我会说至少在脚本的 prod. 版本中将其注释掉)

您的脚本的生产版本应该正确实现Unregister-Event,更类似于:

$FileWatcherReg = @{
    InputObject      = $Watcher
    EventName        = 'Created'
    SourceIdentifier = 'FileCreated'
    MessageData      = @{WatchQueue = $WatchQueue; Timer = $WatchTimer }
    Action           = {
        if ($null -ne $event) {
            Write-Host "Path: $($Event.SourceArgs.FullPath) - ($($Event.Timegenerated))"
        }
    }
   
}

Register-ObjectEvent @FileWatcherReg 

while ($true) {
    Start-Sleep -Milliseconds 100

    # Logic to exit the loop at some point.
}

# Exit script logic ...
Unregister-Event -SourceIdentifier FileCreated

【讨论】:

  • 好的,我有两个问题:首先,为什么取消注册不应该在生产代码的顶部?这看起来真的很安全(在注册之前取消注册)。其次,我看不到我的脚本从哪里退出。它注册一个事件,该事件有一个动作。该操作将永远加载(直到取消注册或 PC 关闭)。所以我不听你的建议。
  • @JonesomeReinstateMonica 真的没什么大不了的,但作为良好编码的原则,当事件未注册时,在脚本顶部取消注册是没有意义的。调试是唯一有意义的上下文。但实际上,即使你把它放在 prod. 中,它也不会真正改变太多,如果你需要经常调试它,那么你可以把它放在那里......
  • Sage,在像这样注册事件的脚本中,脚本永远不会退出,对吧?脚本是一个等待被触发的动作。取消注册会去哪里?
  • @JonesomeReinstateMonica 我想技术上没关系。对于您的脚本,由于您注册并且不想取消注册,因此您可以省略它或在主循环之后包含取消注册。无论如何,我个人喜欢包含取消注册,这样如果我修改主循环以包含退出条件,我不必重新考虑我的资源清理,因为它已经存在。在这种特殊情况下,它并不太重要。无论如何,调试时,这很烦人,因此是脚本建议的顶部。
  • Sage,我不理解 ObjectEvent 上下文中的“主循环”。没有循环......它只是一个挂起事件的函数......(我错过了什么?)
【解决方案2】:

与上面 Sage 的示例类似,是这个更大的示例。它清楚地构造了事件,并展示了如何通过保持脚本运行,然后取消脚本,这将触发清理块。

因此,对于这种方法,有话要说。 (但是,我继续将整个 Register-ObjectEvent 视为一种 TSR ......你的代码保持常驻......永远......等待相关事件......)

例子: https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/using-filesystemwatcher-correctly-part-2#

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-01
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多