michi.wtr
Goto Top

PowerShell Fenster bei Ausführung unterdrücken

Hallo zusammen,

ich habe mir mal ein kurzes Skript in PowerShell geschrieben, um Dateien ein wenig zu bearbeiten. Was genau das Skript macht ist eigentlich nicht wichtig...
Um das Ausführen des Skripts benutzerfreundlicher zu machen, habe ich im regedit zum Kontextmenü für Dateien einen Button hinzugefügt, der wenn ich diesen klicke das Skript mit 2 Argumenten ausführt. Dazu habe ich unter dem command-Schlüssel in der Zeichenfolge (Standard) folgenden Wert festgelegt:

"[Pfad der powershell.exe Datei]" -File "[Pfad des Skripts]" "[Argument1]" "[Argument2]"

Es funktioniert auch alles wunderbar, jedoch kommt jedes mal wenn ich auf den Kontextmenü Button klicke ein nerviges blaues Fenster. Ich denke das hängt mit dem Start von PowerShell zusammen, man sieht auch kurz die Befehle des Skripts durchflitzen, was jetzt nicht stört, da das Skript sowieso fast ein Einzeiler ist, das Fenster im gesamten nervt jedoch schon face-smile.

Interessant ist, wenn ich denselben Befehl (Wert des command-Schlüssels) in die CMD eingebe, dann wird das Skript ausgeführt ohne dieses Fenster (ich denke weil die CMD ja dann das PowerShell Fenster ist, da wenn man PowerShell über die CMD startet öffnet sich auch kein extra Fenster, sondern PS läuft dann über die CMD).
Ich habe schon bei meinen Suchen im Netz ein paar Beiträge gefunden, bei einem davon war die Lösung das Skript einfach via Batch-Datei auszuführen, was ich jedoch nicht sehr elegant finde.... Auch folgenden Befehl einfach ans Anfang des Skripts zu kopieren hilft nicht, da er das PowerShell-Fenster schließt wenn man es mit diesem ausführt, jedoch wird mir beim ausführen des Skripts über das Kontextmenü trotzdem das Fenster angezeigt, da ich ja PowerShell auch dafür erstmal starten muss:

$window = Add-Type -memberDefinition @"
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
"@ -name "Win32ShowWindowAsync" -namespace Win32Functions -passThru

$window::ShowWindow((Get-Process –id $pid).MainWindowHandle, 0)


Kann ich meinem Wert für den command-Schlüssel noch irgendwie Argumente mitgeben um diesen PowerShell-Start unsichtbar zu machen? Habe es schon probiert mit:

"[Pfad der powershell.exe Datei]" -WindowsStyle Hidden -File "[Pfad des Skripts]" "[Argument1]" "[Argument2]"
"[Pfad der powershell.exe Datei]" -ExecutionPolicy Bypass -File "[Pfad des Skripts]" "[Argument1]" "[Argument2]"

da ich diese Befehle auch gelesen hatte. Auch dies war aber leider Erfolglos....


Vielen lieben Dank schonmal im Voraus,
Micha

Content-Key: 3626552062

Url: https://administrator.de/contentid/3626552062

Printed on: April 18, 2024 at 18:04 o'clock

Mitglied: 3479126418
3479126418 Aug 12, 2022 updated at 08:21:12 (UTC)
Goto Top
Zum komplett unsichtbar starten (also auch ohne kurzes Aufblitzen des CMD-Fensters) musst du z.B. ein VBS Schnippsel bemühen um das PS Skript auszuführen
CreateObject("Wscript.Shell").Run "powershell -EP Bypass -File ""D:\script.ps1""",0,false  
Und dann das VBS ausführen mit
cscript //NOLOGO "C:\Pfad\zum\vbsschnippsel.vbs" 
Als Alternative, das Skript als EXE mit Wrapper kompilieren.
-WindowsStyle Hidden
Das verhindert zwar das das Fenster später unsichtbar ist, aber das kurze Aufblitzen der CMD verhindert es trotzdem nicht.
Member: michi.wtr
michi.wtr Aug 12, 2022 at 09:22:47 (UTC)
Goto Top
Das hört sich schonmal gut an, kenne mich mit VBS nur leider gar nicht aus und wollte es wie gesagt vermeiden, da ich das ein wenig unsexy finde ^^. Hab grade auch mal geschaut nach ein paar Konvertern ps1 to exe aber würde das mit VBS trotzdem mal vorerst probieren. Bei deiner Zeile sind 0 und false die übergebenen Parameter, oder sind das tatsächlich auch notwendige Befehle um kein Fenster anzuzeigen (ist ja bei beidem nicht ganz abwegig :D)

Vielen Lieben Dank
Mitglied: 3479126418
3479126418 Aug 12, 2022 updated at 09:29:16 (UTC)
Goto Top
Zitat von @michi.wtr:
Das hört sich schonmal gut an, kenne mich mit VBS nur leider gar nicht aus und wollte es wie gesagt vermeiden, da ich das ein wenig unsexy finde ^^.
Geht aber leider nicht anders. Der "powershell" Befehl ist nunmal ein CMD-Befehl und triggert zwangsweise kurz die CMD wenn man sie nicht vorher durch andere Maßnahmen ausblendet. Das gleiche kann auch ein kleines c# Programm erledigen das per "Process"-Object den ganzen Prozess auf unsichtbar schaltet. Mit was du das programmierst ist eigentlich egal VBS ist nur ein Beispiel.
Bei deiner Zeile sind 0 und false die übergebenen Parameter, oder sind das tatsächlich auch notwendige Befehle um kein Fenster anzuzeigen (ist ja bei beidem nicht ganz abwegig :D)
die 0 ist für das Ausblenden des Fensters verantwortlich und das false, bedeutet warte nicht auf Beendigung des Skriptes, hier steht das auch alles
https://ss64.com/vb/run.html
Member: michi.wtr
michi.wtr Aug 12, 2022 at 10:31:01 (UTC)
Goto Top
Geht aber leider nicht anders. Der "powershell" Befehl ist nunmal ein CMD-Befehl und triggert zwangsweise kurz die CMD wenn man sie nicht vorher durch andere Maßnahmen ausblendet. Das gleiche kann auch ein kleines c# Programm erledigen das per "Process"-Object den ganzen Prozess auf unsichtbar schaltet. Mit was du das programmierst ist eigentlich egal VBS ist nur ein Beispiel.

Ah okay, danke dir, dachte das ginge vielleicht mit irgend einem übergebenen Befehl, aber dann muss das wohl so face-smile
Hab schon bisschen rumprobiert mit dem VBS, aber müsste noch meine ps1 Datei bisschen umändern um das zu testen, die übergebenen Parameter wie Pfad der Datei übergebe ich dann nach dem String mit dem Pfad der .ps1 Datei nehme ich an?
Bzw. muss ich demnach auch das VBS mit Parametern starten, das funktioniert auf dieselbe Weise wie mit PowerShell nehme ich an? Also nach ...vbs" "[Parameter1]" ?
Mitglied: 3479126418
3479126418 Aug 12, 2022 updated at 10:37:27 (UTC)
Goto Top
Zitat von @michi.wtr:
Hab schon bisschen rumprobiert mit dem VBS, aber müsste noch meine ps1 Datei bisschen umändern um das zu testen, die übergebenen Parameter wie Pfad der Datei übergebe ich dann nach dem String mit dem Pfad der .ps1 Datei nehme ich an?
Ja.
Bzw. muss ich demnach auch das VBS mit Parametern starten, das funktioniert auf dieselbe Weise wie mit PowerShell nehme ich an? Also nach ...vbs" "[Parameter1]" ?
ja. Innerhalb der VBS kommst du mit
WScript.Arguments(0)
an die Argumente, erstes Argument = 0, zweites 1, drittes 2 usw.

bsp.
CreateObject("Wscript.Shell").Run "powershell -EP Bypass -File ""D:\script.ps1"" -Param1 " & wscript.arguments(0),0,false  

cscript //NOLOGO C:\Pfad\script.vbs "Argument1" 

Wenn Strings mit Leerzeichen als Parameter vorhanden sind dann natürlich im VBS den Parameter noch mit zusätzlichen Anführungszeichen versehen.
Member: michi.wtr
michi.wtr Aug 12, 2022 at 13:46:54 (UTC)
Goto Top
Supi, funktioniert alles, bis auf ein kleines Problem das mich gerade schon einige Stunden gekostet hat das rauszufinden

Solange sowohl Skript als auch Datei in einem Verzeichnis liegen, welches keine Leerzeichen enthält, funktioniert alles einwandfrei. Jedoch habe ich einige Ordner mit Leerzeichen, vor allem unter Users. Sobald ich nun das VBS aufrufe und ihm den Parameter "Pfad der Datei" übergebe, so funktioniert mein PS Skript nicht mehr, da nicht der vollständige Pfad übergeben wird.
Soweit kein Problem, könnte ich sagen übergebe einfach alle Parameter an das PS Skript, jedoch übergebe ich insgesamt 2 Pfade und müsste diese jetzt auseinander halten können, muss ich wirklich mit Schleife herausfinden wo Pfad 1 endet und Pfad 2 beginnt? Bzw. für weitere Parameterübergabe auch wo Pfad 2 endet und Parameter 1 bis Parameter x sich befinden? Oder kann ich dieses Übergabesystem ein wenig austricksen und den Pfad (ich denke ist doch wie bei anderen Programmiersprachen auch als String als Argument übergeben) als 1 Parameter übergeben kann?

Zum veranschaulichen:
CreateObject("Wscript.Shell").Run "powershell -EP Bypass -File " & wscript.arguments(0) & " " & wscript.arguments(0) & wscript.arguments(1),0,false

usw.

wenn jetzt aber wscript.arguments(0) (= Pfad der .ps1 Datei) ein Leerzeichen enthalten sollte, so ist der Pfad ja aufgeteilt in wscript.arguments(0) und wscript.arguments(1), weshalb somit mein letzter Parameter verloren gehen würde und nicht ans PS Skript weitergegeben wird. (Hoffe man verstehts was ich meine
)

cscript //NOLOGO "C:\Pfad vom\script.vbs" "Argument1" "Argument2"

wäre demnach:

wscript.arguments(0) = "C:\Pfad"
wscript.arguments(1) = "vom\script.vbs"
wscript.arguments(2) = "Argument1"
wscript.arguments(3) = "Argument2"

Jetzt verrutschen die Argumente 1 und 2 nach hinten und werden beim Aufruf ja nicht richtig interpretiert.

Wenn es da noch eine Möglichkeit gäbe, dann wär ich super zufrieden :D (Auch wenn ich es jetzt eigentlich nur geschafft habe dass das Fenster damit ein wenig kleiner und schwarz statt blau ist, da beim aufrufen vom VBS ein schwarzes Fenster für den Bruchteil einer Sekunde geöffnet wird, ist das normal ;) ? )

Falls du diese Frage noch beantworten könntest wäre ich vollkommen zufrieden und könnte meinen Frieden damit machen,

liebe Grüße,
Micha
Mitglied: 3479126418
3479126418 Aug 12, 2022 updated at 13:51:01 (UTC)
Goto Top
Habe ich ja oben bereits darauf hingewiesen du musst zusätzliche Anführungszeichen im VBS hinzufügen genauso wie ich es beim PS1 Pfad gemacht habe (daran denken sie zu verdoppeln da sie schon innerhlab von Anführungszeichen stehen).
Mitglied: 3479126418
Solution 3479126418 Aug 12, 2022 updated at 14:06:46 (UTC)
Goto Top
VBS (Zum Testen sichtbar geschaltet mit 1 statt 0 und zusätzlich -NoExit damit die PS Konsole offen bleibt)
CreateObject("wscript.shell").Run "powershell -EP Bypass -NoExit -File ""c:\temp pfad\test.ps1"" -param1 """ & wscript.arguments(0) & """ -param2 """ & wscript.arguments(1) & """",1,false  

PS
param(
    [string]$param1,
    [string]$param2
)
write-host "Param1: $param1"  
write-host "Param2: $param2"  

Aufruf
cscript //NOLOGO "C:\temp pfad\test.vbs" "Text für Parameter 1" "Text für Parameter 2" 

Ergebnis wie erwartet:

screenshot
Member: michi.wtr
michi.wtr Aug 29, 2022, updated at Aug 30, 2022 at 06:22:05 (UTC)
Goto Top

Ergebnis wie erwartet:

screenshot

Also keine Ahnung was bei mir nicht stimmt, aber wenn ich schreibe:
CreateObject("Wscript.Shell").Run "powershell -EP Bypass -NoExit -File ""C:\T1\test.ps1"" -param1 """ & Wscript.arguments(1) & """ -param2 """ & Wscript.arguments(2) & """", 0, false  

PS:
Set-Content -Value ("Arg1:`t" + $args + "`r`nArg2:`t" + $args[1]) -Path "C:\T1\arguments.txt"  

Aufruf:
cscript //NOLOGO "C:\T1\test.vbs" "Text für Parameter 1" "Text für Parameter 2" 

Dann erhalte ich Ergebnis eher unerwartet:
screenshot 2022-08-29 133619

Hab ich das schon richtig verstanden dass ich -param1 und -param2 tatsächlich so schreiben soll?
Member: michi.wtr
michi.wtr Aug 30, 2022 at 06:28:12 (UTC)
Goto Top
Hat sich glaube ich erledigt, durch Entfernen von -param1 und -param2 aber Beibehalten der Anführungszeichen funktioniert nun alles wie gewünscht:

CreateObject("Wscript.Shell").Run "powershell -EP Bypass -NoExit -File ""C:\T1\test.ps1"" """ & Wscript.arguments(1) & """ """ & Wscript.arguments(2) & """", 0, false  

nicht wundern warum ich nicht bei Wscript.arguments(0) anfange, denn ich übergebe zusätzlich den Pfad des PS-Scripts das ausgeführt werden soll, da alle PS-Skripte 2 Argumente benötigen die ich damit starten möchte face-smile