Как я могу получить текущий файл выполнения PowerShell?



Примечание: PowerShell 1.0

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



powershell.exe .myfile.ps1


Я хотел бы получить строку ".myfile.ps1" (или что-то в этом роде). EDIT: "myfile. ps1" предпочтительнее.

Есть идеи?

691   9  

9 ответов:

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

$MyInvocation.MyCommand.Name 

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

function test {
    $MyInvocation.MyCommand.Name
}

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

$MyInvocation.ScriptName

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

split-path $MyInvocation.PSCommandPath -Leaf

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

$ScriptName = $MyInvocation.MyCommand.Name

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

$path =  $MyInvocation.MyCommand.Definition 

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

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

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

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

Write-Host $currentExecutingPath

остерегайтесь: В отличие от $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)

Я бы сказал, что есть лучший метод, установив область переменной $MyInvocation.MyCommand.Путь:

ex>$ script:MyInvocation.MyCommand.Name

этот метод работает при всех обстоятельствах вызова:

EX: Somescript.пс1

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

провел некоторое тестирование со следующим скриптом, как на 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

Как отмечалось в предыдущих ответах, использование "$MyInvocation " зависит от проблем с областью действия и не обязательно обеспечивает согласованность данных (возвращаемое значение и значение прямого доступа). Я обнаружил, что" самый чистый " (наиболее последовательный) метод получения информации о скрипте, такой как путь к скрипту, имя, parms, командная строка и т. д. независимо от области действия (в основном или последующих/вложенных вызовах функций) следует использовать "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, поэтому не очень много помощи для действительно старых (не обновленных) систем.

есть также некоторые интересные аспекты при использовании "рамки" как вы можете возвратиться, чтобы получить имена и т. д. функции вызова(ов). 0=Текущий, 1=родитель, и т. д.

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

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

Comments

    Ничего не найдено.