Jak uruchomić skrypt PowerShell bez wyświetlania okna?

127

Jak można uruchomić skrypt PowerShell bez wyświetlania okna lub innego znaku użytkownikowi?

Innymi słowy, skrypt powinien działać cicho w tle, bez żadnego znaku dla użytkownika.

Dodatkowe punkty za odpowiedź, która nie korzysta z komponentów innych firm :)

Thomas Bratt
źródło
Sprawdź to pytanie, jeśli jesteś zainteresowany nauką: stackoverflow.com/questions/573623/powershell-vs-unix-shells
Thomas Bratt
To rozwiązanie działa również w Harmonogramie zadań: stackoverflow.com/a/51007810/571591
Hilydrow

Odpowiedzi:

128

Możesz uruchomić to w ten sposób (ale to pokazuje przez chwilę okna):

PowerShell.exe -windowstyle hidden { your script.. }

Lub możesz użyć pliku pomocniczego, który utworzyłem, aby uniknąć okna o nazwie PsRun.exe, które robi dokładnie to. Możesz pobrać plik źródłowy i exe Uruchom zaplanowane zadania za pomocą interfejsu graficznego WinForm w programie PowerShell . Używam go do zaplanowanych zadań.

Edytowano: jak zauważył Marco ten parametr -windowstyle jest dostępny tylko dla wersji 2.

stej
źródło
6
Skompilowałem PsRun, jednak jeśli dodam go do zaplanowanego zadania, to również miga okno ...
Ciantic
2
To samo tutaj, również nie działa, ponieważ okno nadal wyskakuje, aby uruchomić skrypt. Kończy się szybko, ale próbujemy uruchomić to w tle bez przerywania.
Nathan McKaskle
1
Tak, dlatego w odpowiedzi pojawia się „ale to pokazuje okna przez chwilę”.
stej
21
@ThomasBratt W przypadku zaplanowanych zadań zauważyłem, że skrypty PowerShell działają dyskretnie bez, -WindowStyle Hiddenjeśli zadanie jest ustawione na Run whether user is logged on or notna karcie Ogólne w sekcji „Opcje bezpieczeństwa”.
adam
1
Użycie konta użytkownika w SYSTEMIE również pozwala uniknąć wyświetlania okna.
Jon Eldridge,
27

Miałem ten sam problem. Dowiedziałem się, że jeśli przejdziesz do zadania w Harmonogramie zadań, który uruchamia skrypt powershell.exe , możesz kliknąć „ Uruchom, niezależnie od tego, czy użytkownik jest zalogowany ”, a to nigdy nie wyświetli okna PowerShell po uruchomieniu zadania.

Yusha
źródło
3
Najlepsze rozwiązanie bez konieczności korzystania z rozszerzenia, pliku wykonywalnego lub skryptu opakowującego innej firmy.
odwróć
1
Zwróć uwagę, że ta opcja wymaga, aby użytkownik miał uprawnienie „Logowanie jako zadanie wsadowe”
gb96
To rozwiązanie sprawia, że ​​mój skrypt nie działa poprawnie .
Martin Argerami
18

Możesz użyć rozszerzeń społeczności programu PowerShell i zrobić to:

start-process PowerShell.exe -arg $pwd\foo.ps1 -WindowStyle Hidden

Możesz to również zrobić za pomocą VBScript: http://blog.sapien.com/index.php/2006/12/26/more-fun-with-scheduled-powershell/

(Przez ten wątek na forum .)

topór.
źródło
Czy istnieje pakiet NuGet do tego, aby można było go uruchomić z programu Visual Studio?
Piotr Kula
13

Oto podejście, które nie wymaga argumentów wiersza poleceń ani osobnego programu uruchamiającego. Nie jest całkowicie niewidoczne, ponieważ podczas uruchamiania pojawia się okno. Ale potem szybko znika. W porządku, myślę, że jest to najłatwiejsze podejście, jeśli chcesz uruchomić skrypt, klikając dwukrotnie w eksploratorze lub za pomocą skrótu w menu Start (w tym oczywiście podmenu Startup). I podoba mi się, że jest to część kodu samego skryptu, a nie coś zewnętrznego.

Umieść to na początku swojego skryptu:

$t = '[DllImport("user32.dll")] public static extern bool ShowWindow(int handle, int state);'
add-type -name win -member $t -namespace native
[native.win]::ShowWindow(([System.Diagnostics.Process]::GetCurrentProcess() | Get-Process).MainWindowHandle, 0)
Andy Lowry
źródło
10

Oto jedna linijka:

mshta vbscript:Execute("CreateObject(""Wscript.Shell"").Run ""powershell -NoLogo -Command """"& 'C:\Example Path That Has Spaces\My Script.ps1'"""""", 0 : window.close")

Chociaż możliwe jest bardzo krótkie miganie okna, powinno to być rzadkie zjawisko.

Adam Taylor
źródło
W większości przypadków uruchomienie programu Powershell.exe w kontekście zalogowanych użytkowników spowoduje wyświetlenie pełnego okna lub krótkie flashowanie, jeśli użyjesz opcji -windowstyle hidden. Aby całkowicie usunąć okno, możesz zrobić jedną z dwóch rzeczy: 1: Uruchom w innym kontekście użytkownika, na przykład na koncie administratora (nie będzie wyświetlać żadnych okien zalogowanemu użytkownikowi). Lub 2: użyj vbscript z objshell.run z flagą ukrytego okna, aby uruchomić cmd.exe / c powershel.exe -file c: \ script.ps1. Po wywołaniu powłoki PowerShell z cmd uruchomi się ona w istniejącym oknie cmd, które jest już ukryte przez wscript.exe // b / nologo c: \ launcher.vbs.
Iconiu
wow, nagle. W pierwszej chwili nawet nie zauważyłem twojej odpowiedzi. Odpowiedziałem bardzo podobnym scenariuszem. Miło jest widzieć kompetentną osobę, która udziela prawdziwej odpowiedzi.
Gosha,
To powinna być akceptowana odpowiedź, jest to jedyna metoda, która wydaje się działać w każdej sytuacji (w tym w harmonogramie zadań, co było moim problemem).
Martin Argerami
6

Miałem ten problem podczas uruchamiania z C #, w systemie Windows 7, usługa „Wykrywanie usług interaktywnych” pojawiała się podczas uruchamiania ukrytego okna programu PowerShell jako konta SYSTEM.

Użycie parametru „CreateNoWindow” zapobiegło wyświetlaniu ostrzeżenia przez usługę ISD.

process.StartInfo = new ProcessStartInfo("powershell.exe",
    String.Format(@" -NoProfile -ExecutionPolicy unrestricted -encodedCommand ""{0}""",encodedCommand))
{
   WorkingDirectory = executablePath,
   UseShellExecute = false,
   CreateNoWindow = true
};
jmc
źródło
5

Myślę, że najlepszym sposobem na ukrycie ekranu konsoli PowerShell podczas uruchamiania skryptów w tle jest ten kod (odpowiedź „ Bluecakes ”).

Dodaję ten kod na początku wszystkich moich skryptów PowerShell, które muszę uruchomić w tle.

# .Net methods for hiding/showing the console in the background
Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();

[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
function Hide-Console
{
    $consolePtr = [Console.Window]::GetConsoleWindow()
    #0 hide
    [Console.Window]::ShowWindow($consolePtr, 0)
}
Hide-Console

Jeśli ta odpowiedź Ci pomogła, zagłosuj na „Bluecakes” w jego odpowiedzi w tym poście.

gavraham
źródło
U mnie konsola nadal wyświetla się przez około sekundę.
thdoan
3

ps1 ukryty w Harmonogramie zadań i skrócie

    mshta vbscript:Execute("CreateObject(""WScript.Shell"").Run ""powershell -ExecutionPolicy Bypass & 'C:\PATH\NAME.ps1'"", 0:close")
Gosha
źródło
2

Utworzyłem małe narzędzie przekazujące wywołanie do dowolnego narzędzia konsoli, które chcesz uruchomić bez okien, do oryginalnego pliku:

https://github.com/Vittel/RunHiddenConsole

Po skompilowaniu po prostu zmień nazwę pliku wykonywalnego na „<targetExecutableName> w.exe” (dodaj „w”) i umieść go obok oryginalnego pliku wykonywalnego. Następnie możesz wywołać eG powershellw.exe ze zwykłymi parametrami i nie pojawi się okno.

Jeśli ktoś ma pomysł, jak sprawdzić, czy stworzony proces czeka na wejście, z chęcią dołączę Twoje rozwiązanie :)

Chris
źródło
1
Jest to najlepsze rozwiązanie, jeśli chcesz uruchamiać skrypty PowerShell użyciem MessageBoxbez jakiegokolwiek błysku okna na starcie (wymagające EXE skompilowane jako Winexe, a nie aplikacji konsoli i wymagającej Task Scheduler być ustawiony na „Run tylko wtedy, gdy użytkownik jest zalogowany on ”, więc w bieżącej sesji na pulpicie pojawiają się okna dialogowe. Dziękuję za wdrożenie programu powershellw.exe od lat na mojej liście życzeń!
Carl Walsh,
PS: jakiś czas temu załączyłem rozwiązanie "czekania na wejście" (a także kilka poprawek błędów)!
Chris,
@CarlWalsh Zakładam, że masz na myśli, że nie jest to aplikacja konsolowa, ale zamiast tego aplikacja do wygrywania formularzy, co jest poprawne. po prostu nie zawiera żadnych okien. ale typ projektu powinien być zdefiniowany w pliku csproj i nie ma potrzeby ustawiania określonego typu wyjścia po otwarciu go w Visual Studio
Chris
2

Oto działające rozwiązanie w systemie Windows 10, które nie zawiera żadnych komponentów innych firm. Działa poprzez zawijanie skryptu PowerShell do VBScript.

Krok 1: musimy zmienić niektóre funkcje systemu Windows, aby umożliwić VBScript uruchamianie PowerShell i domyślnie otwierać pliki .ps1 za pomocą PowerShell.

-Idź do uruchomienia i wpisz „regedit”. Kliknij OK, a następnie pozwól mu działać.

-wklej tę ścieżkę „HKEY_CLASSES_ROOT \ Microsoft.PowerShellScript.1 \ Shell” i naciśnij enter.

- teraz otwórz wpis po prawej stronie i zmień wartość na 0.

-open PowerShell jako administrator i wpisz „Set-ExecutionPolicy -ExecutionPolicy RemoteSigned”, naciśnij enter i potwierdź zmianę za pomocą „y”, a następnie wprowadź.

Krok 2: Teraz możemy rozpocząć pakowanie naszego skryptu.

-zapisz swój skrypt Powershell jako plik .ps1.

-utwórz nowy dokument tekstowy i wklej ten skrypt.

Dim objShell,objFSO,objFile

Set objShell=CreateObject("WScript.Shell")
Set objFSO=CreateObject("Scripting.FileSystemObject")

'enter the path for your PowerShell Script
 strPath="c:\your script path\script.ps1"

'verify file exists
 If objFSO.FileExists(strPath) Then
   'return short path name
   set objFile=objFSO.GetFile(strPath)
   strCMD="powershell -nologo -command " & Chr(34) & "&{" &_
    objFile.ShortPath & "}" & Chr(34)
   'Uncomment next line for debugging
   'WScript.Echo strCMD

  'use 0 to hide window
   objShell.Run strCMD,0

Else

  'Display error message
   WScript.Echo "Failed to find " & strPath
   WScript.Quit

End If

- teraz zmień ścieżkę do pliku na lokalizację twojego skryptu .ps1 i zapisz dokument tekstowy.

-Teraz kliknij plik prawym przyciskiem myszy i przejdź do zmiany nazwy. Następnie zmień rozszerzenie nazwy pliku na .vbs i naciśnij klawisz Enter, a następnie kliknij przycisk OK.

GOTOWE! Jeśli teraz otworzysz plik .vbs, nie powinno być widać żadnego okna konsoli, gdy skrypt działa w tle.

pamiętaj, aby zagłosować za, jeśli to zadziała!

neobihli
źródło
1

Oto zabawne demo kontrolowania różnych stanów konsoli, w tym minimalizowania i ukrywania.

Add-Type -Name ConsoleUtils -Namespace WPIA -MemberDefinition @'
   [DllImport("Kernel32.dll")]
   public static extern IntPtr GetConsoleWindow();
   [DllImport("user32.dll")]
   public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'@

$ConsoleMode = @{
 HIDDEN = 0;
 NORMAL = 1;
 MINIMIZED = 2;
 MAXIMIZED = 3;
 SHOW = 5
 RESTORE = 9
 }

$hWnd = [WPIA.ConsoleUtils]::GetConsoleWindow()

$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.MAXIMIZED)
"maximized $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.NORMAL)
"normal $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.MINIMIZED)
"minimized $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.RESTORE)
"restore $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.HIDDEN)
"hidden $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.SHOW)
"show $a"
js2010
źródło