В PowerShell 5.1+ существуют следующие переменные, обе из которых, похоже, предлагают полный путь к «вызывающему» сценарию (т. е. сценарию, который вызвал этот сценарий, например, из модуля, функции или внешнего сценария):
$MyInvocation.ScriptName
$MyInvocation.PSCommandPath
Я могу найти официальную документацию, в которой упоминаются оба варианта:
...[$MyInvoction.]ScriptName относится к имени скрипта, который вам позвонил (Да – наверное, стоило выбрать имя получше)
[$MyInvoction.]PSCommandPath содержит полный путь и имя скрипта, который вызвал или вызвал текущий скрипт.
Какой из них мне следует использовать? Мои текущие теории и наблюдения:
Есть ли еще какие-нибудь странные случаи или скрытые «подводные камни» с любым из них, о которых мне следует знать? Или я должен знать о ситуациях, когда одно должно быть предпочтительнее другого?
Согласен с Матиасом, не могу придумать место, где ScriptName может пригодиться. Также не знаю, как можно ответить на этот вопрос, у вас уже есть факты об обоих свойствах, вам решать, какой из них вы хотите использовать.





вр; доктор
Для симметрии с одноименной автоматической переменной $PSCommandPath (которая отражает полный путь к файлу работающего скрипта) лучше использовать $MyInvocation.PSCommandPath (которая отражает путь к вызывающему скрипту, если таковой имеется).
$MyInvocation.ScriptName продолжит работать, но я советую избегать его из-за его неясного названия; Однако есть и положительная сторона: в нем нет обнаруженной вами причуды $null (см. далее).К сожалению, у $MyInvocation.PSCommandPath последнего есть особенность/ошибка: при отсутствии вызывающего сценария он сообщает $null, а не '' (пустую строку) — см. выпуск GitHub #23828.
$null и ''; например.:
$noParentScript = -not $MyInvocation.PSCommandPath - то есть вы можете положиться на логическое приведение PowerShell, которое приводит как $null, так и '' к $false$noParentScript = $MyInvocation.PSCommandPath -like '' - в контексте подстановочного знака , совпадающего с -like, $null принуждается к ''Автоматические переменные $PSCommandPath и $PSScriptRoot были введены в PowerShell v3 (выпущенной в 2012 году) для отражения полного пути к файлу и полного пути к каталогу выполняемого сценария соответственно.
Помимо того, что они проще, чем то, что вам нужно было сделать в версиях 1 и 2 — $MyInvocation.MyCommand.Path и Split-Path -Parent $MyInvocation.MyCommand.Path — эти переменные работают последовательно,
а именно также в (скриптовых) модулях.
Для симметрии с недавно введенными автоматическими переменными в v3 $MyInvocation были присвоены новые свойства с тем же именем, т.е. $MyInvocation.PSCommandPath
и $MyInvocation.PSScriptRoot, которые сообщают аналогичную информацию о вызывающем объекте работающего сценария, т. е. вызывающем сценарии.
Таким образом, эти свойства могут не иметь значений в скрипте, вызываемом непосредственно из интерактивного сеанса или через Invoke-Expression.
Точно так же, как $PSCommandPath сейчас (в основном) дублирует старый $MyInvocation.MyCommand.Path,
так же и $MyInvocation.PSCommandPath (в основном) по отношению к старшему - и, к сожалению, названному - $MyInvocation.ScriptName
В версии 3+ (версия 2, к счастью, сейчас встречается редко), поэтому лучше использовать следующее:
$PSCommandPath и $PSScriptRoot$MyInvocation.PSCommandPath и $MyInvocation.PSScriptRootКак вы заметили, есть странность: $MyInvocation.PSCommandPath сообщает $null, а не '' (пустую строку).
если скрипт вызова отсутствует, в отличие от $MyInvocation.PSScriptRoot (и в отличие от старого эквивалента $MyInvocation.PSCommandPath,
$MyInvocation.ScriptName).
Это следует рассматривать как ошибку — простую оплошность в реализации, приводящую к неловкой асимметрии.
Я сообщил об этом в выпуске GitHub #23828, хотя и не уверен, что это будет исправлено, тем более что
может существовать код, который явно проверяет $null.
Отличный ответ, спасибо. Лично я считаю, что возврат $null более интуитивен, чем «пустая строка». Вы хотите сказать, что пустая строка больше соответствует другим подобным переменным?
Рад слышать, что это помогло, @Minkus; Не за что. По поводу $null: если бы это был C#, я бы согласился, но PowerShell не позволяет хранить $null в переменных и параметрах типа [string]; например, '' -eq [string] $null — это $true, и аналогично [string] $str = $null хранит '', а не $null. И да, есть еще более непосредственная несогласованность: $MyInvocation.PSScriptRoot возвращает '', а не $null, если нет сценария вызова.
Если у вас версия 5.1+: просто используйте
$PSCommandPath.ScriptNameдействительно является пережитком PowerShell 2.0.