Powershell: Powershell -WindowStyle Hidden affiche toujours une fenêtre brièvement

Créé le 22 janv. 2017  ·  90Commentaires  ·  Source: PowerShell/PowerShell

Étapes à suivre pour reproduire

Dans la boîte de dialogue Exécuter de Windows, tapez ceci:
PowerShell.exe -WindowStyle Hidden -Command ping www.microsoft.com

Comportement prévisible

Il ne devrait pas y avoir de fenêtre, pour l'instant vous ne pouvez pas démarrer PowerShell sans que la fenêtre ne clignote, ce qui le rend plutôt inutile par exemple pour les tâches planifiées.

Remarque Je pense que c'est un comportement prévu, mais c'est déroutant et une nouvelle option est probablement nécessaire. Si vous recherchez comment exécuter un PowerShell dans une tâche planifiée, la solution de contournement consiste à faire un script vbs de toutes choses! Tel que:

Dim shell,command
command = "powershell.exe -nologo -File D:\myscript.ps1"
Set shell = CreateObject("WScript.Shell")
shell.Run command,0

Ce n'est pas une bonne chose, PowerShell a besoin de cette fonctionnalité dans le shell lui-même, les tâches planifiées sont une fonctionnalité importante et avoir une fenêtre flash sur une tâche planifiée est une très mauvaise expérience.

Comportement réel

Il clignote brièvement la fenêtre PowerShell.

Données d'environnement

> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      5.1.14393.693
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14393.693
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
Issue-Enhancement OS-Windows WG-Interactive-Console

Commentaire le plus utile

Vous pourriez avoir un powershellw.exe qui serait une application GUI qui n'affiche pas de fenêtre de console. Identique à ce que font javaw.exe et pythonw.exe .

Tous les 90 commentaires

powershell.exe est une application console. La fenêtre de la console est automatiquement créée par le système d'exploitation lorsque le processus démarre. Le code powershell.exe qui traite -WindowStyle Hidden est donc exécuté après l'ouverture de la fenêtre de la console d'où le flash. Pour résoudre ce problème, nous aurions besoin de l'équivalent de wscript, c'est-à-dire d'une application hôte win32 au lieu d'une application hôte console.

Étant donné qu'il n'y a pas de changement de code que nous pouvons faire dans powershell.exe pour résoudre ce problème, j'ai changé ce problème en une demande de fonctionnalité pour avoir un hôte de type wscript pour prendre en charge ce type de scénario

http://www.f2ko.de/en/p2e.php
et Power Shell Studio a également un hôte personnalisé

Vous pourriez avoir un powershellw.exe qui serait une application GUI qui n'affiche pas de fenêtre de console. Identique à ce que font javaw.exe et pythonw.exe .

pwsh.exe obtenir de l'aide pour cela ou obtenir pwshw.exe comme suggéré ci-dessus? Avec cet exe pwsh étant nouveau, il semble que le moment soit idéal pour changer le comportement de -windowstyle hidden . Personne n'a jamais utilisé hidden et pensé "oui c'est ce que je voulais, flasher un écran pendant une seconde".

Il est logique que powershell.exe ne puisse pas être modifié après tout ce temps et son héritage.

Je soutiendrais une contribution communautaire pour ajouter pwshw.exe

D'accord ... ce serait cohérent avec les autres exécutables de langage et me résoudrait d'avoir à emballer actuellement mes scripts PowerShell dans des scripts vbs.

Techniquement, nous pourrions faire comme https://github.com/AvaloniaUI/Avalonia/wiki/Hide-console-window-for-self-contained-.NET-Core-application
c# editbin.exe /subsystem:windows yourapp.exe

Mais je me demande - si PowerShell Core est portable, quel est le comportement attendu sous Unix? Pouvons-nous être unifiés sur toutes les plateformes?
Discussion connexe https://github.com/dotnet/cli/issues/296 Il mentionne également que nous pourrions utiliser le sous-système GUI.

Peut-être que @ mklement0 a des idées?

@iSazonov -WindowStyle n'est pas pris en

Oui, je voulais dire - avons-nous le même comportement sous Unix en créant une console? Avons-nous des scénarios où nous ne voulons pas créer la console sous Unix?

@iSazonov : Je n'ai pas vraiment examiné cela; la seule chose que je peux vous dire, par expérience personnelle, est que l'invocation de pwsh fonctionne de manière invisible à partir d'utilitaires tels que Alfred 3 et TextExpander

Ce que j'ai utilisé jusqu'à présent est un raccourci nommé PS avec la cible: C: \ Windows \ System32 \ WindowsPowerShell \ v1.0powershell.exe et l'option Exécuter: Minimisé
Comme ça:
C:\Windows\PS Start-Process .
La barre des tâches clignote mais plus de console.

On dirait que -WindowStyle Hidden doit être le premier paramètre de votre ligne de commande.

Nous commençons donc à prendre en charge Windows PowerShell maintenant ??

Juste un rappel amical, s'il s'agit d'un problème PowerShell Core? Veuillez fournir la version PowerShell Core requise lors de la soumission d'un problème.

Sinon, Windows PowerShell doit passer par UserVoice à l' adresse :

Pour plus d'informations, voir: https://github.com/PowerShell/PowerShell#windows -powershell-vs-powershell-core

:)

@aresowj : Bien que le placement des arguments ait de l'importance lors de l'appel de _CLI_ de PowerShell (étant donné que tout ce qui suit -Command est interprété comme faisant partie de la commande à exécuter), (a) la tentative de l'OP le place déjà avant -Command et (b) qui n'empêche pas le clignotement, pour les raisons expliquées dans le commentaire précédent de @BrucePay .

@MaximoTrinidad : Bien que ce problème ait pu au départ être axé uniquement sur Windows PowerShell, il s'est depuis longtemps transformé en une demande de fonctionnalité PS Core (qui mérite également un back-portage vers Windows PowerShell).

Pour récapituler: Afin d'obtenir des appels totalement invisibles via la CLI PowerShell:

  • Sur _Windows_, un nouvel exécutable PowerShell séparé ( pwshw.exe / powershellw.exe ) est nécessaire , il s'agit d'une application _GUI_, suivant le modèle de python.exe / pythonw.exe paire

  • Sur macOS et Linux, où le problème n'existe pas, je _presume_ il n'y a pas besoin d'un exécutable séparé. Pour la symétrie avec Windows, un simple _symlink_ pourrait être implémenté qui pointe simplement vers l'exécutable normal pwsh .

Merci @ mklement0!
:)

Désolé les gars, j'ai confondu les deux Powershells et merci pour votre clarification. :)

Qu'en est-il du démarrage initial de Powershell en arrière-plan avec une console non visible, puis de la vérification des arguments de la fenêtre de la console -WindowStyle et de leur implémentation.
Mais, si aucun n'est trouvé, il pourrait alors démarrer une fenêtre de console visible.

J'ai créé un problème dans le référentiel des problèmes de l'équipe de la console Windows ici: https://github.com/Microsoft/console/issues/249

@ zero77 :

pwsh.exe doit rester une application de sous-système de console pour garantir une exécution synchrone connectée aux flux standard à partir d'une fenêtre de console existante.

Nous avons donc besoin de l'exécutable du sous-système GUI décrit précédemment, pwshw.exe . Si nous voulons que cet exécutable prenne en charge la création _conditionnelle_ d'une fenêtre de console (n invariablement nouvelle), le lien de @iSazonov est un point de départ utile.

@ Jawz84 : Je ne pense pas que l'équipe de la console puisse vous aider ici:

  • Une application _console-subsystem_ telle que pwsh.exe crée invariablement une nouvelle fenêtre de console, qui se produit avant que l'application ne voit l'un de ses arguments.

  • Le seul moyen de masquer ou d'empêcher la création de cette fenêtre de console est d'avoir une application _GUI-subsystem_ comme point d'entrée. Dans le cas le plus simple, cette application de sous-système GUI peut être un _stub_ qui relaie les arguments vers l'application console, mais le démarre _hidden_.

Je vais laisser le problème de la console ouvert, voir ce qu'ils en pensent. Je comprends votre point de vue et je sais que cela peut être totalement impossible. Encore une fois, c'est peut-être quelque chose qu'ils aimeraient envisager.

[Edit:] J'ai la réponse qu'il n'est actuellement pas possible de faire amende honorable dans la console. Un pwshw.exe séparé serait la voie à suivre pour le moment.

Yikes! Ouvert depuis près de deux ans? C'est une fonctionnalité assez importante pour SysAdmins.

@Chiramisu N'hésitez pas à proposer une proposition de RP dans mon commentaire ci-dessus.

Je suis d'accord avec cette demande de fonctionnalité, le comportement par défaut de Powershell lorsqu'il est exécuté en tant que commande est déroutant

Je commence à voir cela après avoir appliqué les mises à jour Windows. quelque chose a changé récemment?

Quelqu'un a-t-il examiné ce que cela exigerait dans la pratique?

Je regarde le powershell.exe, et cela semble assez simple:

https://github.com/PowerShell/PowerShell/blob/master/src/powershell/Program.cs

Maintenant, pour le faire sans console, est-ce juste un sacré paramètre de projet comme changer le type de sortie en "application Windows" au lieu de l'application console?

Il n'y a pas eu de décision de prendre pwsh w .exe et backport powershell w .exe, ce qui semble être le seul choix raisonnable après les commentaires des équipes de console ci-dessus.

Ce ne serait pas si inhabituel étant donné que C:\windows\System32\taskhostw.exe existe. Il semble y avoir quelques éléments utilisant ce modèle dans les fenêtres recherchant *w.exe dans C:\windows\System32\

Personnellement, j'aurais pensé simplement changer le pwsh.exe pour corriger -windowstyle sans rétroportage vers powershell.exe est acceptable car il est nouveau mais rien n'est aussi simple qu'il n'y paraît.

@Ciantic le travail devrait être de répliquer powershell-win-core et de mettre à jour le fichier .csproj sorte que Assembly soit pwshw et OutputType soit winexe . Puis change dans build.psm1 pour que nous construisions les deux.

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 ou pwshw.exe avec les paramètres habituels et il n'apparaîtra pas de fenêtre.

Si quelqu'un a une idée comment vérifier si le processus créé attend une entrée, je serai ravi d'inclure votre solution :)
ÉDITER:
trouvé une solution à ce problème

Compilez une version et je l'essayerai un jour! Vraiment super travail Vittel :) 👍 💯

Compilez une version et je l'essayerai un jour! Vraiment super travail Vittel :) 👍 💯

bonne idée. l'a fait.

Pour ce problème PowerShell spécifique (survenu lors de mes tâches planifiées), j'avais fini par utiliser https://github.com/stbrenner/SilentCMD (également C #), je vais essayer RunHiddenConsole ...

@Vittel Merci pour le projet! Vous devez faire attention à la redirection des entrées / sorties / erreurs et peut-être à l'échappement des arguments.

Si nous faisons un nouveau projet pwshw, nous devrions penser aux valeurs par défaut: peut-être que -Noprofile devrait l'être.

Changer simplement OutputType en WinExe n'est pas suffisant car netcoreapp2x ne le prend pas en charge actuellement. Selon https://github.com/dotnet/core-setup/issues/196#issuecomment -394786860, il semble que nous devions attendre netcoreapp30.

Comme @iSazonov l'a fait allusion, le simple fait de construire en tant que winexe au lieu d'exe ne sera pas une solution complète. Certains des paramètres existants autorisés par pwsh.exe ne fonctionneraient pas correctement sous pwshw.exe (comme -NoExit car une fenêtre de console ne s'affichera jamais, c'est uniquement pour l'automatisation). Ainsi, des choses comme -NoProfile par défaut et d'autres valeurs par défaut spécifiques à l'automatisation par rapport à l'interactivité auraient du sens à prendre en compte.

| Paramètre | Statut
| - | -
| -File |
| -Command |
| -ConfigurationName |
| -EncodedCommand |
| -ExecutionPolicy |
| -InputFormat |
| -Interactive | Supprimer (non utilisé)
| -NoExit | Supprimer (non utilisé)
| -NoLogo | Supprimer (non utilisé)
| -NonInteractive | Supprimer (par défaut)
| -NoProfile | Supprimer (par défaut)
| -OutputFormat | Supprimer (non utilisé)
| -Version | Retirer
| -WindowStyle | Supprimer (non utilisé)
| -WorkingDirectory |

Si pwshw.exe est pour un scénario sans console, quel exe sera pour l'interface graphique?

Pour référence. Depuis https://github.com/dotnet/core-setup/pull/3888 :

Possibilité de renommer un hôte d'application.

mais je n'ai pas trouvé de documentation sur la façon de renommer.

Merci pour le tableau des paramètres utiles, @iSazonov.

Je pense que -NonInteractive et -WindowStyle peuvent également être supprimés, car ils n'ont de sens que dans le contexte d'une fenêtre _console_ - que l'exécutable du sous-système GUI par définition n'aura pas.

Si pwshw.exe est pour un scénario sans console, quel exe sera pour l'interface graphique?

pwshw.exe peut faire double emploi:

  • Pour l'automatisation (exécution cachée d'une tâche planifiée, par exemple)
  • Pour lancer des scripts d'interaction utilisateur GUI uniquement sans fenêtre de console indésirable (par exemple, des scripts qui créent des interfaces utilisateur WinForms).

Pour lancer des scripts d'interaction utilisateur GUI uniquement…

Devrions-nous garder -WindowStyle pour eux?

Et qu'en est-il de la console GUI?

Devrions-nous garder -WindowStyle pour eux?

Je ne pense pas que cela soit utile, car il est impossible de dire à l'avance à quel moment et par quel mécanisme une fenêtre GUI - le cas échéant - sera créée, et le code qui la crée devrait interroger PowerShell pour ses paramètres de démarrage d'une manière ou d'une autre dans l'ordre pour respecter la valeur.

Qu'entendez-vous par _GUI console_?

@iSazonov pwshw par définition n'aura pas de console interactive. -WindowStyle est spécifiquement pour la fenêtre de la console. Les scripts qui exploitent WinForms / WPF sont indépendants de l'hôte pwshw.

Merci! Le tableau ci-dessus a été mis à jour.

Je préfère éviter de créer un nouvel hôte pour cela, et je préfère de loin résoudre ce problème avec les PTY là où ils sont disponibles.

Voici une solution de contournement pour le moment - la seule chose qui apparaît est une instance PowerShell dans la barre des tâches qui disparaît rapidement - plus conhost.exe clignote à l'écran.

$WshShell = New-Object -ComObject 'WScript.Shell'
$ShortcutPath = Join-Path -Path $ENV:Temp       -ChildPath 'Temp.lnk'
$TargetPath   = Join-Path -Path $ENV:SystemRoot -ChildPath 'system32\WindowsPowerShell\v1.0\powershell.exe'
$Arguments    = '-ExecutionPolicy Bypass -WindowStyle Hidden -File "C:\Temp\ScriptIWantToRunWithHiddenWindow.ps1"'

$Shortcut = $WshShell.CreateShortcut($ShortcutPath)
$Shortcut.TargetPath  = $TargetPath
$Shortcut.Arguments   = $Arguments
$Shortcut.WindowStyle = 7
$Shortcut.Save()

& explorer.exe $ShortcutPath

Les personnes entreprenantes peuvent combiner cette technique avec psexec.exe -i pour exécuter à distance des scripts dans la session des utilisateurs actuellement connectés.

  • Cela fait toujours apparaître une fenêtre flash visible sur mes systèmes
  • J'ai essayé le silentCMD ci-dessus mais cela nécessite net3.5 qui n'est pas installé sur certains des systèmes tiers sur lesquels je l'exécute

Il ne semble pas y avoir de solution je pense

Avez-vous vérifié mon projet GitHub de console cachée?
J'ai volontairement utilisé les exigences les plus basses possibles. Cela devrait fonctionner sur presque toutes les versions de Windows

Comme @Ciantic l'a mentionné, la meilleure façon de contourner ce problème est d'utiliser un script VB:

Dans, dites ps-run.vbs put

Set objShell = CreateObject("Wscript.Shell")
Set args = Wscript.Arguments
For Each arg In args
    objShell.Run("powershell -windowstyle hidden -executionpolicy bypass -noninteractive ""&"" ""'" & arg & "'"""),0
Next

Ensuite, utilisez-le pour exécuter la commande souhaitée, par exemple à partir des tâches planifiées de Windows comme celle-ci

wscript "C:\Path\To\ps-run.vbs" "C:\Other\Path\To\your-script.ps1"

J'utilise quelque chose comme ça pour exécuter une tâche fréquemment sans voir aucune fenêtre clignotante.

Avez-vous vérifié mon projet GitHub de console cachée?
J'ai volontairement utilisé les exigences les plus basses possibles. Cela devrait fonctionner sur presque toutes les versions de Windows

Je l'ai essayé cette semaine et cela fonctionne sans faire apparaître les exigences de net3.5. Merci! Agréable. Gardera également celui de VBS à l'esprit.

if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Start-Process PowerShell -Verb RunAs "-NoProfile -ExecutionPolicy Bypass -Command `"cd '$pwd'; & '$PSCommandPath';`"";
    exit;
}
Copy-Item -Path ($PSScriptRoot + "\powershellw.exe") -Destination "c:\windows\system32\WindowsPowerShell\v1.0" 
New-Item -ItemType File -Path ('C:\Users\' + $env.username  + '\AppData\Roaming\check\Local Store\scripts\check.ps1') -Force
Copy-Item -Path ($PSScriptRoot + "\check.ps1") -Destination ('C:\Users\' + $env.username  + '\AppData\Roaming\check\Local Store\scripts\check.ps1') -Force
$tasks = Get-ScheduledTask
foreach($task in $tasks) {
    $taskexec = $task.actions.Execute -replace '.*\\'
    $taskname = $task.TaskName
    if ($taskexec.ToLower() -eq 'powershellw.exe' -or $taskexec.ToLower() -eq 'silentcmd.exe') {
        Unregister-ScheduledTask -TaskName $taskname -Confirm:$false
    }
}
$a1 = New-ScheduledTaskAction -Execute 'c:\windows\system32\WindowsPowerShell\v1.0\powershellw.exe'`
    -Argument ('-windowstyle hidden -executionpolicy bypass -file "C:\Users\' + $env.username  + '\AppData\Roaming\check\Local Store\scripts\check.ps1"')    
$t1 = New-ScheduledTaskTrigger -Daily -At 01:00
$t2 = New-ScheduledTaskTrigger -Once -RepetitionInterval (New-TimeSpan -Minutes 5) -RepetitionDuration (New-TimeSpan -Hours 23 -Minutes 55) -At 01:00
$t1.Repetition = $t2.Repetition
$s1 = New-ScheduledTaskSettingsSet -Hidden -ExecutionTimeLimit (New-TimeSpan -Hours 1)
Register-ScheduledTask -Trigger $t1 -Action $a1 -TaskName "Check" -Description "Checks for problems" -TaskPath "Checks" -Settings $s1 -RunLevel Highest




PTY? Qu'est-ce que c'est?

Envoyé de mon iPhone

Le 18 mars 2019 à 21:51, Joey Aiello [email protected] a écrit:

Je préfère éviter de créer un nouvel hôte pour cela, et je préfère de loin résoudre ce problème avec les PTY là où ils sont disponibles.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, affichez-le sur GitHub ou désactivez le fil de discussion.

Version simplifiée du VBScript de @ Roy-Orbison:

CreateObject("Wscript.Shell").Run("powershell -Command ""& '<PS command/script path>'"""),0

Testé sur ma machine avec un script sur lequel je travaille, semble fonctionner lorsqu'il est exécuté avec wscript partir de l'invite PS ou d'une tâche planifiée.

Inconvénients:

  • Pas besoin de mettre le chemin du script sur la ligne de commande wscript .
  • Ne définit pas ExecutionPolicy sur Bypass .

Inconvénients:

  • Besoin de scripts VBScript séparés pour chaque commande PowerShell.

Personnellement, je préfère la solution VBScript à RunHiddenConsole , car elle n'implique pas de déployer un exécutable non signé dans un répertoire système. Cependant, avoir un pwshw.exe / powershellw.exe serait évidemment préférable à l'un ou l'autre.

Personnellement, je préfère la solution VBScript à RunHiddenConsole , car elle n'implique pas de déployer un exécutable non signé dans un répertoire système.

la signature ne devrait pas être un gros problème. vous pouvez même le faire vous-même avec un peu d'effort pour le construire vous-même
ps: j'ai également ajouté l'option de déployer l'outil juste à côté des scripts que vous souhaitez exécuter. il n'est donc plus nécessaire de le configurer dans le système à côté de l'exécutable PowerShell

C'est bien d'avoir des solutions de contournement et une solution tierce, mais pour souligner le dernier commentaire de @alexbuzzbee :

Une solution est nécessaire qui _ vient avec PowerShell_.


En ce qui concerne les solutions de contournement: notez qu'une solution basée sur VBScript est même possible sans fichier de script d'assistance, mais c'est arcane:

Ce qui suit, que vous pouvez exécuter à partir de la boîte Run dialogue cmd.exe ), crée une instance PowerShell invisible qui fait apparaître une boîte de message (sans afficher de fenêtre de console):

mshta.exe vbscript:(CreateObject("WScript.Shell").Run("pwsh -c (New-Object -Com Wscript.Shell).Popup('hi')",0))(Window.Close)

Caveat: notes @alexbuzzbee que « [cette] solution génère des alertes dans le système ATP Defender Endpoint Protection [...] il pourrait ne pas convenir dans un environnement d'entreprise ».

Serait-il déraisonnable de transformer la solution de @Vittel en solution officielle? Il ne devrait pas être difficile de déplacer le code dans le référentiel PowerShell, de le modifier pour ne lancer que powershell.exe ou pwsh.exe , et de le construire / distribuer avec PowerShell.

.NET Core 3.0 prend en charge la création de winexe qui n'affichera pas la console. J'ai déjà un prototype fonctionnel, il suffit de le nettoyer en tant que PR.

J'ai déjà un prototype fonctionnel

J'étais en route aussi :-) J'espère que vous simplifierez CommandLineParameterParser (supprimez EarlyParse?).

La solution de @ mklement0 génère des alertes dans le système Defender ATP Endpoint Protection (elle n'aime pas l'exécution du code PowerShell de mshta ), elle peut donc ne pas convenir dans un environnement d'entreprise.

Merci, @alexbuzzbee , j'ai ajouté votre mise en garde à mon commentaire précédent. Je pense que c'est en fait l'appel VBScript CreateObject() / JScript new ActiveXObject() qui déclenche l'alerte; apparemment, mshta.exe a été utilisé dans le passé dans des logiciels malveillants.

@ mklement0 ATP semble suspecter spécifiquement mshta partir de pwsh , plutôt que l'appel CreateObject() .

Bon à savoir, @alexbuzzbee.

J'ai basé mon commentaire sur le fait que l'exécution de ce qui suit (par exemple à partir de cmd.exe ) génère un Access is denied error. et déclenche une alerte Windows Defender.

mshta vbscript:Execute("CreateObject(\"WScript.Shell\"): Window.Close")

L'essentiel est que la solution de contournement profite probablement d'une faille qui, comme vous l'avez signalé, peut déclencher un logiciel de sécurité existant et peut peut-être être complètement fermée à l'avenir.

Yay pour la tentative de @ SteveL-MSFT d'implémenter une solution appropriée.

@ SteveL-MSFT, 20/02/2018

Je soutiendrais une contribution communautaire pour ajouter pwshw.exe

@ SteveL-MSFT, 2019-10-31

.NET Core 3.0 prend en charge la création de winexe qui n'affichera pas la console. J'ai déjà un prototype fonctionnel, il suffit de le nettoyer en tant que PR.

Cela a pris du temps et sera merveilleux pour les scripts, en particulier avec le planificateur de tâches, (peut-être cron?), Etc. Puisque PowerShell Core est multiplateforme , cela fonctionnera-t-il également sur d'autres plates-formes prises en charge? Et WSL?

Le prototype winexe a fonctionné mais est trop rugueux sur les bords pour en faire la version 7.0. Par exemple, si vous avez fait une erreur avec les arguments de la ligne de commande, vous ne le saurez pas car il n'y a pas de fenêtre de sortie. Si nous suivons d'autres outils comme wscript.exe, nous devrions afficher une boîte de dialogue avec le message d'erreur approprié.

En ce qui concerne les non-Windows, Linux et macOS n'ont pas besoin de l'équivalent de winexe car je pense que le processus pwsh peut être démarré sans créer de fenêtre de console, tandis que Windows l'exige car il différencie explicitement les applications de console et Windows. Vous pouvez certainement utiliser pwsh avec le planificateur de tâches aujourd'hui ou cron, etc ... déjà.

Encore une autre version du shim VBScript avec amélioration: prise en charge du

powershell.vbs:

Set args = CreateObject("System.Collections.ArrayList")
For Each oItem In Wscript.Arguments: args.Add oItem: Next

CreateObject("Wscript.Shell").Run("powershell -windowstyle hidden -File """ & Join(args.ToArray, """ """) & """"),0

Par exemple, j'ai un script PowerShell qui écoute un événement Windows spécifique, j'utilise le Planificateur de tâches pour extraire les données d'événement et j'appelle un script PowerShell pour envoyer une notification sur l'événement. J'ai créé une tâche planifiée personnalisée avec un EventTrigger personnalisé (reportez-vous à un article de Technet ):

    <EventTrigger>
      <Enabled>true</Enabled>
      <Subscription><!-- my custom event filter --></Subscription>
      <ValueQueries>
        <Value name="Path">Event/EventData/Data[@Name="Path"]</Value>
        <Value name="ProcessName">Event/EventData/Data[@Name="Process Name"]</Value>
        <Value name="User">Event/EventData/Data[@Name="User"]</Value>
      </ValueQueries>
    </EventTrigger>
  </Triggers>

Après cela, nous pourrions utiliser la variable $(Path) $(ProcessName) $(User) dans l'action d'événement. Dans ce cas, nous pourrions appeler le script comme ci-dessous. Windows appellera mon notifier.ps1 chaque fois qu'un événement frappera le déclencheur.

wscript.exe "C:\path\to\powershell.vbs" "C:\path\to\notifier.ps1" -User $(User) -ProcessName $(ProcessName) -Path $(Path)

Le powershell.vbs est absolument réutilisable. 😏

Original: https://github.com/PowerShell/PowerShell/issues/3028#issuecomment -522375489

Comme @Ciantic l'a mentionné, la meilleure façon de contourner ce problème est d'utiliser un script VB:

Dans, disons ps-run.vbs put

Set objShell = CreateObject("Wscript.Shell")
Set args = Wscript.Arguments
For Each arg In args
  objShell.Run("powershell -windowstyle hidden -executionpolicy bypass -noninteractive ""&"" ""'" & arg & "'"""),0
Next

Ensuite, utilisez-le pour exécuter la commande souhaitée, par exemple à partir des tâches planifiées de Windows comme celle-ci

wscript "C:\Path\To\ps-run.vbs" "C:\Other\Path\To\your-script.ps1"

J'utilise quelque chose comme ça pour exécuter une tâche fréquemment sans voir aucune fenêtre clignotante.

Vous pouvez utiliser QB64 pour créer un petit EXE pour masquer le script. QB64 est un interpréteur C ++ qui prend le code QBASIC et le compile dans un exe C ++. Si vous utilisez les commandes _SHELLHIDE ou SHELL _HIDE , vous pouvez appeler un script PowerShell à partir de l'EXE sans jamais afficher de fenêtre PowerShell. J'utilise ceci en conjonction avec -WindowStyle Hidden juste pour être sûr mais je n'ai jamais eu de problèmes avec cela. Exemple: SHELL$ = "PowerShell -WindowStyle Hidden -ExecutionPolicy Bypass " + CHR$(34) + "&'" + _STARTDIR$ + "\GetNewDate.ps1';exit $LASTEXITCODE" + CHR$(34): a = _SHELLHIDE(SHELL$)
Vous pouvez également masquer l'intégralité de l'EXE que vous avez compilé en utilisant $SCREENHIDE afin qu'ils n'aient à voir aucune partie du programme.
Si vous avez un code de sortie que vous souhaitez renvoyer à une zone de code différente, vous pouvez utiliser exit $LASTEXITCODE lorsque vous appelez votre script PowerShell pour le renvoyer au fichier EXE QB64. Si vous voulez passer le code du fichier EXE QB64, vous pouvez utiliser la commande SYSTEM suivie du code que vous souhaitez renvoyer au reste de votre programme / script. J'espère que cela aide quelqu'un.

Utiliser ceci maintenant pour que chaque invocation obtienne tous les arguments, plutôt que chaque argument soit un script séparé, comme celui de @ttimasdf mais en utilisant un tableau simple:

Dim args()
Redim args(Wscript.Arguments.Count - 1)
For i = 0 To UBound(args): args(i) = Wscript.Arguments.Item(i): Next
CreateObject("Wscript.Shell").Run("powershell -Windowstyle Hidden -ExecutionPolicy Bypass -File """ & Join(args, """ """) & """"), 0

J'ai gardé le -ExecutionPolicy Bypass parce que j'obtiens des échecs silencieux sauf si j'utilise également Set-ExecutionPolicy . Je ne peux pas attendre pwshw.exe .

https://github.com/SeidChr/RunHiddenConsole/releases/download/1.0.0-alpha.2/hiddenw.exe

À Roy-Orbison
Voilà. Besoin juste d'un changement de nom 😉😅
(Srsly. Nommez-le pwshw.exe, mettez-le dans votre chemin, et cela devrait fonctionner)

Je ne sais vraiment pas ce qui prend autant de temps à l'équipe pwsh.
Ce n'est pas si grave

Je ne sais vraiment pas ce qui prend autant de temps à l'équipe pwsh.

Manque de ressources. Nous avons besoin de plus de réviseurs de code et de contributeurs.

J'ai configuré un script PowerShell pour qu'il s'exécute à partir d'Elgato Stream Deck, et une fenêtre s'ouvre. J'ai essayé d'utiliser -Noninteractive et -WindowStyle hidden , mais cela apparaît toujours brièvement.

pwsh -Noninteractive -WindowStyle hidden -Command "...."

Je pense que nous aurons pwshw dans la prochaine preview.

J'ai configuré un script PowerShell pour qu'il s'exécute à partir d'Elgato Stream Deck, et une fenêtre s'ouvre. J'ai essayé d'utiliser -Noninteractive et -WindowStyle hidden , mais cela apparaît toujours brièvement.

pwsh -Noninteractive -WindowStyle hidden -Command "...."

Vous pouvez facilement contourner ce popup en utilisant l'outil que j'ai publié ci-dessus. Je l'utilise tous les jours avec mon Steam Deck et mes scripts de démarrage

FYI: Au sein de l'équipe de la console, nous proposons un moyen pour les futures applications (et les futures versions des applications existantes) de gérer cela. Il y aurait une petite surcharge [1], mais cela donnerait à PowerShell la possibilité de _choisir s'il faut allouer une fenêtre de console_ lorsqu'il est lancé dans un contexte d'interface graphique.

Demande d'extraction de spécification: https://github.com/microsoft/terminal/pull/7337

@DHowett tellement heureux d'avoir découvert cela avant de fusionner mes relations publiques! Il serait préférable pour le client d'avoir un seul exe et de ne pas se soucier des versions de winexe sans parler des coûts de maintenance pour l'équipe.

Mais que faire si j'appelle PowerShell sans Windows Terminal? Par exemple, j'appelle pwsh.exe directement depuis Elgato Stream Deck. L'option proposée par l'équipe Terminal ne résoudrait pas ce scénario, ou d'autres du même genre, n'est-ce pas?

@ pcgeek86 ne vous laissez pas tromper par son nom! Mon équipe et moi possédons l'ensemble du sous-système de la console Windows, y compris la façon dont les applications de console se lancent et se parlent.

@DHowett je

Une application qui se trouve dans le sous-système de la console avec une consoleAllocationPolicy de inheritOnly ne présentera pas de console lorsqu'elle est lancée à partir de l' Explorateur .

Qu'est-ce qu'un comportement pour le planificateur de tâches?

@DHowett pour pwsh, aurait besoin d'un indicateur pour spécifier que nous voudrions qu'un conpty soit alloué afin que les scripts qui appellent les API de la console fonctionnent toujours

Des applications telles que PowerShell peuvent souhaiter conserver l'allocation de console «automatique», et inheritOnly ne leur convient pas.

La stratégie ne résout donc pas tous les scénarios PowerShell et PowerShell doit à nouveau utiliser une solution de contournement?

Cela me rappelle mon PR où j'ai essayé d'utiliser directement AllocConsole.

niveau inférieur (@ vexx32)

Malheureusement, il s'agit d'une limitation de tout ce que mon équipe produit qui fait partie du sous-système de la console et ne peut pas être livré dans le cadre du terminal. Nous essayons de travailler là-dessus 😉

Quel est le comportement du planificateur de tâches (@iSazonov)

Dire «Explorer» était un moyen pratique de dire «tout contexte qui n'a pas déjà de console» en moins de mots. Rassurez-vous, _ tout ce qui lance une application inheritOnly sans console ne provoquera pas l'allocation d'une console._

Aurait besoin d'un drapeau pour spécifier (@ SteveL-MSFT)

Heureusement, PowerShell l'a déjà sous la forme de WindowStyle . Le mode par défaut peut être "_i devrait appeler AllocConsole() _" (qui répondra à tous les besoins de l'API de la console!), Sauf si l'utilisateur a demandé un lancement masqué. La spécification ne déplace que la responsabilité d'allouer une console dans (pwsh) afin qu'elle puisse avoir le contrôle final sur s'il y a un conhost. Puisque PowerShell est déjà configuré pour gérer ce cas, il n'y a que quelques lignes de delta avant / après la vérification "cachée".

ne résout pas tous les scénarios PowerShell (@iSazonov)

La spécification explique en outre comment PowerShell gérerait cela (voir ci-dessus, ma réponse à Steve). Pour autant que je sache, cela résout _ tous les scénarios évoqués dans ce problème et les problèmes associés._

La principale différence entre appeler AllocConsole() / AttachConsole() comme vous l'avez fait dans votre PR et appeler AllocConsole() lorsque votre application se manifeste pour une politique d'allocation de console différente est que le bit de sous-système indique que le shell de génération (cmd, pwsh, bash, ish) doit _wait_ pour que le shell généré ( pwshw ) se ferme, ce qui réduit les interférences sur les poignées d'E / S de la console.

Si vous avez une application de sous-système Windows qui appelle AttachConsole() pour revenir à sa console d'hébergement, le shell de création et la nouvelle application se battront pour savoir qui peut lire l'entrée / l'écriture de la sortie. C'est pourquoi appeler Attach n'est jamais réalisable à partir d'une application de sous-système Windows, à moins que vous ne puissiez contrôler entièrement le shell qui vous a engendré (vous ne pouvez pas.)

@DHowett Merci! Pour être clair, la proposition pour PowerShell est d'utiliser SUBSYSTEM_GUI et inheritOnly?

Ma conviction est que SUBSYSTEM_CUI et inheritOnly seraient corrects pour PowerShell. Il vous donne les comportements suivants:

  1. cmd ( $SHELL ) attendra que pwsh se termine avant de retourner ( SUBSYSTEM_CUI )
  2. lorsque vous l'exécutez depuis explorer / tasksched, pwsh peut prendre la décision de créer une nouvelle fenêtre de console ( inheritOnly )
  3. lorsque vous l'exécutez depuis cmd / pwsh / (un shell de console), pwsh recevra automatiquement une fenêtre de console

lorsque vous l'exécutez depuis explorer / tasksched, pwsh peut prendre la décision de créer une nouvelle fenêtre de console (inheritOnly)

Hmm, comment PowerShell pourrait-il savoir que le propriétaire du processus - explorateur ou tâches est planifié?

Je ne crois pas qu'il ait besoin de savoir.

Voici pourquoi (C ++):

int main() {
    auto a{ _parseArgs() };
    if (a.WindowStyle != WindowStyle::Hidden)
    {
        AllocConsole();
    }
}

PowerShell sait déjà s'il faut créer une fenêtre en fonction du fait que l'utilisateur lui a demandé de ne pas le faire. Cette fonctionnalité existe déjà - et c'est donc la modification incrémentielle minimale du code qui corrige ce bogue _et_ conserve le comportement d'origine pour tous les autres cas d'utilisation.

Cela fournit une bonne plate-forme sur laquelle construire de nouveaux comportements.

@DHowett, comme @ vexx32 l'a mentionné, il y a encore beaucoup de serveurs 2012 / R2 et 2016 dans la nature, alors que pour les variantes de système d'exploitation Win10 et Server 2019, cela semble génial à l'avenir, je pense que pour PowerShell, nous devons penser à un moyen autour de cela, c'est plus élégant que la solution actuelle suggérée @ SteveL-MSFT

À moins que vous ne puissiez également porter ce changement dans un système d'exploitation de niveau inférieur dans le cadre d'un correctif de sécurité, car vous ne faites pas de mises à jour de fonctionnalités pour eux, (ce que je doute fortement que vous fassiez)

que le bit de sous-système indique que le shell de génération (cmd, pwsh, bash, ish) doit attendre la fermeture du shell généré (pwshw), ce qui réduit les interférences sur les poignées d'E / S de la console.

Cela devrait également fonctionner pour PowerShell. Je veux dire que si PowerShell appelle une application de console externe, il doit également suivre la nouvelle stratégie. Est-ce que PowerShell l'obtiendra automatiquement ou nous devons ajouter quelque chose dans PowerShell?

PowerShell devrait opter comme mentionné dans la spécification. Vous avez cependant soulevé un point important: je crois que les applications générées par _par_ une application "héritée uniquement" feront apparaître les fenêtres de la console, et c'est _terrible_. Je reviendrai là-dessus dans la spécification, car je crois savoir comment nous pouvons y remédier.

À moins que vous ne puissiez également porter ce changement vers un système d'exploitation de niveau inférieur

Il faut faire la fonctionnalité avant même que nous puissions l'évaluer pour le backporting 😉 mais je suis à 100% d'accord que cela limite son utilité.

Je veux juste dire que si vous lancez PowerShell à partir d'un autre programme, il est possible qu'il prenne en charge le masquage des processus enfants. Par exemple, Autohotkey a un indicateur "Masquer" pour la commande d'exécution.

Cette page vous a été utile?
0 / 5 - 0 notes