确定当前PowerShell脚本位置的最佳方法是什么?

问题描述 投票:451回答:13

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

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

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

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

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

powershell powershell-v2.0
13个回答
748
投票

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

5
投票

我总是使用这个小片段,它以同样的方式用于Powershell和ISE:

# set active path to script-location:
$path = $MyInvocation.MyCommand.Path
if (!$path) {$path = $psISE.CurrentFile.Fullpath}
if ( $path) {$path = split-path $path -Parent}
set-location $path

2
投票

如果任何其他方法失败,您也可以考虑使用split-path -parent $psISE.CurrentFile.Fullpath。特别是,如果你运行一个文件来加载一堆函数,然后在ISE shell中执行这些函数(或者如果你运行选择),那么上面的Get-Script-Directory函数似乎不起作用。


2
投票

发现此处发布的旧解决方案在PowerShell V5上对我不起作用。我想出了这个:

try {
    $scriptPath = $PSScriptRoot
    if (!$scriptPath)
    {
        if ($psISE)
        {
            $scriptPath = Split-Path -Parent -Path $psISE.CurrentFile.FullPath
        } else {
            Write-Host -ForegroundColor Red "Cannot resolve script file's path"
            exit 1
        }
    }
} catch {
    Write-Host -ForegroundColor Red "Caught Exception: $($Error[0].Exception.Message)"
    exit 2
}

Write-Host "Path: $scriptPath"

HTH


-3
投票
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

58
投票

如果要创建V2模块,可以使用名为$PSScriptRoot的自动变量。

从PS>帮助automatic_variable

$PSScriptRoot
       Contains the directory from which the script module is being executed.
       This variable allows scripts to use the module path to access other
       resources.

30
投票

适用于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
}

14
投票

也许我在这里遗漏了一些东西...但如果你想要现在的工作目录,你可以使用:(Get-Location).Path表示字符串,Get-Location表示对象。

除非你指的是这样的东西,我在再次阅读这个问题后理解这一点。

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

13
投票

对于Powershell 3+

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

我已将此功能放在我的个人资料中。也可以使用F8 / Run Selection在ISE中运行。


11
投票

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

$PSCommandPath | Split-Path -Parent

10
投票

我使用automatic variable $ ExecutionContext,它适用于PowerShell 2及更高版本。

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

$ ExecutionContext包含一个EngineIntrinsics对象,该对象表示Windows PowerShell主机的执行上下文。您可以使用此变量来查找cmdlet可用的执行对象。


7
投票

我需要知道脚本名称及其执行位置。

将“$ global:”前缀添加到MyInvocation结构时,将从主脚本和导入的.PSM1库文件的主行调用时返回完整路径和脚本名称。它也可以在导入库的函数内部工作。

经过多次摆弄后,我决定使用$ global:MyInvocation.InvocationName。它可靠地运行CMD,Run With Powershell和ISE。本地和UNC发射都返回正确的路径。


7
投票

花了一些时间来开发一些能够接受已接受答案的东西并将其变成一个强大的功能。

不确定其他人,但我在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
}

这也意味着该函数指的是脚本范围,而不是Michael Sorens在他的blog中概述的父母范围。

© www.soinside.com 2019 - 2024. All rights reserved.