Uwaga: PowerShell 1.0
Chciałbym uzyskać nazwę aktualnie wykonywanego pliku programu PowerShell. To znaczy, jeśli rozpocznę sesję w ten sposób:
powershell.exe .\myfile.ps1
Chciałbym uzyskać ciąg „. \ Myfile.ps1” (lub coś w tym rodzaju). EDYCJA : preferowany jest plik „myfile.ps1” .
Jakieś pomysły?
powershell
Ron Klein
źródło
źródło
Odpowiedzi:
Próbowałem podsumować tutaj różne odpowiedzi, zaktualizowane dla PowerShell 5:
Jeśli używasz tylko programu PowerShell 3 lub nowszego, użyj
$PSCommandPath
Jeśli chcesz kompatybilności ze starszymi wersjami, włóż podkładkę:
if ($PSCommandPath -eq $null) { function GetPSCommandPath() { return $MyInvocation.PSCommandPath; } $PSCommandPath = GetPSCommandPath; }
To dodaje,
$PSCommandPath
jeśli jeszcze nie istnieje.Kod podkładki można wykonać w dowolnym miejscu (na najwyższym poziomie lub wewnątrz funkcji), chociaż
$PSCommandPath
zmienna podlega normalnym regułom określania zakresu (np. Jeśli umieścisz podkładkę w funkcji, zmienna będzie ograniczona tylko do tej funkcji).Detale
Istnieją 4 różne metody używane w różnych odpowiedziach, więc napisałem ten skrypt, aby zademonstrować każdą (plus
$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 "";
Wynik:
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
Uwagi:
C:\
, ale rzeczywisty skrypt jestC:\Test\test.ps1
..\Test\test.ps1
)$PSCommandPath
jest jedynym niezawodnym sposobem, ale został wprowadzony w programie PowerShell 3źródło
$PSCommandPath
jeśli starsza wersja (WindowsXP) nie jest wymagana.function PSCommandPath
) i odniesienie do niewłaściwej funkcji (Write-Host " * Direct: $PSCommandPath"; Write-Host " * Function: $(ScriptName)";
- czy może przeoczę coś oczywistego?Chociaż obecna odpowiedź jest w większości przypadków poprawna, są pewne sytuacje, w których nie da ona poprawnej odpowiedzi. Jeśli używasz wewnątrz swoich funkcji skryptowych, to:
$MyInvocation.MyCommand.Name
Zwraca nazwę funkcji zamiast nazwy skryptu.
function test { $MyInvocation.MyCommand.Name }
Da ci " test " bez względu na nazwę twojego skryptu. Właściwe polecenie do uzyskania nazwy skryptu to zawsze
$MyInvocation.ScriptName
zwraca pełną ścieżkę do wykonywanego skryptu. Jeśli potrzebujesz tylko nazwy pliku skryptu, ten kod powinien ci pomóc:
split-path $MyInvocation.PSCommandPath -Leaf
źródło
$MyInvocation.ScriptName
zwróć pusty ciąg dla mnie, PS v3.0.$MyInvocation.ScriptName
działa tylko z wnętrza funkcji. Zobacz moją odpowiedź poniżej .Jeśli chcesz tylko nazwę pliku (nie pełną ścieżkę), użyj tego:
$ScriptName = $MyInvocation.MyCommand.Name
źródło
Spróbuj wykonać następujące czynności
$path = $MyInvocation.MyCommand.Definition
Może to nie dać ci rzeczywistej wpisanej ścieżki, ale da ci prawidłową ścieżkę do pliku.
źródło
$path = Split-Path $MyInvocation.MyCommand.Definition -Parent
Jeśli szukasz bieżącego katalogu, w którym wykonywany jest skrypt, możesz wypróbować ten:
$fullPathIncFileName = $MyInvocation.MyCommand.Definition $currentScriptName = $MyInvocation.MyCommand.Name $currentExecutingPath = $fullPathIncFileName.Replace($currentScriptName, "") Write-Host $currentExecutingPath
źródło
C:\ilike.ps123\ke.ps1
, prawda?Replace()
metoda zastępuje każde wystąpienie igły (nie tylko ostatnie wystąpienie) i też ją przetestowałem. Jednak dobrym pomysłem jest wykonanie odejmowania na łańcuchach.String.TrimEnd()
($currentExecutingPath = $fullPathIncFileName.TrimEnd($currentScriptName)
)? - Działa poprawnie:"Ich bin Hamster".TrimEnd("ster")
zwracaIch bin Ham
i"Ich bin Hamsterchen".TrimEnd("ster")
zwracaIch bin Hamsterchen
(zamiastIch bin Hamchen
) - Dobra!$currentScriptPath = $MyInvocation.MyCommand.Definition; $currentScriptName = $MyInvocation.MyCommand.Name; $currentScriptDir = $currentScriptPath.Substring(0,$currentScriptPath.IndexOf($currentScriptName));
uwaga: W przeciwieństwie do
$PSScriptRoot
i$PSCommandPath
automatycznych zmiennych,PSScriptRoot
aPSCommandPath
właściwości$MyInvocation
zmiennej automatycznej zawierają informacje o wywołującego lub wywołanie skryptu, a nie bieżącego skryptu.na przykład
... gdzie
DPM.ps1
zawieraWrite-Host ("="+($MyInvocation.PSCommandPath)+"!"+$PSCommandPath)
źródło
Twierdziłbym, że istnieje lepsza metoda, ustawiając zakres zmiennej $ MyInvocation.MyCommand.Path:
ex> $ script : MyInvocation.MyCommand.Name
Ta metoda działa we wszystkich okolicznościach wywołania:
Np .: 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
WYNIK:
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
Zauważ, że powyższa zaakceptowana odpowiedź NIE zwraca wartości, gdy jest wywoływana z Main. Należy również zauważyć, że powyższa zaakceptowana odpowiedź zwraca pełną ścieżkę, gdy pytanie dotyczyło tylko nazwy skryptu. Zmienna o określonym zakresie działa we wszystkich miejscach.
Ponadto, jeśli chcesz mieć pełną ścieżkę, po prostu zadzwoń:
$script:MyInvocation.MyCommand.Path
źródło
Jak zauważono w poprzednich odpowiedziach, użycie „$ MyInvocation” wiąże się z problemami dotyczącymi zakresu i niekoniecznie zapewnia spójne dane (wartość zwracana w porównaniu z wartością dostępu bezpośredniego). Zauważyłem, że "najczystszą" (najbardziej spójną) metodą uzyskiwania informacji o skrypcie, takich jak ścieżka skryptu, nazwa, parametry, wiersz poleceń itp., Niezależnie od zakresu (w głównych lub kolejnych / zagnieżdżonych wywołaniach funkcji) jest użycie "Get- Zmienna „na„ 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
Możesz więc uzyskać te same informacje, co $ PSCommandPath, ale o wiele więcej w transakcji. Nie jestem pewien, ale wygląda na to, że „Get-Variable” nie było dostępne aż do PS3, więc nie ma zbyt wiele pomocy w przypadku naprawdę starych (niezaktualizowanych) systemów.
Istnieje również kilka interesujących aspektów korzystania z "-Scope", ponieważ można cofnąć się w celu uzyskania nazw itp. Funkcji wywołujących. 0 = prąd, 1 = rodzic itd.
Mam nadzieję, że jest to trochę pomocne.
Ref, https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-variable
źródło
Przeprowadziłem kilka testów z następującym skryptem, zarówno na PS 2, jak i PS 4 i uzyskałem ten sam wynik. Mam nadzieję, że to pomaga ludziom.
$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
Wyniki -
źródło
Może to działać w przypadku większości wersji programu PowerShell:
(& { $MyInvocation.ScriptName; })
Może to działać w przypadku zaplanowanego zadania
Get-ScheduledJob |? Name -Match 'JOBNAMETAG' |% Command
źródło