Как получить текущий исполняемый файл PowerShell?
Примечание: PowerShell 1.0
Я хочу получить текущее имя файла PowerShell. То есть, если я начну свой сеанс следующим образом:
powershell.exe .\myfile.ps1
Я хочу получить строку ".\myfile.ps1" (или что-то в этом роде). EDIT: "myfile.ps1" .
Любые идеи?
Ответы
Ответ 1
В то время как текущий ответ прав в большинстве случаев, есть определенные ситуации, в которых он не даст вам правильного ответа. Если вы используете внутри своих функций script, то:
$MyInvocation.MyCommand.Name
Возвращает имя функции вместо имени имени script.
function test {
$MyInvocation.MyCommand.Name
}
Дает вам " test" независимо от того, как назван ваш script.
Правильная команда для получения имени script всегда
$MyInvocation.ScriptName
это возвращает полный путь к script, который вы выполняете. Если вам нужно только имя файла script, чем этот код, вам следует:
split-path $MyInvocation.PSCommandPath -Leaf
Ответ 2
Если вы хотите, чтобы имя файла (а не полный путь) использовало это:
$ScriptName = $MyInvocation.MyCommand.Name
Ответ 3
Я попытался обобщить различные ответы здесь, обновленные для PowerShell 5:
- Если вы используете только PowerShell 3 или выше, используйте
$PSCommandPath
-
Если требуется совместимость со старыми версиями, вставьте прокладку:
if ($PSCommandPath -eq $null) { function GetPSCommandPath() { return $MyInvocation.PSCommandPath; } $PSCommandPath = GetPSCommandPath; }
Это добавляет $PSCommandPath
, если он еще не существует.
Код прокладки можно выполнять в любом месте (верхний уровень или внутри функции), хотя переменная $PSCommandPath
подчиняется нормальным правилам определения области видимости (например, если вы помещаете прокладку в функцию, переменная привязана к этой функции только).
Подробнее
В различных ответах используются 4 разных метода, поэтому я написал этот script для демонстрации каждого (плюс $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:\
, но фактический script - C:\Test\test.ps1
.
- Никакой метод не сообщает вам исходный путь вызова (
.\Test\test.ps1
)
-
$PSCommandPath
является единственным надежным способом, но был представлен в PowerShell 3
- Для версий до 3 ни один метод не работает как внутри, так и снаружи функции
Ответ 4
Попробуйте выполнить
$path = $MyInvocation.MyCommand.Definition
Это может не дать вам фактический путь, но он даст вам допустимый путь к файлу.
Ответ 5
Если вы ищете текущий каталог, в котором выполняется script, вы можете попробовать следующее:
$fullPathIncFileName = $MyInvocation.MyCommand.Definition
$currentScriptName = $MyInvocation.MyCommand.Name
$currentExecutingPath = $fullPathIncFileName.Replace($currentScriptName, "")
Write-Host $currentExecutingPath
Ответ 6
остерегайтесь:
В отличие от автоматических переменных $PSScriptRoot
и $PSCommandPath
, PSScriptRoot
и PSCommandPath
свойства $MyInvocation
automatic переменная содержит информацию о вызове или вызове script, а не текущий script.
например.
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)
Ответ 7
Я бы сказал, что есть лучший метод, установив область видимости переменной $MyInvocation.MyCommand.Path:
ex > $ script: 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. Скользящая переменная работает во всех местах.
Кроме того, если вам нужен полный путь, вы просто вызываете:
$script:MyInvocation.MyCommand.Path
Ответ 8
Произошло ли тестирование со следующим script, как на 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
Как отмечалось в предыдущих ответах, использование "$ MyInvocation" зависит от проблем, связанных с определением области охвата, и необязательно предоставляет согласованные данные (значение возврата по сравнению с прямым значением доступа). Я обнаружил, что "самый чистый" (наиболее согласованный) метод получения script информации, такой как script путь, имя, парм, командная строка и т.д., Независимо от области действия (в основных или последующих/вложенных вызовах функций) используйте "Get-Variable" в "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 = родительский и т.д.
Надеюсь, что это будет несколько полезно.
Ref, https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-variable
Ответ 10
Это может работать на большинстве версий powershell:
(& { $MyInvocation.ScriptName; })
Это может работать для запланированной работы
Get-ScheduledJob |? Name -Match 'JOBNAMETAG' |% Command