每当需要引用公共模块或脚本时,我喜欢使用相对于当前脚本文件的路径。这样,我的脚本总能在库中找到其他脚本。

那么,确定当前脚本目录的最佳标准方法是什么?目前,我正在做:

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

我知道在模块(.psm1)中,您可以使用$PSScriptRoot来获取此信息,但在常规脚本(即.ps1文件)中不会设置此信息。

获取当前PowerShell脚本文件位置的规范方法是什么?


当前回答

非常类似于已经发布的答案,但管道似乎更像powershell:

$PSCommandPath | Split-Path -Parent

其他回答

PowerShell 3 +

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

PowerShell 2

在PowerShell 3之前,没有比查询 一般脚本的定义属性。我在基本上每个PowerShell脚本的顶部都有以下一行:

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

也许我遗漏了什么…但是如果你想要当前的工作目录,你可以使用这个:(Get-Location)。字符串的路径,对象的Get-Location。

除非你指的是这样的事情,我再看了一遍问题后就明白了。

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

如果你想从相对于脚本运行位置的路径加载模块,比如从“lib”子文件夹中,你需要使用以下方法之一:

$PSScriptRoot,它在作为脚本调用时工作,例如通过PowerShell命令 psISE.CurrentFile美元。FullPath,当你在ISE中运行时

但如果你都不在PowerShell中,只是在PowerShell中输入,你可以使用:

pwd。路径

你可以将这三个变量中的一个赋值给一个名为$base的变量,这取决于你运行的环境,如下所示:

$base=$(if ($psISE) {Split-Path -Path $psISE.CurrentFile.FullPath} else {$(if ($global:PSScriptRoot.Length -gt 0) {$global:PSScriptRoot} else {$global:pwd.Path})})

然后在你的脚本中,你可以这样使用它:

Import-Module $base\lib\someConstants.psm1
Import-Module $base\lib\myCoolPsModule1.psm1
#etc.

我花了一段时间来开发一些东西,把接受的答案变成一个健壮的函数。

我不确定其他人的情况,但我在一个同时使用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
}

这也意味着函数引用Script作用域,而不是Michael Sorens在他的一篇博客文章中概述的父作用域。

我使用自动变量$ExecutionContext。 它将在PowerShell 2及更高版本中工作。

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

美元的ExecutionContext 对象的engineintrinsic对象 Windows PowerShell主机的执行上下文。你可以 使用此变量查找执行对象 可用于cmdlet。