当作为命令调用时,ScriptProperty 无法访问脚本的 cmdlet

ScriptProperty can't access script's cmdlets when invoked as a command

给出这样的代码 MRE:

function Get-One {1}
Update-TypeData -TypeName 'Demo' -MemberType 'ScriptProperty' -MemberName 'Test1' -Value {Get-Date}
Update-TypeData -TypeName 'Demo' -MemberType 'ScriptProperty' -MemberName 'Test2' -Value {Get-One}
$example = [PSCustomObject]@{PSTypeName = 'Demo'}
$example

如果我以 pwsh -File '.\Demo.ps1' 的形式调用它,那么一切都会如您所愿/我得到以下输出:

Test1               Test2
-----               -----
2021-04-17 21:35:55     1

但是,如果我调用与 pwsh -Command '.\Demo.ps1' 相同的命令,我会得到这个(即 Test2 为空白);虽然我希望得到与上述相同的结果:

Test1               Test2
-----               -----
2021-04-17 21:35:55     

即当我通过 -Command 参数调用时,ScriptProperty 无法访问脚本本身定义的 cmdlets/functions;虽然可以访问标准的(例如 Get-Date)。

我认为这是一个错误; PWSH 和 PowerShell 中似乎只有相同的行为;这使得这种可能性降低了一点。

这是一个错误吗?还是我的理解遗漏了什么。

行为差异的原因是 -File 隐式 dot-sources 目标脚本文件,这意味着它在 全局 范围.

通常,此细节影响不大(除非您还通过 -NoExit 请求在脚本终止后留在会话中)。

在这里,它产生了关键的区别:

  • -File 一起,Get-One 最终定义在 global 范围内,这是ScriptProperty-defining { Get-One } 脚本块可以看到它.

  • 相比之下,运行带有-Command的脚本文件不是点源,使得Get-One 命令实际上对 { Get-One } 脚本块不可见 - 并且在此类 ScriptProperty 定义脚本块中发生的错误被悄悄地 忽略 .

有两个解决方案:

  • 或者:将您的 Get-One 函数明确定义为 global:

    function global:Get-One { 1 }
    
  • 或者:使用-Command时,显式点源脚本:

     pwsh -Command '. .\Demo.ps1'