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

Ron*_*ein 86 powershell

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

powershell.exe .\myfile.ps1
Run Code Online (Sandbox Code Playgroud)

我想得到字符串".\ myfile.ps1"(或类似的东西).编辑:"myfile.ps1"是首选.
有任何想法吗?

小智 77

虽然目前的答案在大多数情况下是正确的,但在某些情况下它不会给你正确的答案.如果您在脚本函数中使用,那么:

$MyInvocation.MyCommand.Name 
Run Code Online (Sandbox Code Playgroud)

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

function test {
    $MyInvocation.MyCommand.Name
}
Run Code Online (Sandbox Code Playgroud)

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

$MyInvocation.ScriptName
Run Code Online (Sandbox Code Playgroud)

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

split-path $MyInvocation.PSCommandPath -Leaf
Run Code Online (Sandbox Code Playgroud)

  • `$ MyInvocation.ScriptName`为我返回空字符串,PS v3.0. (30认同)
  • 请注意,在顶层,使用posh v4未定义Scriptname.我喜欢在顶级使用$ MyInvocation.MyCommand.Definition作为完整路径,或者根据其他答案使用Name. (6认同)
  • @JohnC` $ MyInvocation.ScriptName`仅适用于函数内部.请参阅[我的答案如下](http://stackoverflow.com/a/43643346/7913). (4认同)
  • `$ MyInvocation.MyCommand.Definition`为我工作! (3认同)

Kei*_*ill 70

如果您只想要文件名(不是完整路径),请使用:

$ScriptName = $MyInvocation.MyCommand.Name
Run Code Online (Sandbox Code Playgroud)


gre*_*mac 48

我试图总结一下这里的各种答案,针对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() { return $MyInvocation.MyCommand.Definition; # Note this is the contents of the MyCommandDefinition function  
}
function PSCommandPath() { 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: $(PSCommandPath)";
Write-Host "";
Run Code Online (Sandbox Code Playgroud)

输出:

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

PSVersion: 5.1.14393.1066

$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:  return $MyInvocation.MyCommand.Definition; # Note this is the contents of the MyCommandDefinition function


$MyInvocation.PSCommandPath:
 *   Direct:
 * Function: C:\Test\test.ps1
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 执行C:\,但实际的脚本是C:\Test\test.ps1.
  • 没有方法告诉你原始的调用路径(.\Test\test.ps1)
  • $PSCommandPath 是唯一可靠的方法,但在PowerShell 3中引入
  • 对于3之前的版本,没有一种方法可以在函数内部和外部工作

  • 对于今天(2017年)阅读的任何人,他们应该阅读这篇文章作为正确的答案!+1 (6认同)
  • @CollinChaffin:同意,现在(2017年)目前支持的最少的是Windows 7,因此如果不需要传统(WindowsXP),没有理由不使用`$ PSCommandPath`. (2认同)

Jar*_*Par 32

请尝试以下方法

$path =  $MyInvocation.MyCommand.Definition 
Run Code Online (Sandbox Code Playgroud)

这可能不会为您提供输入的实际路径,但它会为您提供该文件的有效路径.


Ryk*_*Ryk 7

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

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

Write-Host $currentExecutingPath
Run Code Online (Sandbox Code Playgroud)


小智 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
Run Code Online (Sandbox Code Playgroud)

...... DPM.ps1包含哪里

Write-Host ("="+($MyInvocation.PSCommandPath)+"!"+$PSCommandPath)
Run Code Online (Sandbox Code Playgroud)


小智 5

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

ex> $脚本:MyInspiration.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
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

请注意,当从 Main 调用时,上述接受的答案不会返回值。另请注意,当问题仅请求脚本名称时,上述接受的答案会返回完整路径。作用域变量在所有地方都有效。

另外,如果您确实想要完整路径,那么您只需调用:

$script:MyInvocation.MyCommand.Path
Run Code Online (Sandbox Code Playgroud)


Ant*_*Gut 5

如之前的回复所述,使用“$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
Run Code Online (Sandbox Code Playgroud)

因此,您可以获得与 $PSCommandPath 相同的信息,但交易内容更多。不确定,但看起来“Get-Variable”直到 PS3 才可用,所以对真正旧的(未更新的)系统没有太多帮助。

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

希望这有点帮助。

参考,https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-variable