現在のPowerShell実行ファイルを取得するにはどうすればよいですか?


92

注:PowerShell 1.0
現在実行中のPowerShellファイル名を取得します。つまり、次のようにセッションを開始すると、

powershell.exe .\myfile.ps1

文字列"。\ myfile.ps1"(またはそのようなもの)を取得します。編集"myfile.ps1"が推奨されます。
何か案は?


ありがとう、現在の答えはほとんど同じですが、必要なのはファイル名(パス全体ではなく)だけなので、受け入れられる答えは@Keithです。ただし、両方の回答に+1します。今、私は$ MyInvocationについて知っています:-)
ロンクライン

含まれているスクリプトから親スクリプトを取得するのはどうですか?
Florin Sabau 2013

回答:


67

ここでは、PowerShell 5用に更新されたさまざまな答えを要約しようとしました。

  • PowerShell 3以降のみを使用している場合は、 $PSCommandPath

  • 古いバージョンとの互換性が必要な場合は、shimを挿入します。

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

    これは$PSCommandPath、まだ存在しない場合に追加されます。

    シムコードはどこでも(トップレベルまたは関数内で)実行できますが、$PSCommandPath変数は通常のスコープルールに従います(たとえば、シムを関数に入れると、変数のスコープはその関数のみになります)。

詳細

さまざまな回答で使用される4つの異なる方法があるので、それぞれを(プラス$PSCommandPath)を示すためにこのスクリプトを作成しました。

function PSCommandPath() { return $PSCommandPath; }
function ScriptName() { return $MyInvocation.ScriptName; }
function MyCommandName() { return $MyInvocation.MyCommand.Name; }
function MyCommandDefinition() {
    # Begin of MyCommandDefinition()
    # Note: ouput of this script shows the contents of this function, not the execution result
    return $MyInvocation.MyCommand.Definition;
    # End of MyCommandDefinition()
}
function MyInvocationPSCommandPath() { 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: $(MyInvocationPSCommandPath)";
Write-Host "";

出力:

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

PSVersion: 5.1.19035.1

$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:
    # Begin of MyCommandDefinition()
    # Note this is the contents of the MyCommandDefinition() function, not the execution results
    return $MyInvocation.MyCommand.Definition;
    # End of MyCommandDefinition()


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

ノート:

  • から実行されましたC:\が、実際のスクリプトはC:\Test\test.ps1です。
  • 渡された呼び出しパスを伝えるメソッドはありません(.\Test\test.ps1
  • $PSCommandPath 唯一の信頼できる方法ですが、PowerShell 3で導入されました
  • 3より前のバージョンの場合、関数の内部と外部の両方で機能する単一のメソッドはありません

7
今日(2017年)を読んでいる人は、この投稿を正解として読むべきです!+1
コリンチャフィン2017

2
@CollinChaffin:同意され、現在(2017)は、現在最もサポートされていないのはWindows 7なので$PSCommandPath、レガシー(WindowsXP)が必要ない場合に使用しない理由はありません。
tukan

最初のコード例には、同じ関数の2つの定義(function PSCommandPath)と間違った関数への参照が含まれているため、欠陥があります(Write-Host " * Direct: $PSCommandPath"; Write-Host " * Function: $(ScriptName)";または、明らかなものを見落としているか?
Mike L'Angelo

@ MikeL'Angeloそうですね!3年間気付かれなかった。修正しました、ありがとうございます。出力と結論は同じですが。
gregmac

81

ほとんどの場合、現在の回答は正しいですが、特定の状況では正しい回答が得られない場合があります。スクリプト関数内で使用する場合:

$MyInvocation.MyCommand.Name 

スクリプトの名前ではなく、関数の名前を返します。

function test {
    $MyInvocation.MyCommand.Name
}

スクリプトの名前に関係なく、「テスト」を提供します。スクリプト名を取得するための正しいコマンドは常に

$MyInvocation.ScriptName

これは、実行しているスクリプトの完全パスを返します。スクリプトのファイル名だけが必要な場合は、このコードが役立つはずです。

split-path $MyInvocation.PSCommandPath -Leaf

6
トップレベルでは、スクリプト名はposh v4では未定義であることに注意してください。最上位で$ MyInvocation.MyCommand.Definitionを使用して、他の回答のようにフルパスまたは名前を指定します。
AnneTheAgile 2015

30
$MyInvocation.ScriptName私にはPS v3.0の空の文字列を返します。
JohnC、2015

4
@JohnC $MyInvocation.ScriptNameは関数内からのみ機能します。以下の私の答えを参照しください。
gregmac

72

フルパスではなくファイル名だけが必要な場合は、次のようにします。

$ScriptName = $MyInvocation.MyCommand.Name

32

以下をお試しください

$path =  $MyInvocation.MyCommand.Definition 

これは入力された実際のパスを提供しない場合がありますが、ファイルへの有効なパスを提供します。


1
@ハミッシュは、ファイルから呼び出された場合に具体的に言う。
JaredPar '18年

参考:これにより、フルパスとファイル名が得られます(
Powershell

私はまさにこのコマンドを探していました。JaredPar、ありがとう!:)
sqlfool 2013年

分割パスを使用してディレクトリを取得しますか?$path = Split-Path $MyInvocation.MyCommand.Definition -Parent
2017

7

スクリプトが実行されている現在のディレクトリを探している場合は、これを試すことができます。

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

Write-Host $currentExecutingPath

1
それはで正しく動作しませんC:\ilike.ps123\ke.ps1か?
fridojet

@fridojet-わかりません、テストするPS端末の近くではありません。試してみてみませんか?
Ryk

いいえ、ただの修辞的な質問です;-)- Replace()メソッドは針のすべての発生(最後の発生だけでなく)を置き換え、私もテストしたので、それは論理的です。ただし、文字列の減算のようなことをするのは良い考えです。
fridojet

... String.TrimEnd()$currentExecutingPath = $fullPathIncFileName.TrimEnd($currentScriptName))はどうですか?-正常に動作してい"Ich bin Hamster".TrimEnd("ster")ます:(の代わりに)リターンIch bin Ham"Ich bin Hamsterchen".TrimEnd("ster")リターン-ファイン!Ich bin HamsterchenIch bin Hamchen
fridojet

$currentScriptPath = $MyInvocation.MyCommand.Definition; $currentScriptName = $MyInvocation.MyCommand.Name; $currentScriptDir = $currentScriptPath.Substring(0,$currentScriptPath.IndexOf($currentScriptName));
YP 2013年

7

注意:$PSScriptRootおよび$PSCommandPath自動変数とは異なり、自動変数の PSScriptRootおよびPSCommandPathプロパティには$MyInvocation、現在のスクリプトではなく、呼び出し元または呼び出し元のスクリプトに関する情報が含まれています。

例えば

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

...どこDPM.ps1

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

4

変数$ MyInvocation.MyCommand.Pathのスコープを設定することにより、より良い方法があると私は主張します。

ex> $ script:MyInvocation.MyCommand.Name

このメソッドは、呼び出しのすべての状況で機能します。

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

出力:

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

上記の受け入れられた回答がMainから呼び出されたときに値を返さないことに注意してください。また、質問がスクリプト名のみを要求した場合、上記の受け入れられた回答は完全なパスを返すことに注意してください。スコープ変数はすべての場所で機能します。

また、完全なパスが必要な場合は、次のように呼び出します。

$script:MyInvocation.MyCommand.Path

3

以前の応答で述べたように、「$ MyInvocation」の使用はスコープの問題の影響を受けやすく、必ずしも一貫したデータ(戻り値と直接アクセス値)を提供するわけではありません。スコープに関係なく、スクリプトパス、名前、パラメーター、コマンドラインなどのスクリプト情報を取得するための「最もクリーンな」(最も一貫性のある)メソッドは、(メインまたは後続/ネストされた関数呼び出しで)「Get- 「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

そのため、$ PSCommandPathと同じ情報を取得できますが、取引の内容はさらに多くなります。確かではありませんが、PS3までは "Get-Variable"が利用できなかったため、本当に古い(更新されていない)システムにはあまり役立ちません。

また、「-Scope」を使用すると、呼び出し元の関数の名前などを取得するためにバックトラックできるため、いくつかの興味深い側面があります。0 =現在、1 =親など

これが多少役立つことを願っています。

参照、https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-variable


1

PS 2とPS 4の両方で、次のスクリプトを使用していくつかのテストを行い、同じ結果が得られました。これが人々の役に立つことを願っています。

$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

結果 -

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

1

これはほとんどのpowershellバージョンで動作します:

(& { $MyInvocation.ScriptName; })

これはスケジュールされたジョブで機能します

Get-ScheduledJob |? Name -Match 'JOBNAMETAG' |% Command
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.