programing

현재 PowerShell 스크립트의 위치를 확인하는 가장 좋은 방법은 무엇입니까?

padding 2023. 4. 8. 08:02
반응형

현재 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

3 에는 PowerShell 3에 문의하는 보다 더 좋은 .MyInvocation.MyCommand.Definition츠미야PowerShell을 사용하다

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

모듈을 V2 할 수 .$PSScriptRoot.

PS > Help 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
}

PowerShell 3+용

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

이 기능을 프로파일에 배치했습니다.ISE에서도 /Run Selection을 사용하여 동작합니다.

지금 이렇게 .(Get-Location).Path에 대해Get-Location를 선택합니다.

이런 걸 말하는 게 아니라면, 질문을 다시 읽어보니 이해가 되네요.

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

자동 변수를 사용합니다. $ExecutionContextPowerShell 2 power power power power 。

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

$Execution Context에 엔진이 포함되어 있습니다.윈도우즈 PowerShell 호스트의 실행 컨텍스트를 나타내는 내장 개체입니다.이 변수를 사용하여 cmdlet에서 사용할 수 있는 실행 개체를 찾을 수 있습니다.

이미 게시된 답변과 매우 유사하지만 파이핑은 PowerShell과 비슷합니다.

$PSCommandPath | Split-Path -Parent

저는 그 대답을 받아들여 강력한 기능으로 바꾸는 것을 개발하는 데 시간이 걸렸습니다.

다른 사람들은 잘 모르지만 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
}

또한 이 함수는 마이클 소렌스가 블로그 투고에서 개략적으로 설명한 것처럼 부모의 범위가 아니라 스크립트 범위를 참조하는 것을 의미합니다.

이 모든 답변과 코멘트를 바탕으로 앞으로 이 질문을 보는 모든 분들을 위해 정리했습니다.다른 답변에 나와 있는 모든 상황을 다루고 있으며, Fail Safe로 발견된 다른 상황을 추가했습니다.

function Get-ScriptPath()
{
    # If using PowerShell ISE
    if ($psISE)
    {
        $ScriptPath = Split-Path -Parent -Path $psISE.CurrentFile.FullPath
    }
    # If using PowerShell 3.0 or greater
    elseif($PSVersionTable.PSVersion.Major -gt 3)
    {
        $ScriptPath = $PSScriptRoot
    }
    # If using PowerShell 2.0 or lower
    else
    {
        $ScriptPath = split-path -parent $MyInvocation.MyCommand.Path
    }

    # If still not found
    # I found this can happen if running an exe created using PS2EXE module
    if(-not $ScriptPath) {
        $ScriptPath = [System.AppDomain]::CurrentDomain.BaseDirectory.TrimEnd('\')
    }

    # Return result
    return $ScriptPath
}

스크립트 이름과 실행원지를 알아야 했습니다.

MyInvocation 구조에 "$global:"을 접두사로 붙이면 메인스크립트와 Import된 메인라인에서 모두 호출되었을 때 풀 경로와 스크립트 이름이 반환됩니다.PSM1 라이브러리 파일또한 가져온 라이브러리의 함수 내에서 작동합니다.

만지작거리다가 $global을 사용하기로 결정했다.MyInvocation.Invocation Name(호출명)CMD 부팅, Run With Powershell 및 ISE에서 안정적으로 작동합니다.로컬 부팅과 UNC 부팅 모두 올바른 경로를 반환합니다.

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

여기에 게재된 오래된 솔루션은 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"

또,split-path -parent $psISE.CurrentFile.Fullpath다른 방법 중 하나가 실패했을 경우.특히 파일을 실행하여 여러 함수를 로드한 후 ISE 쉘에서 해당 기능을 실행하는 경우(또는 선택한 경우)는 다음과 같습니다.Get-Script-Directory위와 같은 기능이 작동하지 않습니다.

"lib" 서브폴더 등 스크립트가 실행되는 위치에 상대적인 경로에서 모듈을 로드하려면 다음 중 하나를 사용해야 합니다.

$PSScriptRootPowerShell 명령어 등 스크립트로 호출할 때 기능합니다.$psISE.CurrentFile.FullPathISE 내에서 동작하고 있는 경우

그러나 둘 다 사용하지 않고 PowerShell 쉘 내에서 입력만 하면 다음을 사용할 수 있습니다.

pwd.Path

이 세 가지 중 하나를 다음 변수에 할당할 수 있습니다.$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.
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

언급URL : https://stackoverflow.com/questions/5466329/whats-the-best-way-to-determine-the-location-of-the-current-powershell-script

반응형