这应该是一个简单的任务,但是我已经看到过几次关于如何获取已执行cmdlet所在目录的路径的尝试,结果好坏参半。例如,当我执行C:\temp\myscripts\mycmdlet。我想能够将C:\temp\myscripts存储在mycmdlet.ps1中的一个变量中。

这是一个有效的解决方案(尽管有点麻烦):

$invocation = (Get-Variable MyInvocation).Value
$directorypath = Split-Path $invocation.MyCommand.Path
$settingspath = $directorypath + '\settings.xml'

另一个人建议这样的解决方案,它只适用于我们的测试环境:

$settingspath = '.\settings.xml'

我非常喜欢后一种方法,与每次都将文件路径解析为参数相比,我更喜欢这种方法,但我无法让它在我的开发环境中工作。我该怎么办?这与PowerShell的配置方式有关吗?


当前回答

I had similar problems and it made me a lot of trouble since I am making programs written in PowerShell (full end user GUI applications) and I have a lot of files and resources I need to load from disk. From my experience, using . to represent current directory is unreliable. It should represent current working directory, but it often does not. It appears that PowerShell saves location from which PowerShell has been invoked inside .. To be more precise, when PowerShell is first started, it starts, by default, inside your home user directory. That is usually directory of your user account, something like C:\USERS\YOUR USER NAME. After that, PowerShell changes directory to either directory from which you invoked it, or to directory where script you are executing is located before either presenting you with PowerShell prompt or running the script. But that happens after PowerShell app itself originally starts inside your home user directory.

And . represents that initial directory inside which PowerShell started. So . only represents current directory in case if you invoked PowerShell from the wanted directory. If you later change directory in PowerShell code, change appears not to be reflected inside . in every case. In some cases . represents current working directory, and in others directory from which PowerShell (itself, not the script) has been invoked, what can lead to inconsistent results. For this reason I use invoker script. PowerShell script with single command inside: POWERSHELL. That will ensure that PowerShell is invoked from the wanted directory and thus make . represent current directory. But it only works if you do not change directory later in PowerShell code. In case of a script, I use invoker script which is similar to last one I mentioned, except it contains a file option: POWERSHELL -FILE DRIVE:\PATH\SCRIPT NAME.PS1. That ensures that PowerShell is started inside current working directory.

只需单击脚本就可以从主用户目录调用PowerShell,而不管脚本位于何处。 它的结果是当前工作目录是脚本所在的目录,但PowerShell调用目录是C:\USERS\YOUR USER NAME,与。根据情况返回这两个目录中的一个,这是荒谬的。

但是为了避免所有这些麻烦并使用调用程序脚本,您可以简单地使用$PWD或$PSSCRIPTROOT来代替。表示当前目录,具体取决于您希望表示当前工作目录还是已从其中调用脚本的目录。 如果你出于某种原因,想要检索两个目录中的另一个。返回时,您可以使用$HOME。

就我个人而言,我用PowerShell开发的应用程序的根目录中只有调用程序脚本,它会调用我的主应用程序脚本,只要记住永远不要改变应用程序源代码中的当前工作目录,所以我永远不必担心这个问题,我可以使用。要表示当前目录和支持相对文件寻址在我的应用程序没有任何问题。 这应该适用于PowerShell的新版本(更新于版本2)。

其他回答

你会认为使用'。\'作为路径意味着它是调用路径。但也不是所有时候。例如,如果您在作业ScriptBlock中使用它。在这种情况下,它可能指向%profile%\Documents。

Get-Location将返回当前位置:

$Currentlocation = Get-Location

在Powershell 3及以上,您可以简单地使用

PSScriptRoot美元

是的,应该可以。但如果你需要看到绝对路径,这就是你所需要的:

(Get-Item .).FullName

你还可以使用:

(Resolve-Path .\).Path

括号中的部分返回一个PathInfo对象。

(PowerShell 2.0起可用。)