gpt4 book ai didi

引用函数时 PowerShell 退出事件不起作用

转载 作者:行者123 更新时间:2023-12-05 00:49:35 25 4
gpt4 key购买 nike

我有一个 .ps1一旦 PowerShell session 结束,需要一些代码来执行清理目的的脚本。我遇到的问题的最简单再现:

function ExitLogic(){
Write-Host 'closing'
}
Write-Host 'started'
Register-EngineEvent `
-SourceIdentifier ([System.Management.Automation.PsEngineEvent]::Exiting) `
-Action { ExitLogic }

ExitLogic 永远不会发生。如果我手动使用 exit 则不会命令在我的 PowerShell session 中,而不是如果我单击 X窗口按钮,如果我在 cmd.exe 中运行 PowerShell ......我不知所措。但是,如果我更改 Action来自引用的参数 ExitLogic作为 Write-Host 'inline closing' 的函数那么它确实有效。

最佳答案

tl;博士

到时候-Action脚本块执行(当引擎退出时),ExitLogic()功能不再在范围内。

给 Ethan 的注意事项:我提出的一些要点您可能已经知道了 - 我在这里将它们拼写出来是为了将来的读者。

总分:

  • *.ps1文件不在子进程中运行 ,因此退出脚本并不等于退出整个 PowerShell 引擎。
  • 脚本默认在子作用域中运行 ,因此其中定义的函数仅在脚本运行时才在作用域内。
  • 只有在全局作用域中定义的函数才能在 -Action 中引用脚本块 .
  • 到时候-Action脚本块执行,许多常规 PowerShell 功能不再可用 . 编写自 v6.2.0
  • 值得注意的是,PowerShell 自己的 不能再使用输出流 - 不再打印常规输出和错误消息。
  • 但是,您可以使用 Write-Host产生显示输出 (尽管外部调用者将通过 stdout 接收到该信息),但请注意 如果引擎退出也关闭了当前的控制台窗口,您甚至看不到它。 一个 Read-Host命令可以延迟关闭。
  • 似乎只有来自 Microsoft.PowerShell.Utility 的命令模块可用,而所有其他模块都已卸载 - 参见 this GitHub issue .
  • 重要 : 事件处理程序只有在 PowerShell 本身退出 session 时才能运行 (无论是正常情况还是通过 throw 触发的脚本终止错误) - 如果您通过关闭控制台/终端窗口间接终止 PowerShell,则事件处理程序将不会运行。

  • 您的具体案例 :
  • 鉴于-Action当引擎退出时调用块,这发生在脚本完成后,它没有看到 ExitLogic功能,到那时已经超出了范围。
  • 一种制作方法 ExitLogic在全局范围内可用的是“点源”您的脚本(例如, . .\script.ps1 ),但请注意,这只适用于全局范围;需要做更多工作才能从子作用域或模块作用域向全局作用域添加函数。

  • 以下代码段演示了这一点:

    让我们假设存在脚本 .\script.ps1具有以下内容:
    function ExitLogic {
    Write-Host 'closing'
    }

    Write-Host 'started'

    $null = Register-EngineEvent `
    -SourceIdentifier PowerShell.Exiting `
    -Action {
    try { ExitLogic } catch { Write-Host $_ }
    Read-Host -Prompt 'Press ENTER to exit'
    }

    注:如 Get-Help Register-EngineEvent 状态,以下 -SourceIdentifier支持的值: PowerShell.Exiting , PowerShell.OnIdle , 和 PowerShell.OnScriptBlockInvoke ,对应于类似枚举的值 [System.Management.Automation.PSEngineEvent] class ;显式使用后者(如在 OP 中)可为您提供更多类型安全性,但键入起来也更麻烦。

    警告 : 以下命令退出正在运行的 PowerShell session ;它只是 Read-Host保持窗口打开的命令,允许您检查事件处理程序的 Write-Host输出;按 Enter 后,窗口关闭。
  • 直接调用:

  • # Due to direct invocation, the -Action block does NOT see ExitLogic()
    PS> .\script.ps1; exit
    started
    The term 'ExitLogic' is not recognized as the name of a cmdlet, function,
    script file, or operable program.
    Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    Press ENTER to exit:
  • 点源调用:

  • # Thanks to dot-sourcing in the global scope, the -Action block DOES see ExitLogic()
    PS> . .\script.ps1; exit
    started
    closing
    Press ENTER to exit:

    关于引用函数时 PowerShell 退出事件不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47476484/

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