PowerShell脚本工作目录(当前位置)

时间:2019-10-07 21:43:35

标签: powershell path scripting working-directory

当我从任何文件夹(例如C:\Scripts)启动PowerShell脚本时, 脚本中的“当前” PowerShell文件夹 始终是用户配置文件文件夹(例如c:\users\Joe) (使用仅包含Get-Location的脚本进行测试)

但是应该是启动脚本的文件夹...

我该如何解决?

1 个答案:

答案 0 :(得分:2)

当PowerShell 直接直接调用*.ps1脚本时,该脚本在与调用方相同的运行空间中运行进程内 ,因此脚本默认情况下将相同当前位置(工作目录)视为呼叫者

顺便说一句:相反,如果脚本更改当前位置,则在脚本退出后,调用方也会看到该信息(详细信息,请参见下文)。

如果您没有看到此行为,则表示一些幕后代码正在更改当前位置。 < / p>


我可以实际看到此情况的唯一方法是在以下情况下:

  • 如果(a)您的$PROFILE文件包含Set-Location / Push-Location命令,该命令明确切换到您的主文件夹(b)(就像您的情况一样,我们现在知道)自动加载模块中是否存在代码损坏,该代码在(自动)import [1] 上执行此操作:

    • 您通过其CLI(对于 Windows PowerShell powershell.exe,对于PowerShell Core pwsh)来调用PowerShell < em>没有-NoProfile开关;例如powershell -File someScript.ps1

    • 在类似Unix的平台上,您的脚本已实现并被称为带有shebang行的不扩展的可执行shell脚本(不包含-NoProfile-有关详细信息,请参见下文)。 / p>

  • 如果通过以下命令/功能之一运行脚本:

    • 通过Start-Job(在子进程中)或Start-ThreadJob(在新的运行空间中),至少当前是这样(PowerShell Core 7.0.0-preview.4)

      • 注意:这两个cmdlet的行为并不完全相同,这本身就是有问题的,但是更大的问题是它们不能简单地继承调用者的当前位置-请参见{ {3}}。
    • 在新的运行空间中通过PowerShell SDK。

除此之外,我只能看到基于偶然事件的代码会产生您的症状,例如以下内容-无意义-重新定义了交互式提示字符串定义函数prompt,使它在每个命令之后悄悄地切换到$HOME目录:

# !! Obviously, do NOT do this.
function prompt { 
  # Print the usual prompt string.
  "PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) "
  # Quietly return to $HOME
  Set-Location $HOME 
}

其余的答案讨论了可能感兴趣的相关场景。


以其自己的目录作为工作目录(当前位置)执行PowerShell脚本:

在PowerShell v3 +中,自动变量$PSScriptRoot包含执行脚本所在目录的完整路径。

如果您需要脚本以其自己的目录作为工作目录执行(当前位置),请使用以下方法:

# Switch to this script's directory.
Push-Location -LiteralPath $PSScriptRoot

try {
 # Your script's body here.
 # ... 
 $PWD  # output the current location 
}
finally {
  # Restore the previous location.
  Pop-Location
}

注意:

  • 显式还原先前位置(目录)的原因是 PowerShell在运行中的脚本(.ps1文件)( ),因此如果脚本使用 Set-LocationPush-Location 更改当前位置,全局生效 session ;也就是说,即使脚本退出后,新位置仍会停留。

  • 类Unix平台(Linux,macOS)上,使用PowerShell Core ,您现在可以选择创建(无扩展名)可执行Shell <带有this GitHub issue 的strong>脚本;这样的脚本子进程 中运行,因此 不需要还原以前的位置(目录)

    • 不幸的是,从PowerShell 7.0.0-preview.4版开始,在基于shebang的脚本中,中断了对脚本自身调用(包括$PSScriptRoot)的访问,包括<{>} shebang line

[1]任何模块都不应在导入时更改会话全局状态(除了导入其命令),但是从技术上讲,它是可能的,即如果您放置诸如{ {1}}位于脚本模块的Set-Location文件的顶级范围中,或者位于通过*.psm1 module-manifest条目在调用者范围内运行的脚本中。甚至二进制cmdlet也可以在导入时通过ScriptsToProcess接口执行代码-请参见this GitHub issue