为什么 PowerShell.exe 没有办法点源脚本?

And*_*ndy 2 powershell dot-source

帮助文档说该脚本将以“点源”模式执行,但事实并非如此。为什么?

我阅读了帮助文档全文,没有找到原因,所以才来求助。

PS> PowerShell.exe -File '.\dot-source-test.ps1'
PS> $theValue
PS> . '.\dot-source-test.ps1'
PS> $theValue
theValue
PS>
Run Code Online (Sandbox Code Playgroud)

“dot-source-test.ps1”的内容是$theValue = 'theValue'

如果 File 的值是文件路径,则脚本在本地范围(“点源”)中运行,以便脚本创建的函数和变量在当前会话中可用。

about_PowerShell_exe - PowerShell | about_PowerShell_exe 微软文档

mkl*_*nt0 6

为防止概念混淆:

为了对script 进行点源化,即直接在调用者的作用域中执行它(而不是默认的子作用域),以便调用者可以看到脚本的变量、函数定义等:

  • 当前的PowerShell会话中,只需直接使用点源运算.符:

    # Dot-source in the caller's scope.
    # When executed at the prompt in an interactive PowerShell session,
    # the script's definitions become globally available.
    . '.\dot-source-test.ps1'
    
    Run Code Online (Sandbox Code Playgroud)
  • 通过powershell.exeWindows PowerShell CLI [1]

    • 注意:您以这种方式执行的任何点源都仅限于运行的子进程及其PowerShell 会话它对调用者的会话没有影响。powershell.exe

    • 通过 CLI 进行点采购仅在两种情况下有意义

      • 场景 A:您通过(可能是位置隐含的)-Command( -c) 参数传递命令,该参数依赖于必须首先来自脚本文件的点源的定义,并且您希望会话在命令执行完毕后自动退出。

      • 场景 B:您正在进入一个(可能是嵌套的)交互式PowerShell 会话,您希望从脚本文件中点源(预加载)定义;与任何交互式会话一样,您需要手动退出它,通常使用exit.

场景 A:预加载定义,执行依赖它们的命令,然后退出:

下面启动一个(新的)PowerShell 会话,如下所示:

  • 脚本文件.\dot-source-test.ps1是点源的,它$theValue在调用者(此处:全局)范围内定义变量。

  • 的值$theValue是输出。

  • 完成命令后,新会话将自动退出。

PS> powershell -c '. .\dot-source-test.ps1; $theValue'
theValue
Run Code Online (Sandbox Code Playgroud)

场景 B:进入具有预加载定义的(新)交互式会话:

只需添加-noexit开关即可进入交互式会话,其中脚本文件.\dot-source-test.ps1已被点源化:

powershell -noexit -c '. .\dot-source-test.ps1'
# You're now  in a (new) interactive session in which $theValue is defined,
# and which you must eventually exit manually.
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 如果既没有指定命令,也没有指定-File命令(通过显式或隐含的-Command/ ),则为隐含的。 因为这里需要进行点采购,所以必须指定以保持会话打开。-c-noexit
    -c-noexit

  • 虽然用于-File点采购也powershell -noexit -File '.\dot-source-test.ps1'有效,但我建议出于概念原因避免使用它

    • 虽然从技术上讲,传递到的脚本-File在新会话中是点源的,但这是 (a) 意外的,因为从会话内部执行的脚本不是(它们在子作用域中运行)并且 (b) 到目前为止最典型的用例-File是执行给定的脚本然后退出- 在这种情况下,点源方面是无关紧要的

    • 因此,最好将此行为视为实现细节,不幸的是CLI 帮助如此突出地提到了它 - 导致了引发此问题的混乱。


[1] 这同样适用于PowerShell [Core] 7+ CLI, pwsh,只不过它默认为-File而非-Command

  • 很好的答案!它解决了我正在尝试通过点源将脚本函数加载到当前命令 shell 中时遇到的问题。是 .\Do-Something.ps1 并且该函数不会被加载。在 7 中,如果您位于同一文件夹中,它会告诉您使用 .\ 表示本地,这是正确的但具有误导性。做这个: 。“.\Do-Something.ps1” (2认同)