Übergeben von Befehlszeilenargumenten an eine PowerShell ps1-Datei

87

Seit Jahren verwende ich die cmd/DOS/WindowsShell und übergebe Befehlszeilenargumente an Batchdateien. Zum Beispiel habe ich eine Datei, zuzu.batund in ihm, ich Zugang %1, %2usw. Nun mag ich das gleiche tun , wenn ich einen Anruf PowerShellSkript when I am in a Cmd.exe shell. Ich habe ein Skript xuxu.ps1(und ich habe meiner PATHEXT-Variablen und den mit PowerShell verknüpften PS1-Dateien PS1 hinzugefügt). Aber egal was ich mache, ich scheine nichts von der $argsVariablen zu bekommen . Es hat immer die Länge 0.

Wenn ich in einer PowerShellShell bin cmd.exe, funktioniert es (natürlich). Aber ich bin noch nicht bequem genug, um ganztägig in der PowerShell-Umgebung zu leben. Ich möchte nicht tippen powershell.exe -command xuxu.ps1 p1 p2 p3 p4. Ich möchte tippen xuxu p1 p2 p3 p4.

Ist das möglich und wenn ja, wie?

Das Beispiel, das ich nicht zur Arbeit bringen kann, ist trivial, foo.ps1:

Write-Host "Num Args:" $args.Length;
foreach ($arg in $args) {
    Write-Host "Arg: $arg";
}

Die Ergebnisse sind immer so:

C:\temp> foo
Num Args: 0
C:\temp> foo a b c d
Num Args: 0
c:\temp>
Daniel 'Dang' Griffith
quelle

Antworten:

34

Dieser Artikel hilft. Insbesondere dieser Abschnitt:

-Datei

Führt das angegebene Skript im lokalen Bereich aus ("Punktquelle"), sodass die vom Skript erstellten Funktionen und Variablen in der aktuellen Sitzung verfügbar sind. Geben Sie den Skriptdateipfad und alle Parameter ein. Datei muss der letzte Parameter im Befehl sein, da alle Zeichen, die nach dem Namen des Dateiparameters eingegeben werden, als Pfad der Skriptdatei gefolgt von den Skriptparametern interpretiert werden.

dh

powershell.exe -File "C:\myfile.ps1" arg1 arg2 arg3

bedeutet, dass die Datei myfile.ps1 ausgeführt wird und arg1 arg2 & arg3 die Parameter für das PowerShell-Skript sind.

Arj
quelle
1
Dies hilft immer noch nicht bei dem, was die Operation will ("Ich möchte tippen xuxu p1 p2 p3 p4").
22.
18

OK, zunächst wird damit eine grundlegende Sicherheitsfunktion in PowerShell verletzt. Mit diesem Verständnis können Sie Folgendes tun:

  1. Öffnen Sie ein Windows Explorer- Fenster
  2. Menü Extras -> Ordneroptionen -> Registerkarte Dateitypen
  3. Suchen Sie den Dateityp PS1 und klicken Sie auf die Schaltfläche Erweitert
  4. Klicken Sie auf die Schaltfläche Neu
  5. Zum Handeln setzen: Öffnen
  6. Geben Sie für die Anwendung Folgendes ein : "C: \ WINNT \ system32 \ WindowsPowerShell \ v1.0 \ Powershell.exe" "-Datei" "% 1"% *

Möglicherweise möchten Sie -NoProfiledort auch ein Argument einfügen, je nachdem, was Ihr Profil tut.

EBGreen
quelle
4
Ich denke, der Schlüssel befindet sich in Schritt 6, wo Sie die Parameter an Powershell.exe übergeben. Daniel sagt, er habe PS1-Dateien mit PowerShell verknüpft, aber das übergibt keine Argumente ohne die zusätzlichen% 1% * -Spezifikationen. Beachten Sie auch, dass der Parameter -File in V1 nicht verfügbar ist. Es ist neu in V2.
Keith Hill
Guter Fang bezüglich des Parameters -file, den ich vergessen hatte.
EBGreen
Ich muss V2 installieren, bevor ich Ihren Vorschlag ausprobieren kann. Vielen Dank. Was bedeutet "das", wenn Sie sagen, dass dies eine grundlegende Sicherheitsfunktion verletzt? Ein PowerShell-Skript von Cmd.exe aus aufrufen, als wäre es eine .com / .bat / .exe-Datei? Parameter an das Skript übergeben?
Daniel 'Dang' Griffith
1
Entschuldigung, ich hätte klarer sein sollen. Das Aufrufen des Skripts ohne expliziten Aufruf von Powershell.exe. Ich sage nicht, dass es ein wichtiges Sicherheitsmerkmal für Sie persönlich ist, und es ist Sicherheit durch Dunkelheit, von der ich sowieso nicht immer ein Fan bin.
EBGreen
6
Um den Kommentar von EBGreen zu ergänzen, besteht das grundlegende Sicherheitsproblem, das PowerShell zu vermeiden versucht, darin, dass Benutzer auf PS1-Dateien doppelklicken, die an E-Mails angehängt sind, und das Skript ausführen. Aus diesem Grund werden PS1-Dateien standardmäßig nur einem Editor zugeordnet. Microsoft möchte wirklich keine PowerShell-Version des ILoveYou-Virus, z. B. "LOVE-LETTER-FOR-YOU.TXT.ps1"
Keith Hill,
18

Nachdem ich die PowerShell-Dokumentation durchgesehen hatte, entdeckte ich einige nützliche Informationen zu diesem Problem. Sie können das nicht verwenden, $argswenn Sie das param(...)am Anfang Ihrer Datei verwendet haben. stattdessen müssen Sie verwenden $PSBoundParameters. Ich habe Ihren Code in ein PowerShell-Skript kopiert / eingefügt und es hat wie erwartet in PowerShell Version 2 funktioniert (ich bin nicht sicher, auf welcher Version Sie waren, als Sie auf dieses Problem gestoßen sind).

Wenn Sie verwenden $PSBoundParameters(und dies funktioniert NUR, wenn Sie es param(...)am Anfang Ihres Skripts verwenden), handelt es sich nicht um ein Array, sondern um eine Hash-Tabelle. Sie müssen also mit dem Schlüssel / Wert-Paar darauf verweisen.

param($p1, $p2, $p3, $p4)
$Script:args=""
write-host "Num Args: " $PSBoundParameters.Keys.Count
foreach ($key in $PSBoundParameters.keys) {
    $Script:args+= "`$$key=" + $PSBoundParameters["$key"] + "  "
}
write-host $Script:args

Und wenn mit ...

PS> ./foo.ps1 a b c d

Das Ergebnis ist...

Num Args:  4
$p1=a  $p2=b  $p3=c  $p4=d
Randall Borck
quelle
Dies erklärt nicht, dass OP seine Befehlszeile mit Powershell.exe oder pwsh startet. Das Verhalten ändert sich, wenn OP dies tut.
Eric Hansen
1
@EricHansen Ich weiß nicht, was du meinst, ich erhalte das gleiche Ergebnis wie folgt: `Powershell> Powershell.exe. \ ParamTest.ps1 val1 val2 val3 val4 Num Args: 4 $ p1 = val1 $ p2 = val2 $ p3 = val3 $ p4 = val4 `
Randall Borck
@ RandallBrock Das Verhalten der Argumente ändert sich für mich. Wenn ich in CMD / Batch bin und so etwas mache, mag pwsh .\ParamTest.ps1 -arg1 val1 -listOfArgs val2 val3 val4es das wirklich nicht. Wenn ich dagegen in PowerShell bin und dies tue .\ParamTest.ps1 -arg1 val1 -listOfArgs val2 val3 val4, funktioniert das wie erwartet. Ich habe gehört, dass dies aus "Sicherheitsgründen" so funktionieren soll.
Eric Hansen
@ EricHansen Ich frage mich, ob es eine Versionssache ist. Für mich startet pwsh 6.2.0, aber Powershell.exe startet 5.1.17134.858, die beide die gleichen Ergebnisse Powershell>pwsh .\ParamTest.ps1 val1 val2 val3 val4liefern: Ausbeuten:Num Args: 4 $p1=val1 $p2=val2 $p3=val3 $p4=val4
Randall Borck
1
@ Timo Ich weiß nicht genau, was Sie tun, aber es paramist ein Sprachkonstrukt, aber es muss das erste sein, was in der Datei enthalten ist. Haben Sie zuvor eine Variable oder etwas anderes deklariert? Weitere Informationen hier: docs.microsoft.com/en-us/powershell/module/…
Randall Borck
11

Sie können Ihre Parameter in der Datei wie deklarieren:

[string]$para1
[string]$param2

Rufen Sie dann die PowerShell-Datei wie folgt auf .\temp.ps1 para1 para2....para10usw.

VB
quelle
Wie funktioniert es? Ist im Skript $para1ein reserviertes Wort?
Timo
6

Vielleicht können Sie den PowerShell-Aufruf in eine .batDatei wie folgt einschließen :

rem ps.bat
@echo off
powershell.exe -command "%*"

Wenn Sie diese Datei dann unter einem Ordner in Ihrem Ordner ablegen PATH, können Sie PowerShell-Skripts wie folgt aufrufen:

ps foo 1 2 3

Das Zitieren kann jedoch etwas chaotisch werden:

ps write-host """hello from cmd!""" -foregroundcolor green
guillermooo
quelle
+1 für die dreifachen Anführungszeichen. das hatte mich für eine Weile festgefahren.
DeanOC
1

Möglicherweise erhalten Sie nicht "xuxu p1 p2 p3 p4", wie es scheint. Aber wenn Sie in PowerShell sind und festlegen

PS > set-executionpolicy Unrestricted -scope currentuser

Sie können diese Skripte folgendermaßen ausführen:

./xuxu p1 p2 p3 p4

oder

.\xuxu p1 p2 p3 p4

oder

./xuxu.ps1 p1 p2 p3 p4

Ich hoffe, das macht Sie ein bisschen komfortabler mit PowerShell.

Atiq Rahman
quelle
0

Wenn Sie ps1-Skripte von cmd aus aufrufen und Argumente übergeben möchten, ohne das Skript wie aufzurufen

powershell.exe script.ps1 -c test
script -c test ( wont work )

Sie können Folgendes tun

setx PATHEXT "%PATHEXT%;.PS1;" /m
assoc .ps1=Microsoft.PowerShellScript.1
ftype Microsoft.PowerShellScript.1=powershell.exe "%1" %*

Dies setzt voraus, dass sich Powershell.exe auf Ihrem Weg befindet

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/ftype

ta32
quelle
Beachten Sie, dass hierfür die Eingabeaufforderung cmd als Administrator ausgeführt werden muss. Außerdem habe ich Probleme, es unter Windows 10, Version 1903 (18362.778), tatsächlich zum Laufen zu bringen. Alle Befehle werden erfolgreich ausgeführt, aber die Argumente werden immer noch nicht übergeben. Ich denke, das Umschließen mit einer .bat-Datei ist die portabelste Lösung.
David Airapetyan