Как получить текущий исполняемый файл 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