Каков наилучший способ определения местоположения текущего сценария PowerShell?

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

Итак, каков наилучший стандартный способ определения каталога текущего скрипта? В настоящее время я делаю:

$MyDir = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition) 

Я знаю, что в модулях (.psm1) вы можете использовать $PSScriptRoot для получения этой информации, но это не устанавливается в обычных скриптах (т. Е. Файлы .ps1).

Каков канонический способ получить текущее местоположение файла сценария PowerShell?

PowerShell 3+

 # This is an automatic variable set to the current file's/module's directory $PSScriptRoot 

PowerShell 2

До PowerShell 3 не было лучшего способа, чем запрос свойства MyInvocation.MyCommand.Definition для общих сценариев. У меня была следующая строка вверху по существу каждого сценария powershell, который у меня был:

 $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition 

Если вы создаете модуль V2, вы можете использовать автоматическую переменную с именем $PSScriptRoot .

От PS> Справка automatic_variable

 $ PSScriptRoot
        Содержит каталог, из которого выполняется скриптовый модуль.
        Эта переменная позволяет сценариям использовать путь к модулю для доступа к другим
        Ресурсы.

Для PowerShell 3.0

 $PSCommandPath Contains the full path and file name of the script that is being run. This variable is valid in all scripts. 

Функция:

 function Get-ScriptDirectory { Split-Path -Parent $PSCommandPath } 

Может быть, я что-то пропустил здесь … но если вы хотите работать с (Get-Location).Path рабочим каталогом, вы можете просто использовать это: (Get-Location).Path для строки или Get-Location для объекта.

Если вы не ссылаетесь на что-то подобное, что я понимаю, прочитав вопрос снова.

 function Get-Script-Directory { $scriptInvocation = (Get-Variable MyInvocation -Scope 1).Value return Split-Path $scriptInvocation.MyCommand.Path } 

Я использую автоматическую переменную $ ExecutionContext, она работает от PowerShell 2 и более поздних версий.

 $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath('.\') 

$ ExecutionContext Содержит объект EngineIntrinsics, который представляет контекст выполнения хоста Windows PowerShell. Вы можете использовать эту переменную для поиска объектов выполнения, доступных для командлетов.

Мне нужно было знать имя сценария и его исполнение.

Префикс «$ global:» в структуру MyInvocation возвращает полный путь и имя сценария при вызове как из основного сценария, так и из основной строки импортированного файла библиотеки .PSM1. Он также работает из функции в импортированной библиотеке.

После долгих возиться, я решил использовать $ global: MyInvocation.InvocationName. Он надежно работает с запуском CMD, Run With Powershell и ISE. Как местные, так и UNC запускают правильный путь.

Потратил меня на то, чтобы разработать что-то, что приняло принятый ответ и превратило его в надежную функцию.

Не уверен в других, но я работаю в среде с машинами на обеих версиях PowerShell 2 и 3, поэтому мне нужно было обойти оба. Следующая функция предлагает изящный откат:

 Function Get-PSScriptRoot { $ScriptRoot = "" Try { $ScriptRoot = Get-Variable -Name PSScriptRoot -ValueOnly -ErrorAction Stop } Catch { $ScriptRoot = Split-Path $script:MyInvocation.MyCommand.Path } Write-Output $ScriptRoot } 

Это также означает, что функция ссылается на область сценария, а не на область родителя, как обрисовал Майкл Соренс в своем блоге

Очень похоже на уже опубликованные ответы, но трубопровод кажется более PS-подобным.

 $PSCommandPath | Split-Path -Parent 

Для Powershell 3+

 function Get-ScriptDirectory { if ($psise) {Split-Path $psise.CurrentFile.FullPath} else {$global:PSScriptRoot} } 

Я поместил эту функцию в свой профиль. Работает в ISE с использованием F8 / Run Selection.

Вы также можете рассмотреть split-path -parent $psISE.CurrentFile.Fullpath если какой-либо из других методов завершится с ошибкой. В частности, если вы запустите файл для загрузки кучи функций, а затем выполните эти функции с помощью оболочки ISE (или если вы запустили), кажется, что функция Get-Script-Directory как указано выше, не работает.

 function func1() { $inv = (Get-Variable MyInvocation -Scope 1).Value #$inv.MyCommand | Format-List * $Path1 = Split-Path $inv.scriptname Write-Host $Path1 } function Main() { func1 } Main 
  • Не удается установить пакет nuget из-за «Не удалось инициализировать хост PowerShell»
  • Как включить локально определенную функцию при использовании команды Invoke-Command PowerShell для удаленного доступа?
  • Рекурсивный поиск файлов с использованием PowerShell
  • Как получить емкость диска и свободное место удаленного компьютера
  • Есть ли способ сделать работу сценария powershell, дважды щелкнув файл .ps1?
  • Как получить только каталоги с помощью Get-ChildItem?
  • Удаление файлов старше 15 дней с помощью PowerShell
  • Подсчитайте элементы в папке с помощью PowerShell
  • Web.Config преобразуется за пределы Microsoft MSBuild?
  • Давайте будем гением компьютера.