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

时间:2009-05-03 14:27:10

标签: powershell

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

powershell.exe .\myfile.ps1

我想获得字符串“。\ myfile.ps1”(或类似的东西)。 编辑“myfile.ps1”更可取 有什么想法吗?

11 个答案:

答案 0 :(得分:72)

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

$MyInvocation.MyCommand.Name 

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

function test {
    $MyInvocation.MyCommand.Name
}

会给你" 测试"无论您的脚本如何命名。 获取脚本名称的正确命令始终为

$MyInvocation.ScriptName

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

split-path $MyInvocation.PSCommandPath -Leaf

答案 1 :(得分:68)

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

$ScriptName = $MyInvocation.MyCommand.Name

答案 2 :(得分:37)

我试图总结一下这里的各种答案,并针对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 "";

输出:

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

说明:

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

答案 3 :(得分:32)

尝试以下

$path =  $MyInvocation.MyCommand.Definition 

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

答案 4 :(得分:7)

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

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

Write-Host $currentExecutingPath

答案 5 :(得分:7)

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

e.g。

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)

答案 6 :(得分:4)

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

离> $的脚本:MyInvocation.MyCommand.Name

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

EX: 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

答案 7 :(得分:2)

@gregmac 的(优秀而详细的)答案的简短演示,它基本上推荐 $PSCommandPath 作为唯一可靠的命令,用于返回使用 Powershell 3.0 及更高版本的当前正在运行的脚本。

这里我显示返回完整路径或仅返回文件名。

Test.ps1:

'Direct:'
$PSCommandPath  # Full Path 
Split-Path -Path $PSCommandPath -Leaf  # File Name only

function main () {
  ''
  'Within a function:'
  $PSCommandPath
  Split-Path -Path $PSCommandPath -Leaf
}

main

输出:

PS> .\Test.ps1
Direct:
C:\Users\John\Documents\Sda\Code\Windows\PowerShell\Apps\xBankStatementRename\Test.ps1
Test.ps1

Within a function:
C:\Users\John\Documents\Sda\Code\Windows\PowerShell\Apps\xBankStatementRename\Test.ps1
Test.ps1

答案 8 :(得分: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

答案 9 :(得分:1)

如前面的回复中所述,使用“$ MyInvocation”会受到范围问题的影响,并不一定提供一致的数据(返回值与直接访问值)。我发现获取脚本信息(如脚本路径,名称,参数,命令行等)的“最干净”(最一致)方法,无论范围如何(在主要或后续/嵌套函数调用中)都使用“Get-变量“on”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/en-us/powershell/module/microsoft.powershell.utility/get-variable

答案 10 :(得分:0)

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

(& { $MyInvocation.ScriptName; })

这可以用于计划作业

Get-ScheduledJob |? Name -Match 'JOBNAMETAG' |% Command