Come eseguire uno script di PowerShell senza visualizzare una finestra?


127

Come è possibile eseguire uno script PowerShell senza visualizzare una finestra o altri segni per l'utente?

In altre parole, lo script dovrebbe essere eseguito silenziosamente in background senza alcun segno per l'utente.

Credito extra per una risposta che non utilizza componenti di terze parti :)


Dai un'occhiata a questa domanda se sei interessato all'apprendimento: stackoverflow.com/questions/573623/powershell-vs-unix-shells
Thomas Bratt,

Questa soluzione funziona per Task Scheduler così: stackoverflow.com/a/51007810/571591
Hilydrow

Risposte:


128

Puoi eseguirlo in questo modo (ma questo mostra Windows per un po '):

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

Oppure usi un file di supporto che ho creato per evitare la finestra chiamata PsRun.exe che fa esattamente questo. È possibile scaricare il file sorgente ed exe Esegui attività pianificate con la GUI di WinForm in PowerShell . Lo uso per attività pianificate.

Modificato: come notato da Marco questo parametro -windowstyle è disponibile solo per V2.


6
Ho compilato lo PsRun, tuttavia, se lo aggiungo all'attività pianificata, lampeggia anche una finestra ...
Ciantic,

2
Lo stesso qui, inoltre, non funziona perché la finestra si apre ancora per eseguire lo script. Esce rapidamente ma stiamo provando a eseguirlo in background senza interruzioni.
Nathan McKaskle,

1
Sì, ecco perché c'è "ma questo mostra una finestra per un po '" nella risposta.
stej,

21
@ThomasBratt Per le attività pianificate, ho scoperto che gli script di PowerShell vengono eseguiti in modo silenzioso senza -WindowStyle Hiddenche l'attività sia impostata Run whether user is logged on or notnella scheda Generale nella sezione "Opzioni di sicurezza".
Adamo,

1
L'uso dell'account utente su SYSTEM evita anche che venga visualizzata una finestra.
Jon Eldridge il

27

Stavo avendo lo stesso problema. Ho scoperto se si va alla Task in Utilità di pianificazione che esegue il powershell.exe script, è possibile fare clic su " Esegui se l'utente è connesso o no ", e che non potrà mai visualizzare la finestra di PowerShell quando viene eseguita l'operazione.


3
La migliore soluzione senza dipendere da uno script di estensione, eseguibile o wrapper di terze parti.
inverti il

1
Questa opzione richiede che l'utente abbia il privilegio "Accedi come processo batch"
gb96

Questa soluzione impedisce al mio script di funzionare correttamente .
Martin Argerami,

18

È possibile utilizzare le estensioni della community di PowerShell e procedere come segue:

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

Puoi farlo anche con VBScript: http://blog.sapien.com/index.php/2006/12/26/more-fun-with-scheduled-powershell/

(Tramite questo thread del forum .)


Esiste un paclage NuGet per questo in modo che io possa eseguirlo da Visual Studio?
Piotr Kula,

13

Ecco un approccio che non richiede argomenti della riga di comando o un launcher separato. Non è completamente invisibile perché una finestra viene mostrata momentaneamente all'avvio. Ma poi svanisce rapidamente. Dove va bene, questo è, a mio avviso, l'approccio più semplice se si desidera avviare lo script facendo doppio clic in Esplora risorse o tramite un collegamento del menu Start (incluso, ovviamente, il sottomenu Startup). E mi piace che sia parte del codice dello script stesso, non qualcosa di esterno.

Metti questo in primo piano nella tua sceneggiatura:

$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)

10

Ecco un one-liner:

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

Sebbene sia possibile per questo far lampeggiare una finestra molto brevemente, ciò dovrebbe essere un evento raro.


Nella maggior parte dei casi, l'esecuzione di Powershell.exe nel contesto degli utenti connessi mostrerà una finestra intera o lampeggerà brevemente se si utilizza -windowstyle nascosto. Per rimuovere completamente la finestra è possibile eseguire una delle due operazioni seguenti: 1: Esegui in un contesto di un utente diverso, ad esempio un account amministratore (non visualizzerà alcuna finestra per l'utente connesso). Oppure 2: utilizzare un vbscript con objshell.run con un flag di finestra nascosta per avviare cmd.exe / c powershel.exe -file c: \ script.ps1. Quando PowerShell viene chiamato da cmd, verrà eseguito nella finestra cmd esistente che è già nascosta da wscript.exe // b / nologo c: \ launcher.vbs.
Iconiu,

wow, all'improvviso. All'inizio non ho nemmeno notato la tua risposta. Ho risposto con una sceneggiatura molto simile. È bello vedere una persona esperta che dia una risposta reale.
Gosha,

Questa dovrebbe essere la risposta accettata, è l'unico metodo che sembra funzionare in ogni situazione (incluso all'interno dell'utilità di pianificazione, che era il mio problema).
Martin Argerami,

6

Stavo riscontrando questo problema durante l'esecuzione da c #, su Windows 7, il servizio "Rilevamento di servizi interattivi" si presentava durante l'esecuzione di una finestra nascosta PowerShell come account SYSTEM.

L'uso del parametro "CreateNoWindow" ha impedito al servizio ISD di visualizzare il relativo avviso.

process.StartInfo = new ProcessStartInfo("powershell.exe",
    String.Format(@" -NoProfile -ExecutionPolicy unrestricted -encodedCommand ""{0}""",encodedCommand))
{
   WorkingDirectory = executablePath,
   UseShellExecute = false,
   CreateNoWindow = true
};

5

Penso che il modo migliore per nascondere la schermata della console di PowerShell quando si eseguono script in background è questo codice ( risposta " Bluecakes ").

Aggiungo questo codice all'inizio di tutti i miei script PowerShell che devo eseguire in background.

# .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

Se questa risposta ti è stata di aiuto, vota "Bluecakes" nella sua risposta in questo post.


Per me la console viene ancora visualizzata per circa un secondo.
thdoan

3

ps1 nascosta dall'Utilità di pianificazione e anche dal collegamento

    mshta vbscript:Execute("CreateObject(""WScript.Shell"").Run ""powershell -ExecutionPolicy Bypass & 'C:\PATH\NAME.ps1'"", 0:close")

2

Ho creato un piccolo strumento che passa la chiamata a qualsiasi strumento console che desideri avviare senza finestre fino al file originale:

https://github.com/Vittel/RunHiddenConsole

Dopo la compilazione basta rinominare l'eseguibile in "<targetExecutableName> w.exe" (aggiungere una "w") e metterlo accanto all'eseguibile originale. È quindi possibile chiamare eG powershellw.exe con i soliti parametri e non si aprirà una finestra.

Se qualcuno ha un'idea di come verificare se il processo creato è in attesa di input, sarà felice di includere la soluzione :)


1
Questa è la migliore risposta se si desidera eseguire script PowerShell utilizzando MessageBox, senza alcun lampo della finestra all'avvio (che richiede un file EXE compilato come winexe, non una console app, e che richiedono Utilità di pianificazione deve essere impostato su "Esegui solo quando l'utente è connesso on ", quindi le finestre di dialogo vengono visualizzate nella sessione desktop corrente.) Grazie per aver implementato questo, powershellw.exe è stato nella mia lista dei desideri per anni!
Carl Walsh,

PS: ho incluso la soluzione per "in attesa di input" qualche tempo fa (oltre a un paio di correzioni di bug)!
Chris,

@CarlWalsh suppongo che tu intenda che non è un'app console, ma un'app di moduli vincenti, che è corretta. non include alcuna finestra. ma il tipo di progetto dovrebbe essere definito nel file csproj e non dovresti aver bisogno di impostare un tipo di output specifico dopo averlo aperto con Visual Studio
Chris

2

Ecco una soluzione funzionante in Windows 10 che non include alcun componente di terze parti. Funziona avvolgendo lo script PowerShell in VBScript.

Passaggio 1: è necessario modificare alcune funzionalità di Windows per consentire a VBScript di eseguire PowerShell e di aprire i file .ps1 con PowerShell per impostazione predefinita.

-go per eseguire e digitare "regedit". Fare clic su OK e quindi consentire l'esecuzione.

-pasta questo percorso "HKEY_CLASSES_ROOT \ Microsoft.PowerShellScript.1 \ Shell" e premi Invio.

-apri la voce a destra e modifica il valore su 0.

-apri PowerShell come amministratore e digita "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned", premi Invio e conferma la modifica con "y", quindi inserisci.

Passaggio 2: ora possiamo iniziare a racchiudere il nostro script.

-salva il tuo script Powershell come file .ps1.

-creare un nuovo documento di testo e incollare questo script.

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

-ora cambia il percorso del file nella posizione del tuo script .ps1 e salva il documento di testo.

-Ora fai clic destro sul file e vai a rinominare. Quindi modificare l'estensione del nome file in .vbs e premere Invio, quindi fare clic su OK.

FATTO! Se ora apri il .vbs non dovresti vedere nessuna finestra della console mentre lo script è in esecuzione in background.

assicurati di votare se questo ha funzionato per te!


1

Ecco una demo divertente del controllo dei vari stati della console, inclusi minimizza e nascosta.

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"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.