什么是确定当前PowerShell脚本位置的最佳方法?

无论何时我需要引用一个通用的模块或脚本,我都喜欢使用相对于当前脚本文件的path,这样,我的脚本就可以随时在库中find其他脚本。

那么,确定当前脚本目录的最佳标准方法是什么? 目前,我正在做:

$MyDir = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition) 

我知道在模块(.psm1)中,您可以使用$PSScriptRoot来获取这些信息,但是这并不是在普通脚本(即.ps1文件)中设置的。

获取当前PowerShell脚本文件位置的规范方法是什么?

PowerShell 3+

 # This is an automatic variable set to the current file's/module's directory $PSScriptRoot 

PowerShell 2

在PowerShell 3之前,没有比查询一般脚本的MyInvocation.MyCommand.Definition属性更好的方法。 我有基本上每个PowerShell脚本的顶部的以下行:

 $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition 

如果您正在创buildV2模块,则可以使用名为$PSScriptRoot的自动variables。

从PS>帮助automatic_variable

 $ PSScriptRoot
       包含正在执行脚本模块的目录。
       这个variables允许脚本使用模块path来访问其他的
       资源。

对于PowerShell 3.0

 $PSCommandPath Contains the full path and file name of the script that is being run. This variable is valid in all scripts. 

该function是:

 function Get-ScriptDirectory { Split-Path -Parent $PSCommandPath } 

也许我错过了这里的东西…但是如果你想要目前的工作目录,你可以使用这个: (Get-Location).Path为一个string,或Get-Location为一个对象。

除非你指的是这样的东西,我再次阅读这个问题后,我明白了。

 function Get-Script-Directory { $scriptInvocation = (Get-Variable MyInvocation -Scope 1).Value return Split-Path $scriptInvocation.MyCommand.Path } 

我需要知道脚本名称以及它从哪里执行。

当从主脚本和导入的.PSM1库文件的主线调用MyInvocation结构前缀“$ global:”时,将返回完整path和脚本名称。 它也可以在导入库中的函数中使用。

经过大量的摆弄之后,我决定使用$ global:MyInvocation.InvocationName。 它可以在CMD启动,运行Powershell和ISE的情况下可靠运行。 本地和UNC发射都返回正确的path。

我使用自动variables $ ExecutionContext,它从PowerShell 2和更高版本。

 $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath('.\') 

$ ExecutionContext包含表示Windows PowerShell主机的执行上下文的EngineIntrinsics对象。 您可以使用此variables查找可用于cmdlet的执行对象。

花了我一段时间去开发一些接受了答案的东西,并把它变成一个强大的function。

不知道其他人,但我在一个与PowerShell版本2和3机器的环境中工作,所以我需要处理这两个。 以下函数提供了优雅的回退:

 Function Get-PSScriptRoot { $ScriptRoot = "" Try { $ScriptRoot = Get-Variable -Name PSScriptRoot -ValueOnly -ErrorAction Stop } Catch { $ScriptRoot = Split-Path $script:MyInvocation.MyCommand.Path } Write-Output $ScriptRoot } 

这也意味着该function是指脚本的范围,而不是由Michael Sorens在其博客中概述的父母的范围

非常类似已经发布的答案,但pipe道似乎更像PS。

 $PSCommandPath | Split-Path -Parent 

对于Powershell 3+

 function Get-ScriptDirectory { if ($psise) {Split-Path $psise.CurrentFile.FullPath} else {$global:PSScriptRoot} } 

我已经把这个function放在我的档案中。 在ISE中使用F8 / Run Selection也可以工作。

如果其他任何方法失败,您也可以考虑使用split-path -parent $psISE.CurrentFile.Fullpath 。 特别是,如果您运行一个文件来加载一堆函数,然后在ISE shell中执行这些函数(或者如果您select运行),那么上面的Get-Script-Directory函数似乎不起作用。

 function func1() { $inv = (Get-Variable MyInvocation -Scope 1).Value #$inv.MyCommand | Format-List * $Path1 = Split-Path $inv.scriptname Write-Host $Path1 } function Main() { func1 } Main