Как я могу получить текущий исполняемый файл PowerShell? - PullRequest
79 голосов
/ 03 мая 2009

Примечание: PowerShell 1.0
Я хотел бы получить текущее имя исполняемого файла PowerShell. То есть, если я начну свою сессию так:

powershell.exe .\myfile.ps1

Я бы хотел получить строку ". \ Myfile.ps1" (или что-то в этом роде). РЕДАКТИРОВАТЬ : "myfile.ps1" является предпочтительным.
Есть идеи?

Ответы [ 10 ]

72 голосов
/ 16 октября 2014

Хотя текущий ответ является правильным в большинстве случаев, есть определенные ситуации, в которых он не даст вам правильный ответ. Если вы используете внутри скрипта функции, то:

$MyInvocation.MyCommand.Name 

Возвращает имя функции вместо имени имени скрипта.

function test {
    $MyInvocation.MyCommand.Name
}

Даст вам " test " независимо от того, как называется ваш скрипт. Правильная команда для получения имени скрипта всегда

$MyInvocation.ScriptName

возвращает полный путь к скрипту, который вы выполняете. Если вам нужно только имя файла сценария, этот код должен вам помочь:

split-path $MyInvocation.PSCommandPath -Leaf
68 голосов
/ 04 мая 2009

Если вы хотите только имя файла (не полный путь), используйте это:

$ScriptName = $MyInvocation.MyCommand.Name
38 голосов
/ 26 апреля 2017

Я попытался обобщить различные ответы, обновленные для 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, ни один метод не работает как внутри, так и снаружи функции
32 голосов
/ 03 мая 2009

Попробуйте следующее

$path =  $MyInvocation.MyCommand.Definition 

Это может не дать вам набранный фактический путь, но даст вам правильный путь к файлу.

7 голосов
/ 27 ноября 2014

берегитесь: В отличие от автоматических переменных $PSScriptRoot и $PSCommandPath, PSScriptRoot и PSCommandPath свойства $MyInvocation автоматического переменная содержит информацию о вызывающем или вызывающем скрипте, а не текущий скрипт.

, например

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 голосов
/ 10 ноября 2010

Если вы ищете текущий каталог, в котором выполняется скрипт, вы можете попробовать это:

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

Write-Host $currentExecutingPath
4 голосов
/ 25 сентября 2017

Я бы сказал, что есть лучший метод, установив область видимости переменной $ 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
1 голос
/ 28 октября 2017

Как отмечалось в предыдущих ответах, использование «$ 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 = родительский и т. Д.

Надеюсь, это несколько полезно.

Ref, https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-variable

1 голос
/ 21 февраля 2017

Провел некоторое тестирование с помощью следующего скрипта на 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
0 голосов
/ 18 апреля 2019

Это может работать на большинстве версий PowerShell:

(& { $MyInvocation.ScriptName; })

Это может работать для запланированной работы

Get-ScheduledJob |? Name -Match 'JOBNAMETAG' |% Command
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...