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

Это должна быть простая задача, но я видел несколько попыток получить путь к каталогу, в котором находится исполняемый командлет, со смешанным успехом. Например, когда я выполняю c:\temp\myscripts\mycmdlet.ps1, у которого есть файл настроек в c:\temp\myscripts\settings.xml, я хотел бы иметь возможность хранить c:\temp\myscripts в переменной в mycmdlet PS1.

Это одно решение, которое работает (хотя и немного громоздко):

$invocation = (Get-Variable MyInvocation).Value
$directorypath = Split-Path $invocation.MyCommand.Path
$settingspath = $directorypath + '\settings.xml'

Другой предложил это решение, которое работает только в нашей тестовой среде:

$settingspath = '.\settings.xml'

Мне нравится, что последний очень подходит и предпочитает, чтобы он каждый раз анализировал путь к файлу как параметр, но я не могу заставить его работать в моей среде разработки. Есть ли у кого-нибудь предложение о том, что делать? Имеет ли это отношение к настройке PowerShell?

4b9b3361

Надежный способ сделать это так же, как вы показали $MyInvocation.MyCommand.Path.

Использование относительных путей будет основываться на $pwd, в PowerShell, текущем каталоге приложения или текущем рабочем каталоге для .NET API.

86
ответ дан 07 дек. '11 в 0:15
источник

Да, это должно сработать. Но если вам нужно увидеть абсолютный путь, это все, что вам нужно:

(Get-Item -Path ".\" -Verbose).FullName
136
ответ дан 17 апр. '14 в 14:30
источник

Вы также можете использовать:

(Resolve-Path .\).Path

В скобках возвращается объект PathInfo.

(Доступно с версии PowerShell 2.0.)

35
ответ дан 27 мая '15 в 5:23
источник

Путь часто равен нулю. Эта функция более безопасна.

function Get-ScriptDirectory
{
    $Invocation = (Get-Variable MyInvocation -Scope 1).Value;
    if($Invocation.PSScriptRoot)
    {
        $Invocation.PSScriptRoot;
    }
    Elseif($Invocation.MyCommand.Path)
    {
        Split-Path $Invocation.MyCommand.Path
    }
    else
    {
        $Invocation.InvocationName.Substring(0,$Invocation.InvocationName.LastIndexOf("\"));
    }
}
31
ответ дан 23 окт. '13 в 16:08
источник

Самый простой способ заключается в использовании следующей предопределенной переменной, хотя я не уверен, что она зависит от версии:

 $PSScriptRoot

Я использую его следующим образом:

 $MyFileName = "data.txt"
 $filebase = $PSScriptRoot + "\" + $MyFileName
22
ответ дан 24 сент. '14 в 19:05
источник

Вы думаете, что использование ". \" в качестве пути означает, что это путь вызова. Но не все время. Например, если вы используете его внутри задания ScriptBlock. В этом случае он может указывать на% profile%\Documents.

1
ответ дан 06 дек. '13 в 16:05
источник

Чтобы расширить ответ на @Cradle: вы также можете написать многоцелевую функцию, которая даст вам тот же результат по запросу OP:

Function Get-AbsolutePath {

    [CmdletBinding()]
    Param(
        [parameter(
            Mandatory=$false,
            ValueFromPipeline=$true
        )]
        [String]$relativePath=".\"
    )

    if (Test-Path -Path $relativePath) {
        return (Get-Item -Path $relativePath).FullName -replace "\\$", ""
    } else {
        Write-Error -Message "'$relativePath' is not a valid path" -ErrorId 1 -ErrorAction Stop
    }

}
0
ответ дан 17 янв. '16 в 2:05
источник