code

현재 PowerShell 실행 파일을 얻으려면 어떻게해야합니까?

codestyles 2020. 9. 20. 10:00
반응형

현재 PowerShell 실행 파일을 얻으려면 어떻게해야합니까?


참고 : PowerShell 1.0
현재 실행중인 PowerShell 파일 이름을 얻고 싶습니다. 즉, 다음과 같이 세션을 시작하면 :

powershell.exe .\myfile.ps1

문자열 ". \ myfile.ps1" (또는 이와 유사한 것) 을 얻고 싶습니다 . 편집 : "myfile.ps1" 이 바람직합니다.
어떤 아이디어?


대부분의 경우 현재 답변이 맞지만 정답을 제공하지 못하는 특정 상황이 있습니다. 스크립트 함수 내에서 사용하는 경우 :

$MyInvocation.MyCommand.Name 

스크립트 이름 대신 함수 이름을 반환합니다.

function test {
    $MyInvocation.MyCommand.Name
}

스크립트 이름에 관계없이 " test "를 제공합니다 . 스크립트 이름을 얻기위한 올바른 명령은 항상

$MyInvocation.ScriptName

실행중인 스크립트의 전체 경로를 반환합니다. 이 코드가 도움이 될 것보다 스크립트 파일 이름 만 필요한 경우 :

split-path $MyInvocation.PSCommandPath -Leaf

전체 경로가 아닌 파일 이름 만 원하면 다음을 사용하십시오.

$ScriptName = $MyInvocation.MyCommand.Name

여기에 PowerShell 5 용으로 업데이트 된 다양한 답변을 요약하려고했습니다.

  • PowerShell 3 이상 만 사용하는 경우 $PSCommandPath
  • 이전 버전과의 호환성을 원하면 shim을 삽입하십시오.

    if ($PSCommandPath -eq $null) { function GetPSCommandPath() { return $MyInvocation.PSCommandPath; } $PSCommandPath = GetPSCommandPath; }

    $PSCommandPath이미 존재하지 않는 경우 추가 됩니다.

    $PSCommandPath변수는 일반적인 범위 지정 규칙 (예 : 함수에 shim을 넣는 경우 변수의 범위가 해당 함수로만 지정됨)이 적용 되지만 shim 코드는 어디에서나 실행할 수 있습니다 (최상위 수준 또는 함수 내부 ).

세부

다양한 답변에 사용되는 4 가지 방법이 있으므로 각각을 설명하기 위해이 스크립트를 작성했습니다 $PSCommandPath.

function PSCommandPath() { return $PSCommandPath; }
function ScriptName() { return $MyInvocation.ScriptName; }
function MyCommandName() { return $MyInvocation.MyCommand.Name; }
function MyCommandDefinition() { return $MyInvocation.MyCommand.Definition; # Note this is the contents of the MyCommandDefinition function  
}
function PSCommandPath() { return $MyInvocation.PSCommandPath; }

Write-Host "";
Write-Host "PSVersion: $($PSVersionTable.PSVersion)";
Write-Host "";
Write-Host "`$PSCommandPath:";
Write-Host " *   Direct: $PSCommandPath";
Write-Host " * Function: $(ScriptName)";
Write-Host "";
Write-Host "`$MyInvocation.ScriptName:";
Write-Host " *   Direct: $($MyInvocation.ScriptName)";
Write-Host " * Function: $(ScriptName)";
Write-Host "";
Write-Host "`$MyInvocation.MyCommand.Name:";
Write-Host " *   Direct: $($MyInvocation.MyCommand.Name)";
Write-Host " * Function: $(MyCommandName)";
Write-Host "";
Write-Host "`$MyInvocation.MyCommand.Definition:";
Write-Host " *   Direct: $($MyInvocation.MyCommand.Definition)";
Write-Host " * Function: $(MyCommandDefinition)";
Write-Host "";
Write-Host "`$MyInvocation.PSCommandPath:";
Write-Host " *   Direct: $($MyInvocation.PSCommandPath)";
Write-Host " * Function: $(PSCommandPath)";
Write-Host "";

산출:

PS C:\> .\Test\test.ps1

PSVersion: 5.1.14393.1066

$PSCommandPath:
 *   Direct: C:\Test\test.ps1
 * Function: C:\Test\test.ps1

$MyInvocation.ScriptName:
 *   Direct:
 * Function: C:\Test\test.ps1

$MyInvocation.MyCommand.Name:
 *   Direct: test.ps1
 * Function: MyCommandName

$MyInvocation.MyCommand.Definition:
 *   Direct: C:\Test\test.ps1
 * Function:  return $MyInvocation.MyCommand.Definition; # Note this is the contents of the MyCommandDefinition function


$MyInvocation.PSCommandPath:
 *   Direct:
 * Function: C:\Test\test.ps1

노트:

  • Executed from C:\, but actual script is C:\Test\test.ps1.
  • No method tells you the original invocation path (.\Test\test.ps1)
  • $PSCommandPath is the only reliable way, but was introduced in PowerShell 3
  • For versions prior to 3, no single method works both inside and outside of a function

Try the following

$path =  $MyInvocation.MyCommand.Definition 

This may not give you the actual path typed in but it will give you a valid path to the file.


If you are looking for the current directory in which the script is being executed, you can try this one:

$fullPathIncFileName = $MyInvocation.MyCommand.Definition
$currentScriptName = $MyInvocation.MyCommand.Name
$currentExecutingPath = $fullPathIncFileName.Replace($currentScriptName, "")

Write-Host $currentExecutingPath

beware: Unlike the $PSScriptRoot and $PSCommandPath automatic variables, the PSScriptRoot and PSCommandPath properties of the $MyInvocation automatic variable contain information about the invoker or calling script, not the current script.

e.g.

PS C:\Users\S_ms\OneDrive\Documents> C:\Users\SP_ms\OneDrive\Documents\DPM ...
=!C:\Users\S_ms\OneDrive\Documents\DPM.ps1

...where DPM.ps1 contains

Write-Host ("="+($MyInvocation.PSCommandPath)+"!"+$PSCommandPath)

I would argue that there is a better method, by setting the scope of the variable $MyInvocation.MyCommand.Path:

ex> $script:MyInvocation.MyCommand.Name

This method works in all circumstances of invocation:

EX: Somescript.ps1

function printme () {
    "In function:"
    ( "MyInvocation.ScriptName: " + [string]($MyInvocation.ScriptName) )
    ( "script:MyInvocation.MyCommand.Name: " + [string]($script:MyInvocation.MyCommand.Name) )
    ( "MyInvocation.MyCommand.Name: " + [string]($MyInvocation.MyCommand.Name) )
}
"Main:"
( "MyInvocation.ScriptName: " + [string]($MyInvocation.ScriptName) )
( "script:MyInvocation.MyCommand.Name: " + [string]($script:MyInvocation.MyCommand.Name) )
( "MyInvocation.MyCommand.Name: " + [string]($MyInvocation.MyCommand.Name) )
" "
printme
exit

OUTPUT:

PS> powershell C:\temp\test.ps1
Main:
MyInvocation.ScriptName:
script:MyInvocation.MyCommand.Name: test.ps1
MyInvocation.MyCommand.Name: test.ps1

In function:
MyInvocation.ScriptName: C:\temp\test.ps1
script:MyInvocation.MyCommand.Name: test.ps1
MyInvocation.MyCommand.Name: printme

Notice how the above accepted answer does NOT return a value when called from Main. Also, note that the above accepted answer returns the full path when the question requested the script name only. The scoped variable works in all places.

Also, if you did want the full path, then you would just call:

$script:MyInvocation.MyCommand.Path

Did some testing with the following script, on both PS 2 and PS 4 and had the same result. I hope this helps people.

$PSVersionTable.PSVersion
function PSscript {
  $PSscript = Get-Item $MyInvocation.ScriptName
  Return $PSscript
}
""
$PSscript = PSscript
$PSscript.FullName
$PSscript.Name
$PSscript.BaseName
$PSscript.Extension
$PSscript.DirectoryName

""
$PSscript = Get-Item $MyInvocation.InvocationName
$PSscript.FullName
$PSscript.Name
$PSscript.BaseName
$PSscript.Extension
$PSscript.DirectoryName

Results -

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      -1     -1      

C:\PSscripts\Untitled1.ps1
Untitled1.ps1
Untitled1
.ps1
C:\PSscripts

C:\PSscripts\Untitled1.ps1
Untitled1.ps1
Untitled1
.ps1
C:\PSscripts

As noted in previous responses, using "$MyInvocation" is subject to scoping issues and doesn't necessarily provide consistent data (return value vs. direct access value). I've found that the "cleanest" (most consistent) method for getting script info like script path, name, parms, command line, etc. regardless of scope (in main or subsequent/nested function calls) is to use "Get-Variable" on "MyInvocation"...

# Get the MyInvocation variable at script level
# Can be done anywhere within a script
$ScriptInvocation = (Get-Variable MyInvocation -Scope Script).Value

# Get the full path to the script
$ScriptPath = $ScriptInvocation.MyCommand.Path

# Get the directory of the script
$ScriptDirectory = Split-Path $ScriptPath

# Get the script name
# Yes, could get via Split-Path, but this is "simpler" since this is the default return value
$ScriptName = $ScriptInvocation.MyCommand.Name

# Get the invocation path (relative to $PWD)
# @GregMac, this addresses your second point
$InvocationPath = ScriptInvocation.InvocationName

So, you can get the same info as $PSCommandPath, but a whole lot more in the deal. Not sure, but it looks like "Get-Variable" was not available until PS3 so not a lot of help for really old (not updated) systems.

There are also some interesting aspects when using "-Scope" as you can backtrack to get the names, etc. of the calling function(s). 0=current, 1=parent, etc.

Hope this is somewhat helpful.

Ref, https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-variable


This can works on most powershell versions:

(& { $MyInvocation.ScriptName; })

This can work for Scheduled Job

Get-ScheduledJob |? Name -Match 'JOBNAMETAG' |% Command

참고URL : https://stackoverflow.com/questions/817198/how-can-i-get-the-current-powershell-executing-file

반응형