Comment exécuter un script PowerShell sans afficher de fenêtre?

127

Comment est-il possible d'exécuter un script PowerShell sans afficher une fenêtre ou tout autre signe à l'utilisateur?

En d'autres termes, le script doit s'exécuter silencieusement en arrière-plan sans aucun signe à l'utilisateur.

Crédit supplémentaire pour une réponse qui n'utilise pas de composants tiers :)

Thomas Bratt
la source
Consultez cette question si vous êtes intéressé par l'apprentissage: stackoverflow.com/questions/573623/powershell-vs-unix-shells
Thomas Bratt
Cette solution fonctionne également pour le planificateur de tâches: stackoverflow.com/a/51007810/571591
Hilydrow

Réponses:

128

Vous pouvez soit l'exécuter comme ceci (mais cela montre une fenêtre pendant un moment):

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

Ou vous utilisez un fichier d'aide que j'ai créé pour éviter la fenêtre appelée PsRun.exe qui fait exactement cela. Vous pouvez télécharger des fichiers source et exe. Exécutez des tâches planifiées avec l'interface graphique WinForm dans PowerShell . Je l'utilise pour les tâches planifiées.

Modifié: comme Marco l'a noté, ce paramètre -windowstyle n'est disponible que pour V2.

stej
la source
6
J'ai compilé le PsRun, cependant, si je l'ajoute à la tâche planifiée, il fait également clignoter une fenêtre ...
Ciantic
2
Même chose ici, ne fonctionne pas non plus car la fenêtre apparaît toujours pour exécuter le script. Il sort rapidement mais nous essayons de l'exécuter en arrière-plan sans interruption.
Nathan McKaskle
1
Oui, c'est pourquoi il y a "mais cela montre une fenêtre pendant un certain temps" dans la réponse.
stej
21
@ThomasBratt Pour les tâches planifiées, j'ai trouvé que les scripts PowerShell s'exécutent en silence sans -WindowStyle Hiddensi la tâche est définie Run whether user is logged on or notsur l'onglet Général sous la section "Options de sécurité".
adam
1
L'utilisation du compte utilisateur dans SYSTEM évite également l'affichage d'une fenêtre.
Jon Eldridge
27

J'avais ce même problème. J'ai découvert que si vous allez à la tâche dans le planificateur de tâches qui exécute le script powershell.exe , vous pouvez cliquer sur " Exécuter si l'utilisateur est connecté ou non " et cela n'affichera jamais la fenêtre PowerShell lorsque la tâche s'exécute.

Yusha
la source
3
Meilleure solution sans dépendre d'une extension, d'un exécutable ou d'un script d'encapsulation tiers.
inverser
1
Notez que cette option nécessite que l'utilisateur dispose du privilège "Ouvrir une session en tant que
tâche
Cette solution empêche mon script de fonctionner correctement .
Martin Argerami le
18

Vous pouvez utiliser les extensions de communauté PowerShell et procédez comme suit:

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

Vous pouvez également le faire avec VBScript: http://blog.sapien.com/index.php/2006/12/26/more-fun-with-scheduled-powershell/

(Via ce fil de discussion .)

hache.
la source
Existe-t-il un paclage NuGet pour cela afin que je puisse l'exécuter à partir de Visual Studio?
Piotr Kula
13

Voici une approche qui ne nécessite pas d'arguments de ligne de commande ou un lanceur séparé. Ce n'est pas complètement invisible car une fenêtre s'affiche momentanément au démarrage. Mais il disparaît ensuite rapidement. Là où ça va, c'est, je pense, l'approche la plus simple si vous souhaitez lancer votre script en double-cliquant dans l'explorateur, ou via un raccourci du menu Démarrer (y compris, bien sûr, le sous-menu Démarrage). Et j'aime que cela fasse partie du code du script lui-même, pas quelque chose d'extérieur.

Mettez ceci au début de votre script:

$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
la source
10

Voici 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")

Bien qu'il soit possible que cela clignote une fenêtre très brièvement, cela devrait être un événement rare.

Adam Taylor
la source
Dans la plupart des cas, l'exécution de Powershell.exe dans le contexte des utilisateurs connectés affichera une fenêtre complète ou clignotera brièvement si vous utilisez -windowstyle hidden. Pour supprimer totalement la fenêtre, vous pouvez faire l'une des deux choses suivantes: 1: Exécuter dans un contexte d'utilisateur différent tel que le compte administrateur (n'affichera aucune fenêtre pour l'utilisateur connecté). Ou 2: Utilisez un vbscript avec objshell.run avec un indicateur de fenêtre masqué pour lancer cmd.exe / c powershel.exe -fichier c: \ script.ps1. Lorsque PowerShell est appelé depuis cmd, il s'exécute dans la fenêtre cmd existante qui est déjà masquée par wscript.exe // b / nologo c: \ launcher.vbs.
Iconiu
wow, soudainement. Je n'ai même pas remarqué votre réponse au début. J'ai répondu avec un script très similaire. C'est agréable de voir une personne bien informée qui donne une vraie réponse.
Gosha
Cela devrait être la réponse acceptée, c'est la seule méthode qui semble fonctionner dans toutes les situations (y compris à l'intérieur du planificateur de tâches, ce qui était mon problème).
Martin Argerami le
6

J'avais ce problème lors de l'exécution à partir de c #, sous Windows 7, le service "Interactive Services Detection" apparaissait lors de l'exécution d'une fenêtre PowerShell cachée en tant que compte SYSTEM.

L'utilisation du paramètre "CreateNoWindow" a empêché le service ISD d'afficher son avertissement.

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

Je pense que le meilleur moyen de masquer l'écran de la console du PowerShell lorsque vous exécutez un script d'arrière-plan est ce code ( réponse " Bluecakes ").

J'ajoute ce code au début de tous mes scripts PowerShell dont j'ai besoin pour exécuter en arrière-plan.

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

Si cette réponse vous a aidé, veuillez voter pour "Bluecakes" dans sa réponse dans ce post.

Gavraham
la source
Pour moi, la console affiche encore pendant environ une seconde.
thdoan
3

ps1 caché du planificateur de tâches et du raccourci aussi

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

J'ai créé un petit outil passant l'appel à n'importe quel outil de console que vous souhaitez démarrer sans fenêtre jusqu'au fichier d'origine:

https://github.com/Vittel/RunHiddenConsole

Après la compilation, renommez simplement l'exécutable en «<targetExecutableName> w.exe» (ajoutez un «w») et placez-le à côté de l'exécutable d'origine. Vous pouvez ensuite appeler eG powershellw.exe avec les paramètres habituels et cela ne fera pas apparaître de fenêtre.

Si quelqu'un a une idée de la façon de vérifier si le processus créé attend une entrée, je serai ravi d'inclure votre solution :)

Chris
la source
1
C'est la meilleure réponse si vous souhaitez exécuter des scripts PowerShell en utilisant MessageBoxsans aucun flash de la fenêtre au démarrage (nécessitant un EXE compilé en tant que Winexe, pas une application console, et nécessitant que le Planificateur de tâches soit défini sur "Exécuter uniquement lorsque l'utilisateur est connecté on "donc les dialogues s'affichent dans la session de bureau en cours.) Merci d'avoir implémenté cela, powershellw.exe est sur ma liste de souhaits depuis des années!
Carl Walsh
PS: j'ai inclus la solution pour "attendre l'entrée" il y a quelque temps (ainsi que quelques corrections de bugs)!
Chris
@CarlWalsh Je suppose que vous voulez dire que ce n'est pas une application console, mais plutôt une application Win Forms, ce qui est correct. juste il n'inclut aucune fenêtre. mais le type de projet doit être défini dans le fichier csproj et vous ne devriez pas avoir besoin de définir un type de sortie spécifique après l'avoir ouvert avec visual studio
Chris
2

Voici une solution de travail dans Windows 10 qui n'inclut aucun composant tiers. Cela fonctionne en encapsulant le script PowerShell dans VBScript.

Étape 1: nous devons modifier certaines fonctionnalités de Windows pour permettre à VBScript d'exécuter PowerShell et d'ouvrir les fichiers .ps1 avec PowerShell par défaut.

-go pour exécuter et tapez "regedit". Cliquez sur OK, puis laissez-le s'exécuter.

- collez ce chemin "HKEY_CLASSES_ROOT \ Microsoft.PowerShellScript.1 \ Shell" et appuyez sur Entrée.

-now ouvre l'entrée sur la droite et change la valeur à 0.

-Ouvrez PowerShell en tant qu'administrateur et tapez «Set-ExecutionPolicy -ExecutionPolicy RemoteSigned», appuyez sur Entrée et confirmez la modification avec «y», puis entrez.

Étape 2: Nous pouvons maintenant commencer à encapsuler notre script.

-enregistrez votre script Powershell sous forme de fichier .ps1.

-créer un nouveau document texte et coller ce 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

-maintenant, changez le chemin du fichier vers l'emplacement de votre script .ps1 et enregistrez le document texte.

-Maintenant, faites un clic droit sur le fichier et allez renommer. Changez ensuite l'extension de nom de fichier en .vbs et appuyez sur Entrée, puis cliquez sur OK.

TERMINÉ! Si vous ouvrez maintenant le .vbs, vous ne devriez voir aucune fenêtre de console pendant que votre script s'exécute en arrière-plan.

assurez-vous de voter si cela a fonctionné pour vous!

neobihli
la source
1

Voici une démonstration amusante de contrôle des différents états de la console, y compris minimiser et masquer.

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
la source