如何获取当前的PowerShell执行文件?


92

注意:PowerShell 1.0
我想获取当前正在执行的PowerShell文件名。也就是说,如果我像这样开始会话:

powershell.exe .\myfile.ps1

我想获取字符串“。\ myfile.ps1”(或类似名称)。编辑“ myfile.ps1”是可取的。
有任何想法吗?


谢谢,当前答案几乎相同,但是我只需要文件名(而不是整个路径),因此可接受的答案是@Keith。但是,两个答案都为+1。现在我知道有关$ MyInvocation的问题了:-)
Ron Klein

如何从包含的脚本中获取父脚本?
Florin Sabau

Answers:


67

我尝试在此处总结各种答案,这些答案针对PowerShell 5已更新:

  • 如果您仅使用PowerShell 3或更高版本,请使用 $PSCommandPath

  • 如果要与旧版本兼容,请插入垫片:

    if ($PSCommandPath -eq $null) { function GetPSCommandPath() { return $MyInvocation.PSCommandPath; } $PSCommandPath = GetPSCommandPath; }

    $PSCommandPath如果尚不存在,则会添加。

    填充代码可以在任何地方(顶级或在函数内部)执行,尽管$PSCommandPath变量受常规作用域规则的约束(例如,如果将填充块放入函数中,则变量仅作用于该函数)。

细节

在各种答案中使用了4种不同的方法,因此我编写了此脚本来演示每种方法(以及$PSCommandPath):

function PSCommandPath() { return $PSCommandPath; }
function ScriptName() { return $MyInvocation.ScriptName; }
function MyCommandName() { return $MyInvocation.MyCommand.Name; }
function MyCommandDefinition() {
    # Begin of MyCommandDefinition()
    # Note: ouput of this script shows the contents of this function, not the execution result
    return $MyInvocation.MyCommand.Definition;
    # End of MyCommandDefinition()
}
function MyInvocationPSCommandPath() { return $MyInvocation.PSCommandPath; }

Write-Host "";
Write-Host "PSVersion: $($PSVersionTable.PSVersion)";
Write-Host "";
Write-Host "`$PSCommandPath:";
Write-Host " *   Direct: $PSCommandPath";
Write-Host " * Function: $(ScriptName)";
Write-Host "";
Write-Host "`$MyInvocation.ScriptName:";
Write-Host " *   Direct: $($MyInvocation.ScriptName)";
Write-Host " * Function: $(ScriptName)";
Write-Host "";
Write-Host "`$MyInvocation.MyCommand.Name:";
Write-Host " *   Direct: $($MyInvocation.MyCommand.Name)";
Write-Host " * Function: $(MyCommandName)";
Write-Host "";
Write-Host "`$MyInvocation.MyCommand.Definition:";
Write-Host " *   Direct: $($MyInvocation.MyCommand.Definition)";
Write-Host " * Function: $(MyCommandDefinition)";
Write-Host "";
Write-Host "`$MyInvocation.PSCommandPath:";
Write-Host " *   Direct: $($MyInvocation.PSCommandPath)";
Write-Host " * Function: $(MyInvocationPSCommandPath)";
Write-Host "";

输出:

PS C:\> .\Test\test.ps1

PSVersion: 5.1.19035.1

$PSCommandPath:
 *   Direct: C:\Test\test.ps1
 * Function: C:\Test\test.ps1

$MyInvocation.ScriptName:
 *   Direct:
 * Function: C:\Test\test.ps1

$MyInvocation.MyCommand.Name:
 *   Direct: test.ps1
 * Function: MyCommandName

$MyInvocation.MyCommand.Definition:
 *   Direct: C:\Test\test.ps1
 * Function:
    # Begin of MyCommandDefinition()
    # Note this is the contents of the MyCommandDefinition() function, not the execution results
    return $MyInvocation.MyCommand.Definition;
    # End of MyCommandDefinition()


$MyInvocation.PSCommandPath:
 *   Direct:
 * Function: C:\Test\test.ps1

笔记:

  • 从执行C:\,但实际脚本是C:\Test\test.ps1
  • 没有方法告诉您传递的调用路径(.\Test\test.ps1
  • $PSCommandPath 是唯一可靠的方法,但已在PowerShell 3中引入
  • 对于3之前的版本,在函数内部和外部都无法使用单个方法

7
对于今天(2017年)阅读的任何人,他们应该阅读本帖子作为正确答案!+1
Collin Chaffin's

2
@CollinChaffin:同意,现在(2017年)当前支持的最少的是Windows 7,因此$PSCommandPath如果不需要旧版(WindowsXP),则没有理由不使用。
tukan '17

第一个代码示例有缺陷,因为它包含相同函数的两个定义(function PSCommandPath)和对错误函数的引用(Write-Host " * Direct: $PSCommandPath"; Write-Host " * Function: $(ScriptName)";-还是我忽略了明显的东西?
Mike L'Angelo

@ MikeL'Angelo你是对的!连续3年未引起注意。固定,谢谢。输出和结论是相同的。
gregmac

81

尽管当前答案在大多数情况下是正确的,但在某些情况下它不会为您提供正确的答案。如果在脚本函数内部使用,则:

$MyInvocation.MyCommand.Name 

返回函数名称,而不是脚本名称。

function test {
    $MyInvocation.MyCommand.Name
}

无论您的脚本如何命名,都会给您“ 测试 ”。获取脚本名称的正确命令始终是

$MyInvocation.ScriptName

这将返回您正在执行的脚本的完整路径。如果您只需要脚本文件名,则此代码应该可以帮助您:

split-path $MyInvocation.PSCommandPath -Leaf

6
请注意,最高级的posh v4没有定义Scriptname。我喜欢在顶层使用$ MyInvocation.MyCommand.Definition作为其他答案的完整路径或名称。
AnneTheAgile 2015年

30
$MyInvocation.ScriptName为我返回空字符串,PS v3.0。
JohnC

4
@JohnC $MyInvocation.ScriptName仅在函数内部起作用。请参阅下面的答案
gregmac '17

72

如果只需要文件名(而不是完整路径),请使用以下命令:

$ScriptName = $MyInvocation.MyCommand.Name

32

尝试以下

$path =  $MyInvocation.MyCommand.Definition 

这可能不会为您提供实际键入的路径,但会为您提供文件的有效路径。


1
@Hamish问题特别说明了是否从文件中调用。
JaredPar

仅供参考:这为您提供了完整的路径和文件名(Powershell 2.0)
Ralph Willgoss 2012年

我一直在搜索此命令。谢谢JaredPar!:)
sqlfool 2013年

使用Split-Path获取目录?$path = Split-Path $MyInvocation.MyCommand.Definition -Parent
颠倒

7

如果要查找执行脚本的当前目录,可以尝试以下操作:

$fullPathIncFileName = $MyInvocation.MyCommand.Definition
$currentScriptName = $MyInvocation.MyCommand.Name
$currentExecutingPath = $fullPathIncFileName.Replace($currentScriptName, "")

Write-Host $currentExecutingPath

1
那将无法正常工作,对C:\ilike.ps123\ke.ps1吗?
fridojet 2012年

@fridojet-不确定,不在PS终端附近进行测试。你为什么不试试看?
Ryk 2012年

不,这只是一个口头上的问题;-)-这是合乎逻辑的,因为该Replace()方法替换了每次出现的针头(不仅是最后一次出现的针头),并且我也对其进行了测试。但是,对字符串进行减法是一个好主意。
fridojet 2012年

... String.TrimEnd()$currentExecutingPath = $fullPathIncFileName.TrimEnd($currentScriptName))呢?-运行正常:"Ich bin Hamster".TrimEnd("ster")返回Ich bin Ham"Ich bin Hamsterchen".TrimEnd("ster")返回Ich bin Hamsterchen(而不是Ich bin Hamchen)-很好!
fridojet 2012年

$currentScriptPath = $MyInvocation.MyCommand.Definition; $currentScriptName = $MyInvocation.MyCommand.Name; $currentScriptDir = $currentScriptPath.Substring(0,$currentScriptPath.IndexOf($currentScriptName));
YP

7

注意:与$PSScriptRoot$PSCommandPath自动变量不同,自动变量的 PSScriptRootPSCommandPath属性$MyInvocation包含有关调用程序或调用脚本的信息,而不是有关当前脚本的信息。

例如

PS C:\Users\S_ms\OneDrive\Documents> C:\Users\SP_ms\OneDrive\Documents\DPM ...
=!C:\Users\S_ms\OneDrive\Documents\DPM.ps1

... DPM.ps1包含

Write-Host ("="+($MyInvocation.PSCommandPath)+"!"+$PSCommandPath)

4

我认为通过设置变量$ MyInvocation.MyCommand.Path的范围,有更好的方法:

ex> $ script:MyInvocation.MyCommand.Name

此方法适用于所有调用环境:

例如:Somescript.ps1

function printme () {
    "In function:"
    ( "MyInvocation.ScriptName: " + [string]($MyInvocation.ScriptName) )
    ( "script:MyInvocation.MyCommand.Name: " + [string]($script:MyInvocation.MyCommand.Name) )
    ( "MyInvocation.MyCommand.Name: " + [string]($MyInvocation.MyCommand.Name) )
}
"Main:"
( "MyInvocation.ScriptName: " + [string]($MyInvocation.ScriptName) )
( "script:MyInvocation.MyCommand.Name: " + [string]($script:MyInvocation.MyCommand.Name) )
( "MyInvocation.MyCommand.Name: " + [string]($MyInvocation.MyCommand.Name) )
" "
printme
exit

输出:

PS> powershell C:\temp\test.ps1
Main:
MyInvocation.ScriptName:
script:MyInvocation.MyCommand.Name: test.ps1
MyInvocation.MyCommand.Name: test.ps1

In function:
MyInvocation.ScriptName: C:\temp\test.ps1
script:MyInvocation.MyCommand.Name: test.ps1
MyInvocation.MyCommand.Name: printme

请注意,从Main调用时,上面接受的答案如何不返回值。另外,请注意,当问题仅要求脚本名称时,上面接受的答案将返回完整路径。作用域变量可在所有地方使用。

另外,如果您确实想要完整的路径,则只需致电:

$script:MyInvocation.MyCommand.Path

3

如先前的答复所述,使用“ $ MyInvocation”会遇到范围问题,并且不一定提供一致的数据(返回值与直接访问值)。我发现,无论范围(在主调用或后续/嵌套函数调用中)如何获取脚本信息(如脚本路径,名称,参数,命令行等)的“最干净”(最一致)方法是使用“ Get- “ MyInvocation”上的“变量” ...

# Get the MyInvocation variable at script level
# Can be done anywhere within a script
$ScriptInvocation = (Get-Variable MyInvocation -Scope Script).Value

# Get the full path to the script
$ScriptPath = $ScriptInvocation.MyCommand.Path

# Get the directory of the script
$ScriptDirectory = Split-Path $ScriptPath

# Get the script name
# Yes, could get via Split-Path, but this is "simpler" since this is the default return value
$ScriptName = $ScriptInvocation.MyCommand.Name

# Get the invocation path (relative to $PWD)
# @GregMac, this addresses your second point
$InvocationPath = ScriptInvocation.InvocationName

因此,您可以获得与$ PSCommandPath相同的信息,但还有很多事情要做。不确定,但是看起来“ Get-Variable”直到PS3才可用,因此对于真正的旧(未更新)系统没有太多帮助。

使用“ -Scope”时还存在一些有趣的方面,因为您可以回溯以获取调用函数的名称等。0 =当前,1 =父级,等等。

希望这会有所帮助。

参考https://docs.microsoft.com/zh-cn/powershell/module/microsoft.powershell.utility/get-variable


1

在PS 2和PS 4上使用以下脚本进行了一些测试,结果相同。希望对大家有帮助。

$PSVersionTable.PSVersion
function PSscript {
  $PSscript = Get-Item $MyInvocation.ScriptName
  Return $PSscript
}
""
$PSscript = PSscript
$PSscript.FullName
$PSscript.Name
$PSscript.BaseName
$PSscript.Extension
$PSscript.DirectoryName

""
$PSscript = Get-Item $MyInvocation.InvocationName
$PSscript.FullName
$PSscript.Name
$PSscript.BaseName
$PSscript.Extension
$PSscript.DirectoryName

结果-

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      -1     -1      

C:\PSscripts\Untitled1.ps1
Untitled1.ps1
Untitled1
.ps1
C:\PSscripts

C:\PSscripts\Untitled1.ps1
Untitled1.ps1
Untitled1
.ps1
C:\PSscripts

1

这可以在大多数Powershell版本上使用:

(& { $MyInvocation.ScriptName; })

这可以用于计划作业

Get-ScheduledJob |? Name -Match 'JOBNAMETAG' |% Command
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.