Примечание. PowerShell 1.0
Я хотел бы получить имя текущего исполняемого файла PowerShell. То есть, если я начну сеанс так:
powershell.exe .\myfile.ps1
Я хочу получить строку ". \ Myfile.ps1" (или что-то в этом роде). РЕДАКТИРОВАТЬ : предпочтительнее myfile.ps1 .
Любые идеи?
powershell
Рон Кляйн
источник
источник
Ответы:
Я попытался обобщить здесь различные ответы, обновленные для 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источник
$PSCommandPath
если устаревшая версия (WindowsXP) не требуется.function PSCommandPath
) и ссылку на неправильную функцию (Write-Host " * Direct: $PSCommandPath"; Write-Host " * Function: $(ScriptName)";
- или я упускаю из виду что-то очевидное?Хотя текущий ответ в большинстве случаев является правильным, в некоторых ситуациях он не даст вам правильный ответ. Если вы используете внутри скрипта функции, то:
$MyInvocation.MyCommand.Name
Возвращает имя функции вместо имени скрипта.
function test { $MyInvocation.MyCommand.Name }
Даст вам " тест " независимо от того, как называется ваш скрипт. Правильная команда для получения имени скрипта всегда
$MyInvocation.ScriptName
это возвращает полный путь к сценарию, который вы выполняете. Если вам нужно только имя файла сценария, этот код должен вам помочь:
split-path $MyInvocation.PSCommandPath -Leaf
источник
$MyInvocation.ScriptName
вернуть пустую строку для меня, PS v3.0.$MyInvocation.ScriptName
работает только внутри функции. Смотрите мой ответ ниже .Если вам нужно только имя файла (а не полный путь), используйте это:
$ScriptName = $MyInvocation.MyCommand.Name
источник
Попробуйте следующее
$path = $MyInvocation.MyCommand.Definition
Это может не дать вам фактического введенного пути, но даст вам действительный путь к файлу.
источник
$path = Split-Path $MyInvocation.MyCommand.Definition -Parent
Если вы ищете текущий каталог, в котором выполняется сценарий, вы можете попробовать этот:
$fullPathIncFileName = $MyInvocation.MyCommand.Definition $currentScriptName = $MyInvocation.MyCommand.Name $currentExecutingPath = $fullPathIncFileName.Replace($currentScriptName, "") Write-Host $currentExecutingPath
источник
C:\ilike.ps123\ke.ps1
, не так ли?Replace()
метод заменяет все вхождения иглы (а не только последнее вхождение), и я также его тестировал. Однако неплохо было бы сделать что-то вроде вычитания на строках.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
) - Отлично!$currentScriptPath = $MyInvocation.MyCommand.Definition; $currentScriptName = $MyInvocation.MyCommand.Name; $currentScriptDir = $currentScriptPath.Substring(0,$currentScriptPath.IndexOf($currentScriptName));
остерегайтесь: В отличии от
$PSScriptRoot
и$PSCommandPath
автоматического переменных, тоPSScriptRoot
иPSCommandPath
свойства$MyInvocation
автоматического переменного содержит информацию о запустивших или вызывающем сценарии, а не текущий сценария.например
... где
DPM.ps1
содержитсяWrite-Host ("="+($MyInvocation.PSCommandPath)+"!"+$PSCommandPath)
источник
Я бы сказал, что есть лучший метод, установив область видимости переменной $ 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:MyInvocation.MyCommand.Path
источник
Как отмечалось в предыдущих ответах, использование «$ 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/en-us/powershell/module/microsoft.powershell.utility/get-variable
источник
Провел некоторое тестирование со следующим скриптом как на 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
Полученные результаты -
источник
Это может работать в большинстве версий PowerShell:
(& { $MyInvocation.ScriptName; })
Это может работать для запланированного задания
Get-ScheduledJob |? Name -Match 'JOBNAMETAG' |% Command
источник