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

это должна быть простая задача, но я видел несколько попыток получить путь к каталогу, где выполняется командлет, со смешанным успехом. Например, когда я выполняю c:tempmyscriptsmycmdlet.ps1, который имеет файл настроек на c:tempmyscriptssettings.xml Я хотел бы иметь возможность хранить c:tempmyscripts в переменной внутри mycmdlet.ps1.

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

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

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

$settingspath = '.settings.xml'

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

12 ответов


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

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


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

(Get-Item -Path ".\").FullName

самым простым методом, по-видимому, является использование следующей предопределенной переменной:

 $PSScriptRoot

about_Automatic_Variables и about_Scripts как государственные, так:

в PowerShell 2.0 эта переменная действительна только в модулях скриптов (.psm1 успешно). Начиная с PowerShell 3.0, он действителен во всех сценариях.

Я использую его так:

 $MyFileName = "data.txt"
 $filebase = Join-Path $PSScriptRoot $MyFileName

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

(Resolve-Path .\).Path

часть в скобках возвращает PathInfo


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

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("\"));
    }
}

попробовать все это: (Get-Location).путь или ($пароль.)путь


Get-Location вернет текущее местоположение

$Currentlocation=Get-Location


Мне нравится одна строка решение :)

$scriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent

попробуйте это:

$WorkingDir = Convert-Path .

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


чтобы развернуть ответ @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
    }

}

в PowerShell 3 и выше, вы можете просто использовать

$PSScriptRoot