Geçerli PowerShell yürütme dosyasını nasıl edinebilirim?


99

Not: PowerShell 1.0
Geçerli çalıştırılan PowerShell dosya adını almak istiyorum. Yani seansıma şöyle başlarsam:

powershell.exe .\myfile.ps1

". \ Myfile.ps1" (veya bunun gibi bir şey) dizesini almak istiyorum . DÜZENLEME : "myfile.ps1" tercih edilir.
Herhangi bir fikir?


Teşekkürler, mevcut cevaplar hemen hemen aynı, ancak sadece dosya adına ihtiyacım var (tüm yol değil), bu nedenle kabul edilen cevap @ Keith's. Yine de her iki yanıta da +1. Şimdi $ MyInvocation şeyini biliyorum :-)
Ron Klein

Ana komut dosyasını dahil edilen bir komut dosyasından almaya ne dersiniz?
Florin Sabau

Yanıtlar:


78

PowerShell 5 için güncellenen, buradaki çeşitli yanıtları özetlemeye çalıştım:

  • Yalnızca PowerShell 3 veya üstünü kullanıyorsanız, $PSCommandPath

  • Eski sürümlerle uyumluluk istiyorsanız, altlığı takın:

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

    Bu $PSCommandPath, zaten mevcut değilse ekler .

    $PSCommandPathDeğişken normal kapsam kurallarına tabi olsa da (örneğin, eğer bir fonksiyona şimi koyarsanız, değişken sadece o fonksiyona göre ayarlanır ), herhangi bir yerde (üst seviye veya bir fonksiyonun içinde ) çalıştırılabilir.

Detaylar

Çeşitli cevaplarda kullanılan 4 farklı yöntem var, bu yüzden bu komut dosyasını her birini (artı $PSCommandPath) göstermek için yazdım :

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 "";

Çıktı:

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

Notlar:

  • Tarafından yürütüldü C:\, ancak gerçek komut dosyası C:\Test\test.ps1.
  • Hiçbir yöntem size geçilen çağrı yolunu söylemez ( .\Test\test.ps1)
  • $PSCommandPath tek güvenilir yoldur, ancak PowerShell 3'te tanıtıldı
  • 3'ten önceki sürümler için, bir işlevin içinde ve dışında tek bir yöntem çalışmaz

7
Bugün (2017) okuyan herkes için BU yazıyı doğru cevap olarak okumalılar! +1
Collin Chaffin

2
@CollinChaffin: kabul edildi ve şimdi (2017) şu anda en az desteklenen Windows 7'dir, bu nedenle $PSCommandPatheski (WindowsXP) gerekli değilse kullanmamak için bir neden yoktur .
tukan

İlk kod örneği, aynı işlevin iki tanımını ( function PSCommandPath) ve yanlış işleve ( Write-Host " * Direct: $PSCommandPath"; Write-Host " * Function: $(ScriptName)";- yoksa bariz bir şeyi gözden kaçırıyor muyum?
Mike L'Angelo

@ MikeL'Angelo Haklısın! 3 yıldır fark edilmeden gitti. Düzeltildi, teşekkürler. Çıktı ve sonuç aynı olsa da.
gregmac

82

Mevcut Cevap çoğu durumda doğru olsa da, size doğru cevabı vermeyeceği bazı durumlar vardır. Komut dosyası işlevlerinizin içinde kullanırsanız, o zaman:

$MyInvocation.MyCommand.Name 

Komut dosyasının adı yerine işlevin adını döndürür.

function test {
    $MyInvocation.MyCommand.Name
}

Senaryonuzun adı ne olursa olsun size " test " verecektir . Komut dosyası adını almak için doğru komut her zaman

$MyInvocation.ScriptName

bu yürütmekte olduğunuz betiğin tam yolunu döndürür. Yalnızca komut dosyası adına ihtiyacınız varsa, bu kodun size yardımcı olması gerekir:

split-path $MyInvocation.PSCommandPath -Leaf

6
En üst düzeyde, Scriptname posh v4 ile tanımsızdır. En üst düzeyde, tam yol için $ MyInvocation.MyCommand.Definition veya diğer cevaplara göre Name kullanmayı seviyorum.
AnneTheAgile

30
$MyInvocation.ScriptNamebenim için boş dize döndür, PS v3.0.
JohnC

4
@JohnC $MyInvocation.ScriptNameyalnızca bir işlevin içinden çalışır. Bkz aşağıda Cevabımı .
gregmac

73

Yalnızca dosya adını istiyorsanız (tam yolu değil) şunu kullanın:

$ScriptName = $MyInvocation.MyCommand.Name

33

Takip etmeyi dene

$path =  $MyInvocation.MyCommand.Definition 

Bu size yazılan gerçek yolu vermeyebilir, ancak size dosyaya giden geçerli bir yol verecektir.


1
@Hamish soru özellikle bir dosyadan çağrılıp çağrılmadığını söylüyor.
JaredPar

Bilginize: Bu size tam yolu ve dosya adını verir (Powershell 2.0)
Ralph Willgoss

Tam olarak bu komutu arıyordum. Teşekkürler JaredPar! :)
sqlfool

Dizini almak için Bölünmüş Yol kullanılsın mı? $path = Split-Path $MyInvocation.MyCommand.Definition -Parent
Underverse

8

Komut dosyasının yürütüldüğü geçerli dizini arıyorsanız, bunu deneyebilirsiniz:

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

Write-Host $currentExecutingPath

1
Bu doğru şekilde çalışmaz C:\ilike.ps123\ke.ps1, değil mi?
fridojet

@fridojet - Emin değilim, test etmek için bir PS terminalinin yakınında değil. Neden denemiyorsun ve görmüyorsun?
Ryk

Hayır, sadece retorik bir soru ;-) - Bu sadece mantıklı olurdu çünkü Replace()yöntem iğnenin her oluşumunun yerini alıyor (sadece son kez değil) ve ben de test ettim. Bununla birlikte, dizelerden çıkarma gibi bir şey yapmak güzel bir fikirdir.
fridojet

... Peki ya String.TrimEnd()( $currentExecutingPath = $fullPathIncFileName.TrimEnd($currentScriptName))? - Doğru çalışıyor: "Ich bin Hamster".TrimEnd("ster")döndürür Ich bin Hamve "Ich bin Hamsterchen".TrimEnd("ster")döndürür Ich bin Hamsterchen(yerine Ich bin Hamchen) - İyi!
fridojet

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

7

dikkat: $PSScriptRootve $PSCommandPathotomatik değişkenlerin aksine, otomatik değişkenin PSScriptRootve PSCommandPathözellikleri $MyInvocation, geçerli komut dosyası değil, çağıran veya çağıran komut dosyası hakkında bilgi içerir.

Örneğin

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

... nerede DPM.ps1içerir

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

5

Önceki yanıtlarda belirtildiği gibi, "$ MyInvocation" kullanımı kapsam belirleme sorunlarına tabidir ve mutlaka tutarlı veriler sağlamaz (doğrudan erişim değerine karşı dönüş değeri). Kapsama bakılmaksızın (ana veya sonraki / iç içe geçmiş işlev çağrılarında) komut dosyası yolu, adı, parametreleri, komut satırı vb. Gibi komut dosyası bilgilerini almak için "en temiz" (en tutarlı) yöntemin "Get- "Çağrım" üzerindeki "Değişken" ...

# 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

Böylece, $ PSCommandPath ile aynı bilgileri alabilirsiniz, ancak anlaşmada çok daha fazlasını alabilirsiniz. Emin değilim, ancak görünen o ki "Get-Variable" PS3'e kadar mevcut değildi, bu yüzden gerçekten eski (güncellenmemiş) sistemler için çok fazla yardım yoktu.

Çağıran işlev (ler) in isimlerini vb. Almak için geriye doğru gidebileceğiniz için "-Scope" kullanırken bazı ilginç yönler de vardır. 0 = akım, 1 = ebeveyn vb.

Umarım bu biraz yardımcı olur.

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


4

$ MyInvocation.MyCommand.Path değişkeninin kapsamını ayarlayarak daha iyi bir yöntem olduğunu iddia ediyorum:

ex> $ script : MyInvocation.MyCommand.Name

Bu yöntem, tüm çağrı koşullarında çalışır:

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

ÇIKTI:

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

Yukarıdaki kabul edilen cevabın Ana'dan çağrıldığında nasıl bir değer döndürmediğine dikkat edin. Ayrıca, soru yalnızca komut dosyası adını istediğinde, yukarıda kabul edilen yanıtın tam yolu döndürdüğünü unutmayın. Kapsamlı değişken her yerde çalışır.

Ayrıca, tam yolu istiyorsanız, o zaman sadece şunu çağırırsınız:

$script:MyInvocation.MyCommand.Path

1

Aşağıdaki komut dosyasıyla hem PS 2 hem de PS 4 üzerinde bazı testler yaptık ve aynı sonucu aldı. Umarım bu insanlara yardımcı olur.

$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

Sonuçlar -

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

Bu, çoğu powershell sürümünde çalışabilir:

(& { $MyInvocation.ScriptName; })

Bu Planlanmış İş için işe yarayabilir

Get-ScheduledJob |? Name -Match 'JOBNAMETAG' |% Command
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.