注意:PowerShell 1.0
我想获取当前正在执行的PowerShell文件名。也就是说,如果我像这样启动我的会话:
powershell.exe .\myfile.ps1
我想要得到字符串".\myfile.ps1"(或类似的内容)。编辑:"myfile.ps1" 更好。
有什么想法吗?
注意:PowerShell 1.0
我想获取当前正在执行的PowerShell文件名。也就是说,如果我像这样启动我的会话:
powershell.exe .\myfile.ps1
我想要得到字符串".\myfile.ps1"(或类似的内容)。编辑:"myfile.ps1" 更好。
有什么想法吗?
我尝试在此处总结各种答案的内容,更新至PowerShell 5:
如果您只使用 PowerShell 3 或更高版本,请使用 $PSCommandPath
如果想要与旧版本兼容,请插入shim:
if ($PSCommandPath -eq $null) { function GetPSCommandPath() { return $MyInvocation.PSCommandPath; } $PSCommandPath = GetPSCommandPath }
这将添加$PSCommandPath
(如果它不存在)。
Shim代码可以在任何地方执行(顶层或函数内部),但$PSCommandPath
变量受常规作用域规则的约束(例如,如果您将shim放在函数中,则该变量仅限于该函数)。
各种答案中使用了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: $(PSCommandPath)"
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中引入的$PSCommandPath
。 - tukanfunction PSCommandPath
),以及对错误函数的引用(Write-Host " * Direct: $PSCommandPath"; Write-Host " * Function: $(ScriptName)";
) - 或者我是否忽略了某些明显的东西? - Mike L'Angelo$PSCommandPath
在99%的情况下就足够了。不过还是谢谢。 - Timoif ($PSCommandPath -eq $null) { $PSCommandPath = $MyInvocation.PSCommandPath; }
,是否就足够了呢? - Nuno André尽管目前的答案在大多数情况下是正确的,但在某些情况下它将无法给出正确的答案。如果您在脚本内使用函数,则:
$MyInvocation.MyCommand.Name
返回函数的名称而不是脚本名称的名称。function test {
$MyInvocation.MyCommand.Name
}
无论你的脚本如何命名,它都会给你“test”。 获取脚本名称的正确命令始终是
$MyInvocation.ScriptName
这将返回您正在执行的脚本的完整路径。如果您只需要脚本文件名,则此代码应该能够帮助您:
这会返回你执行的脚本的完整路径。如果你只需要脚本文件名,那么这段代码可以帮到你:
split-path $MyInvocation.PSCommandPath -Leaf
$MyInvocation.ScriptName
对于我来说返回空字符串,PS v3.0。 - JohnC如果你只需要文件名(而不是完整路径),请使用以下代码:
$ScriptName = $MyInvocation.MyCommand.Name
尝试以下代码:
$path = $MyInvocation.MyCommand.Definition
这可能不会给你输入的实际路径,但它会给你一个指向文件的有效路径。
$path = Split-Path $MyInvocation.MyCommand.Definition -Parent
- Underverse注意:
$PSScriptRoot
和$PSCommandPath
自动变量不同,$MyInvocation
自动变量的PSScriptRoot
和PSCommandPath
属性包含有关调用脚本的信息,而不是当前脚本。
例如:
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)
$fullPathIncFileName = $MyInvocation.MyCommand.Definition
$currentScriptName = $MyInvocation.MyCommand.Name
$currentExecutingPath = $fullPathIncFileName.Replace($currentScriptName, "")
Write-Host $currentExecutingPath
C:\ilike.ps123\ke.ps1
上运行不正确,对吧? - fridojetReplace()
方法会替换 每一个 指定的字符串(而不仅仅是最后一个),我已经测试过了,所以这只是合乎逻辑而已。然而,在字符串上执行减法运算是个好主意。 - fridojetString.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[System.IO.Path]::GetDirectoryName($MyInvocation.MyCommand.Definition)
。 - Jozef Benikovský正如之前的回答中所提到的,使用"$MyInvocation"存在作用域问题,并不一定提供一致的数据(返回值与直接访问值)。我发现,获取脚本路径、名称、参数、命令行等脚本信息的“最干净”(最一致)方法是在“MyInvocation”上使用“Get-Variable”,无论在主函数或后续/嵌套函数调用中都可以。
# 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
我认为有一种更好的方法,可以通过设置变量$MyInvocation.MyCommand.Path的作用域来实现:
例如:$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
$script:MyInvocation.MyCommand.Path
以下是@gregmac(出色且详尽)回答的简短演示,基本上建议在使用Powershell 3.0及以上版本时仅使用$PSCommandPath
命令来返回当前正在运行的脚本。
这里展示了返回完整路径或仅文件名的方式。
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
我用以下脚本进行了一些测试,分别在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