Powershell: Powershell -WindowStyle Hidden todavía muestra una ventana brevemente

Creado en 22 ene. 2017  ·  90Comentarios  ·  Fuente: PowerShell/PowerShell

pasos para reproducir

En el cuadro de diálogo Ejecutar de Windows, escriba esto:
PowerShell.exe -WindowStyle Hidden -Command ping www.microsoft.com

Comportamiento esperado

No debería haber ninguna ventana, ahora mismo no puede iniciar PowerShell sin que la ventana parpadee, lo que lo hace bastante inútil, por ejemplo, para las tareas programadas.

Tenga en cuenta que creo que este es un comportamiento previsto, pero es confuso y probablemente se requiera una nueva opción. Si busca cómo ejecutar un PowerShell en una tarea programada, la solución alternativa es hacer un script vbs de todas las cosas. Como:

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

Esto no es algo bueno, powershell necesita esta función en el propio shell, las tareas programadas son una característica importante y tener una ventana que parpadea en la tarea programada es una experiencia realmente mala.

Comportamiento real

Destella la ventana de PowerShell brevemente.

Datos ambientales

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

Comentario más útil

Podría tener un powershellw.exe que sería una aplicación GUI que no muestra una ventana de consola. Lo mismo que hacen javaw.exe y pythonw.exe .

Todos 90 comentarios

powershell.exe es una aplicación de consola. El sistema operativo crea automáticamente la ventana de la consola cuando se inicia el proceso. Por lo tanto, el código powershell.exe que procesa -WindowStyle Hidden se ejecuta después de que se abre la ventana de la consola, de ahí el flash. Para solucionar esto, necesitaríamos el equivalente a wscript, es decir, una aplicación de host win32 en lugar de una aplicación de host de consola.

Dado que no hay ningún cambio de código que podamos hacer en powershell.exe para solucionar este problema, he cambiado este problema a una solicitud de función para tener un host similar a wscript para admitir este tipo de escenario

http://www.f2ko.de/en/p2e.php
y Power Shell Studio tiene un host personalizado

Podría tener un powershellw.exe que sería una aplicación GUI que no muestra una ventana de consola. Lo mismo que hacen javaw.exe y pythonw.exe .

¿Puede pwsh.exe obtener soporte para esto u obtener pwshw.exe como se sugirió anteriormente? Dado que este exe pwsh es nuevo, parece un buen momento para cambiar el comportamiento de -windowstyle hidden . Nadie ha usado nunca hidden y pensó "sí, eso es lo que quería, flashear alguna pantalla por un segundo".

Tiene sentido que powershell.exe no se pueda cambiar después de todo este tiempo y su legado.

Apoyaría una contribución comunitaria para agregar pwshw.exe

De acuerdo ... esto sería consistente con otros ejecutables de lenguaje y me solucionaría tener que envolver mis scripts de powershell en scripts vbs.

Técnicamente podríamos hacer como https://github.com/AvaloniaUI/Avalonia/wiki/Hide-console-window-for-self-contained-.NET-Core-application
c# editbin.exe /subsystem:windows yourapp.exe

Pero me pregunto: si PowerShell Core es portátil, ¿cuál es el comportamiento esperado en Unix? ¿Podemos unificarnos en todas las plataformas?
Discusión relacionada https://github.com/dotnet/cli/issues/296 También menciona que podríamos usar el subsistema GUI.

¿Quizás @ mklement0 tiene alguna idea?

@iSazonov -WindowStyle no es compatible con Windows

Sí, quise decir: ¿tenemos el mismo comportamiento en Unix al crear una consola? ¿Tenemos escenarios en los que no queremos crear la consola en Unix?

@iSazonov : Realmente no he pwsh invisible funciona bien desde utilidades como Alfred 3 y TextExpander

Lo que he estado usando hasta ahora es un acceso directo llamado PS con Target: C: \ Windows \ System32 \ WindowsPowerShell \ v1.0powershell.exe y la opción Ejecutar: Minimizado
Me gusta esto:
C:\Windows\PS Start-Process .
La barra de tareas parpadea pero no más consola.

Parece que -WindowStyle Hidden tiene que ser el primer parámetro de su línea de comando.

Entonces, ¿estamos comenzando a admitir Windows PowerShell ahora?

Solo un recordatorio amistoso, si se trata de un problema de PowerShell Core? Proporcione la versión de PowerShell Core según se requiera cuando envíe un problema.

De lo contrario, Windows PowerShell debe pasar por UserVoice en: https://windowsserver.uservoice.com/forums/301869-powershell

Para obtener más información, consulte: https://github.com/PowerShell/PowerShell#windows -powershell-vs-powershell-core

:)

@aresowj : Si bien la ubicación de los argumentos es importante cuando se llama a _CLI_ de PowerShell (dado que todo lo que sigue a -Command se interpreta como parte del comando a ejecutar), (a) el intento del OP ya lo coloca antes de -Command y (b) eso no evita el parpadeo, por las razones explicadas en el comentario anterior de @BrucePay .

@MaximoTrinidad : si bien este problema puede haber comenzado como enfocado solo en Windows PowerShell, hace mucho tiempo que se ha transformado en una solicitud de función de PS Core (que también merece la conversión a Windows PowerShell).

Para recapitular: para obtener invocaciones completamente invisibles a través de la CLI de PowerShell:

  • En _Windows_, se necesita un nuevo ejecutable de PowerShell separado ( pwshw.exe / powershellw.exe ) que sea una aplicación _GUI_, siguiendo el modelo de python.exe / pythonw.exe par

  • En macOS y Linux, donde el problema no existe, presumo que no hay necesidad de un ejecutable por separado. Para la simetría con Windows, se podría implementar un _symlink_ simple que simplemente apunte al ejecutable normal pwsh .

¡Gracias @ mklement0!
:)

Lo siento chicos, confundí los dos Powershells y gracias por tu aclaración. :)

¿Qué tal si inicialmente se inicia Powershell en segundo plano con una consola no visible, luego se verifica cualquier argumento de la ventana de la consola -WindowStyle y se implementa?
Pero, si no se encuentra ninguno, podría iniciar una ventana de consola visible.

Creé un problema en el repositorio de problemas del equipo de la consola de Windows aquí: https://github.com/Microsoft/console/issues/249

@ zero77 :

pwsh.exe debe seguir siendo una aplicación de subsistema de consola para garantizar una ejecución sincrónica y conectada a secuencias estándar desde una ventana de consola existente.

Por lo tanto, necesitamos el ejecutable del subsistema GUI _separate_ previamente discutido, pwshw.exe . Si queremos que ese ejecutable admita la creación _condicional_ de una ventana de consola (invariablemente nueva), el enlace de @iSazonov es un punto de partida útil.

@ Jawz84 : No creo que el equipo de la consola pueda ayudar aquí:

  • Una aplicación _console-subsystem_ como pwsh.exe crea invariablemente una nueva ventana de consola, lo que ocurre antes de que la aplicación vea cualquiera de sus argumentos.

  • La única forma de _ ocultar_ o _ evitar la creación_ de esta ventana de consola es tener una aplicación _GUI-subsistema_ como punto de entrada. En el caso más simple, esta aplicación del subsistema GUI puede ser un _stub_ que transmite argumentos a la aplicación de consola, pero la inicia _hidden_.

Dejaré abierto el problema de la consola, a ver qué opinan. Entiendo su punto, y sé que puede ser totalmente imposible. Una vez más, puede ser algo que les gustaría considerar.

[Editar:] Tengo la respuesta de que actualmente no es posible enmendar esto en la consola. Un pwshw.exe separado sería el camino a seguir por ahora.

¡Ay! ¿Abierto durante casi dos años? Esta es una característica bastante importante para los administradores de sistemas.

@Chiramisu No dude en ofrecer relaciones públicas - propuesta en mi comentario anterior.

Estoy de acuerdo con esta solicitud de función, el comportamiento predeterminado de Powershell cuando se ejecuta como un comando es desconcertante

Empiezo a ver esto después de aplicar las actualizaciones de Windows. algo ha cambiado recientemente?

¿Alguien ha mirado lo que esto requeriría en la práctica?

Estoy mirando el powershell.exe, y parece bastante simple:

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

Ahora, para hacerlo sin consola, ¿es solo una maldita configuración del proyecto como cambiar el tipo de salida a "aplicación de Windows" en lugar de la aplicación de consola?

No se ha tomado la decisión de hacer pwsh w .exe y backport powershell w .exe, que parece ser la única opción razonable después de los comentarios de los equipos de la

Esto no sería tan inusual dado que C:\windows\System32\taskhostw.exe existe. Parece que hay algunos elementos que usan este patrón en Windows que buscan *w.exe en C:\windows\System32\

Personalmente, habría pensado que simplemente cambiar el pwsh.exe para arreglar -windowstyle sin backporting a powershell.exe es aceptable ya que es nuevo, pero nada es tan simple como parece.

@Ciantic, el trabajo debería ser replicar powershell-win-core y actualizar el archivo .csproj para que Assembly sea pwshw y OutputType sea winexe . Luego cambia en build.psm1 para que construyamos ambos.

He creado una pequeña herramienta que pasa la llamada a cualquier herramienta de consola que desee iniciar sin ventanas hasta el archivo original:

https://github.com/Vittel/RunHiddenConsole

Después de compilar, simplemente cambie el nombre del ejecutable a "<targetExecutableName> w.exe" (agregue una "w"), y colóquelo junto al ejecutable original.
Luego puede llamar a eG powershellw.exe o pwshw.exe con los parámetros habituales y no aparecerá ninguna ventana.

Si alguien tiene una idea de cómo verificar si el proceso creado está esperando una entrada, estaré feliz de incluir su solución :)
EDITAR:
encontré una solución para ese problema

¡Compila un lanzamiento y lo intentaré alguna vez! Realmente un gran trabajo Vittel :) 👍 💯

¡Compila un lanzamiento y lo intentaré alguna vez! Realmente un gran trabajo Vittel :) 👍 💯

buena idea. también lo hizo.

Para ese problema específico de PowerShell (ocurrido en mis tareas programadas) terminé usando https://github.com/stbrenner/SilentCMD (también C #), probaré RunHiddenConsole ...

@Vittel ¡ Gracias por el proyecto! Debe prestar atención a la redirección de entrada / salida / error y quizás al escape de argumentos.

Si vamos a hacer un nuevo proyecto pwshw deberíamos pensar en los valores predeterminados: quizás -Noprofile debería serlo.

Simplemente cambiar OutputType a WinExe no es suficiente ya que netcoreapp2x no lo admite actualmente. Según https://github.com/dotnet/core-setup/issues/196#issuecomment -394786860, parece que tenemos que esperar a netcoreapp30.

Como aludió @iSazonov , simplemente construir como winexe en lugar de exe no será una solución completa. Algunos de los parámetros existentes permitidos por pwsh.exe no funcionarían correctamente bajo pwshw.exe (como -NoExit ya que nunca aparecerá una ventana de consola, es solo para automatización). Entonces, cosas como -NoProfile por defecto y otros valores predeterminados específicos de la automatización frente a la interactiva, tendría sentido considerar.

| Parámetro | Estado
| - | -
| -File |
| -Command |
| -ConfigurationName |
| -EncodedCommand |
| -ExecutionPolicy |
| -InputFormat |
| -Interactivo | Eliminar (no utilizado)
| -NoSalir | Eliminar (no utilizado)
| -NoLogo | Eliminar (no utilizado)
| -NonInteractive | Eliminar (por defecto)
| -NoProfile | Eliminar (por defecto)
| -OutputFormat | Eliminar (no utilizado)
| -Version | Eliminar
| -WindowStyle | Eliminar (no utilizado)
| -WorkingDirectory |

Si pwshw.exe es para un escenario sin consola, ¿qué exe será para GUI?

Para referencia. De https://github.com/dotnet/core-setup/pull/3888 :

Posibilidad de cambiar el nombre de un apphost.

pero no encontré documentos sobre cómo cambiar el nombre.

Gracias por la útil tabla de parámetros, @iSazonov.

Creo que -NonInteractive y -WindowStyle pueden eliminarse, ya que solo tienen significado en el contexto de una ventana _console_, que el ejecutable del subsistema GUI por definición no tendrá.

Si pwshw.exe es para un escenario sin consola, ¿qué exe será para GUI?

pwshw.exe puede hacer doble función:

  • Para la automatización (ejecutar oculto de una tarea programada, por ejemplo)
  • Para iniciar scripts de interacción de usuario GUI sin una ventana de consola no deseada (por ejemplo, scripts que crean UI de WinForms).

Para iniciar scripts de interacción de usuario GUI ...

¿Deberíamos guardar -WindowStyle para ellos?

¿Y la consola GUI?

¿Deberíamos guardar -WindowStyle para ellos?

No creo que eso sea útil, porque no se puede saber de antemano en qué punto y a través de qué mecanismo se creará una ventana GUI, si es que se creará, y el código que la crea tendría que consultar a PowerShell por sus parámetros de inicio de alguna manera en orden. respetar el valor.

¿Qué quieres decir con _GUI console_?

@iSazonov pwshw por definición no tendrá una consola interactiva. -WindowStyle es específicamente para la ventana de la consola. Los scripts que aprovechan WinForms / WPF son independientes del host pwshw.

¡Gracias! Se actualizó la tabla anterior.

Prefiero evitar crear un nuevo host para esto, y preferiría resolverlo con PTY donde estén disponibles.

Aquí hay una solución por ahora: lo único que aparece es una instancia de PowerShell en la barra de tareas que desaparece rápidamente, no más conhost.exe parpadeando en la pantalla.

$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

Las personas emprendedoras pueden combinar esta técnica con psexec.exe -i para ejecutar scripts de forma remota en la sesión de usuarios actualmente conectados.

  • Esto todavía muestra una ventana flash visible rápida en mis sistemas
  • Probé el silentCMD anterior pero esto requiere net3.5 que no está instalado en algunos de los sistemas de terceros en los que ejecuto esto

No parece haber una solución, creo

¿Has revisado el proyecto de GitHub para ejecutar consola oculta?
He utilizado intencionalmente los requisitos más bajos posibles. Debería funcionar en casi todas las versiones de Windows.

Como mencionó @Ciantic , la mejor manera de

En, digamos 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

Luego utilícelo para ejecutar el comando que desee, por ejemplo, desde las tareas programadas de Windows como tal

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

Utilizo algo como esto para ejecutar una tarea con frecuencia sin ver ventanas parpadeantes.

¿Has revisado el proyecto de GitHub para ejecutar consola oculta?
He utilizado intencionalmente los requisitos más bajos posibles. Debería funcionar en casi todas las versiones de Windows.

Lo probé esta semana y funciona sin que aparezcan los requisitos de net3.5. ¡Gracias! Agradable. También tendrá en cuenta el VBS.

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? ¿Que es eso?

Envoyé de mon iPhone

Le 18 de marzo de 2019 a las 21:51, Joey Aiello [email protected] a écrit:

Prefiero evitar crear un nuevo host para esto, y preferiría resolverlo con PTY donde estén disponibles.

-
Recibes esto porque estás suscrito a este hilo.
Responda a este correo electrónico directamente, véalo en GitHub o silencia el hilo.

Versión simplificada de VBScript de @ Roy-Orbison:

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

Probado en mi máquina con un script en el que estoy trabajando, parece funcionar cuando se ejecuta con wscript desde el indicador de PS o la tarea programada.

Ventajas:

  • No es necesario colocar la ruta del script en la línea de comando wscript .
  • No establece ExecutionPolicy en Bypass .

Desventajas:

  • Necesita scripts de VBScript separados para cada comando de PowerShell.

Personalmente prefiero la solución VBScript a RunHiddenConsole , ya que no implica implementar un ejecutable sin firmar en un directorio del sistema. Sin embargo, tener un pwshw.exe / powershellw.exe oficial obviamente sería preferible a cualquiera de los dos.

Personalmente prefiero la solución VBScript a RunHiddenConsole , ya que no implica implementar un ejecutable sin firmar en un directorio del sistema.

firmar no debería ser un gran problema. incluso puede hacerlo usted mismo con un pequeño esfuerzo de construirlo usted mismo
ps: también he agregado la opción de implementar la herramienta justo al lado de los scripts que desea ejecutar. por lo que ya no es necesario configurarlo en el sistema junto al ejecutable de PowerShell

Es bueno tener soluciones alternativas y una solución de terceros, pero para enfatizar el último comentario de @alexbuzzbee :

Se necesita una solución que _ viene con PowerShell_.


En cuanto a las soluciones alternativas: tenga en cuenta que una solución basada en VBScript es incluso posible sin un archivo de script auxiliar, pero es un misterio:

Lo siguiente, que puede ejecutar desde el cuadro Run diálogo cmd.exe ), crea una instancia invisible de PowerShell que muestra un cuadro de mensaje (sin mostrar una ventana de consola):

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

Advertencia : @alexbuzzbee señala que "[esta] solución genera alertas en el sistema Defender ATP Endpoint Protection [...] por lo que podría no ser adecuada en un entorno empresarial".

¿No sería razonable convertir la solución de @Vittel en la solución oficial? No debería ser difícil mover el código al repositorio de PowerShell, modificarlo para que solo inicie powershell.exe o pwsh.exe y compilarlo / distribuirlo con PowerShell.

.NET Core 3.0 admite la creación de winexe, que no mostrará la consola. Ya tengo un prototipo funcional, solo necesito limpiarlo como relaciones públicas.

Ya tengo un prototipo funcional

Yo también estaba en camino :-) Espero que simplifiques CommandLineParameterParser (¿eliminar EarlyParse?).

La solución de @ mklement0 genera alertas en el sistema Defender ATP Endpoint Protection (no le gusta que mshta ejecute código PowerShell), por lo que podría no ser adecuado en un entorno empresarial.

Gracias, @alexbuzzbee , agregué tu advertencia a mi comentario anterior. Creo que en realidad es la llamada de VBScript CreateObject() / JScript new ActiveXObject() que activa la alerta; aparentemente, mshta.exe se ha utilizado en malware en el pasado.

@ mklement0 ATP parece sospechar específicamente de mshta comienzan pwsh , en lugar de la llamada CreateObject() .

Es bueno saberlo, @alexbuzzbee.

Basé mi comentario en el hecho de que ejecutar lo siguiente (por ejemplo, desde cmd.exe ) genera un Access is denied error. y activa una alerta de Windows Defender.

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

La conclusión es que la solución alternativa probablemente se esté aprovechando de una laguna que, como ha informado, puede activar el software de seguridad existente y tal vez pueda cerrarse por completo en el futuro.

Bien por el intento de @ SteveL-MSFT de implementar una solución adecuada.

@ SteveL-MSFT, 2018-02-20

Apoyaría una contribución comunitaria para agregar pwshw.exe

@ SteveL-MSFT, 31 de octubre de 2019

.NET Core 3.0 admite la creación de winexe, que no mostrará la consola. Ya tengo un prototipo funcional, solo necesito limpiarlo como relaciones públicas.

Esto ha tardado mucho en llegar y será maravilloso para la creación de scripts, especialmente con el Programador de tareas, (¿quizás cron?), Etc. Dado que PowerShell Core es multiplataforma , ¿funcionará esto también en otras plataformas compatibles? ¿Qué tal WSL?

El prototipo winexe funcionó pero es demasiado tosco para convertirlo en 7.0. Por ejemplo, si cometió un error con los argumentos de la línea de comando, no lo sabrá ya que no hay una ventana de salida. Si seguimos otras herramientas como wscript.exe, deberíamos mostrar un cuadro de diálogo con el mensaje de error correspondiente.

En cuanto a los que no son de Windows, Linux y macOS no necesitan el equivalente de winexe, ya que creo que el proceso pwsh se puede iniciar sin crear una ventana de consola, mientras que Windows lo requiere porque diferencia explícitamente entre la consola y las aplicaciones de Windows. Ciertamente puede usar pwsh con el Programador de tareas hoy o cron, etc ... ya.

Otra versión más de VBScript shim con mejoras: admite el paso de argumentos a Powershell Script. Esto nos dará más flexibilidad en el script que se llamará. ¡Todo sin una ventana emergente!

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

Por ejemplo, tengo un script de PowerShell que escucha un evento específico de Windows, uso el Programador de tareas para extraer datos de eventos y llamo a un script de PowerShell para enviar una notificación sobre el evento. Creé una tarea programada personalizada con un EventTrigger personalizado (consulte una publicación 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>

Después de eso, podríamos usar la variable $(Path) $(ProcessName) $(User) dentro de la acción del evento. Para este caso, podríamos llamar al script como se muestra a continuación. Windows llamará a mi notifier.ps1 cada vez que un evento presione el gatillo.

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

El powershell.vbs es absolutamente reutilizable. 😏

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

Como mencionó @Ciantic , la mejor manera de

En, digamos 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

Luego utilícelo para ejecutar el comando que desee, por ejemplo, desde las tareas programadas de Windows como tal

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

Utilizo algo como esto para ejecutar una tarea con frecuencia sin ver ventanas parpadeantes.

Puede usar QB64 para crear un pequeño EXE para ocultar el script. QB64 es un intérprete de C ++ que toma el código QBASIC y lo compila en un exe de C ++. Si usa los comandos _SHELLHIDE o SHELL _HIDE , puede llamar a un script de PowerShell desde el EXE sin mostrar una ventana de PowerShell en absoluto. Lo uso junto con -WindowStyle Hidden solo para estar seguro, pero nunca he tenido ningún problema con él. Ejemplo: SHELL$ = "PowerShell -WindowStyle Hidden -ExecutionPolicy Bypass " + CHR$(34) + "&'" + _STARTDIR$ + "\GetNewDate.ps1';exit $LASTEXITCODE" + CHR$(34): a = _SHELLHIDE(SHELL$)
También puede ocultar el EXE completo que compiló usando $SCREENHIDE para que no tengan que ver ninguna parte del programa.
Si tiene un código de salida que desea devolver a un área de código diferente, puede usar exit $LASTEXITCODE cuando llame a su secuencia de comandos de PowerShell para devolverlo al EXE de QB64. Si desea pasar el código del QB64 EXE, puede usar el comando SYSTEM seguido del código que desea devolver al resto de su programa / script. Espero que esto ayude a alguien.

Usando esto ahora para que cada invocación obtenga todos los argumentos, en lugar de que cada argumento sea un script separado, como el de @ttimasdf , pero usando una matriz 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

Mantuve el -ExecutionPolicy Bypass porque obtengo fallas silenciosas a menos que también use Set-ExecutionPolicy . No puedo esperar por pwshw.exe .

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

@ Roy-Orbison
Ahí tienes. Solo necesita un cambio de nombre 😉😅
(Srsly. Nómbrelo pwshw.exe, colóquelo en su ruta y debería funcionar)

Realmente no sé por qué tarda tanto el equipo de pwsh.
No es tan importante

Realmente no sé por qué tarda tanto el equipo de pwsh.

Falta de recursos. Necesitamos más revisores y colaboradores de código.

Configuré un script de PowerShell para que se ejecutara desde Elgato Stream Deck y se abre una ventana. Intenté usar -Noninteractive y -WindowStyle hidden , pero todavía aparece brevemente.

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

Espero que obtengamos pwshw en la próxima vista previa.

Configuré un script de PowerShell para que se ejecutara desde Elgato Stream Deck y se abre una ventana. Intenté usar -Noninteractive y -WindowStyle hidden , pero todavía aparece brevemente.

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

Podrías evitar fácilmente esa ventana emergente con la herramienta que publiqué anteriormente. Usándolo todos los días con mi plataforma de vapor y scripts de inicio

FYI: En el equipo de la consola, estamos proponiendo una forma para que las aplicaciones futuras (y las versiones futuras de las aplicaciones existentes) lidien con esto. Habría un poco de sobrecarga [1], pero le daría a PowerShell la capacidad de _eligir si asignar una ventana de consola_ cuando se inicie en un contexto de GUI.

Solicitud de extracción de especificación: https://github.com/microsoft/terminal/pull/7337

¡@DHowett me alegro de haber descubierto esto antes de fusionar mi PR! Sería mejor para el cliente tener un solo exe y no preocuparse por las versiones de Winexe y mucho menos por los costos de mantenimiento para el equipo.

Pero, ¿y si llamo a PowerShell sin la terminal de Windows? Por ejemplo, estoy llamando a pwsh.exe directamente desde Elgato Stream Deck. La opción propuesta por el equipo de Terminal no resolvería este escenario, ni otros similares, ¿verdad?

@ pcgeek86 ¡no dejes que el nombre te engañe! Mi equipo y yo somos dueños de todo el subsistema de la consola de Windows, incluida la forma en que las aplicaciones de la consola se inician y se comunican entre sí.

@DHowett ¿ Supongo que eso significa que la funcionalidad solo estaría disponible en versiones futuras de Windows? Entonces, ¿alguien que todavía use versiones de Windows de nivel inferior esencialmente no tiene suerte? 🤔

Una aplicación que está en el subsistema de la consola con una consoleAllocationPolicy de hereitOnly no presentará una consola cuando se inicie desde Explorer .

¿Qué es un comportamiento del Programador de tareas?

@DHowett para pwsh, necesitaría una bandera para especificar que queremos que se asigne una conpty para que los scripts que llaman a las API de la consola sigan funcionando

Es posible que las aplicaciones como PowerShell deseen conservar la asignación de consola "automática", y hereitOnly no sería adecuado para ellas.

Entonces, ¿la política no resuelve todos los escenarios de PowerShell y PowerShell debería usar una solución alternativa nuevamente?

Esto me recuerda a mi PR donde intenté usar directamente AllocConsole.

nivel bajo (@ vexx32)

Desafortunadamente, esta es una limitación en todo lo que mi equipo produce que es parte del subsistema de la consola y no se puede enviar como parte de Terminal. Estamos tratando de trabajar en eso 😉

Cuál es el comportamiento del Programador de tareas (@iSazonov)

Decir "Explorador" fue una forma conveniente de decir "cualquier contexto que no tenga una consola" en menos palabras. Tenga la seguridad de que _ cualquier cosa que inicie una aplicación inheritOnly sin una consola no causará la asignación de una consola.

Necesitaría una bandera para especificar (@ SteveL-MSFT)

Afortunadamente, PowerShell ya tiene esto en forma de WindowStyle . El modo predeterminado puede ser "_i debería llamar a AllocConsole() _" (que atenderá todas las necesidades de la API de la consola), a menos que el usuario solicite un lanzamiento oculto. La especificación solo mueve la responsabilidad de asignar una consola a (pwsh) para que pueda obtener el control final sobre si hay un conhost. Dado que powershell ya está configurado para manejar este caso, son solo unas pocas líneas delta antes / después de la verificación "oculta".

no resuelve todos los escenarios de PowerShell (@iSazonov)

La especificación explica además cómo powershell manejaría esto (ver arriba, mi respuesta a Steve). Por lo que tengo entendido, esto resuelve _todos los escenarios mencionados en este problema y los problemas vinculados.

La principal diferencia entre llamar a AllocConsole() / AttachConsole() como lo hizo en su PR y llamar a AllocConsole() cuando su aplicación se manifiesta para una política de asignación de consola diferente es que el bit del subsistema indica que el shell de generación (cmd, pwsh, bash, ish) debe _esperar_ a que salga el shell generado ( pwshw ), lo que reduce la interferencia en los controles de E / S de la consola.

Si tiene una aplicación de subsistema de Windows que llama a AttachConsole() para volver a su consola de alojamiento, el shell de generación y la nueva aplicación pelearán por quién puede leer la entrada / escribir la salida. Es por eso que llamar a Attach _nunca_ funciona desde una aplicación del subsistema de Windows, a menos que pueda controlar completamente el shell que lo generó (no puede).

@DHowett ¡Gracias! Para que quede claro, la propuesta para PowerShell es usar SUBSYSTEM_GUI y hereitOnly?

Mi creencia es que SUBSYSTEM_CUI y inheritOnly serían correctos para PowerShell. Te da los siguientes comportamientos:

  1. cmd ( $SHELL ) esperará a que pwsh salga antes de regresar ( SUBSYSTEM_CUI )
  2. cuando lo ejecuta desde explorer / tasksched, pwsh puede tomar la decisión de crear una nueva ventana de consola ( inheritOnly )
  3. cuando lo ejecuta desde cmd / pwsh / (un shell de consola), pwsh recibirá automáticamente una ventana de consola

cuando lo ejecuta desde el explorador / tasksched, pwsh puede tomar la decisión sobre la creación de una nueva ventana de consola (sólo heredar)

Mmmm, ¿cómo podría saber PowerShell que es el propietario del proceso: explorador o asignado a tareas?

No creo que necesite saberlo.

He aquí por qué (C ++):

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

PowerShell ya sabe si generar una ventana en función de si el usuario pidió que no lo hiciera. Esa característica ya existe, por lo que este es el cambio incremental mínimo en el código que corrige este error _y_ mantiene el comportamiento original para todos los demás casos de uso.

Eso proporciona una buena plataforma sobre la que construir nuevos comportamientos.

@DHowett como @ vexx32 mencionó, todavía hay una gran cantidad de Server 2012 / R2 y 2016 en la naturaleza, así que mientras que para las variantes del sistema operativo Win10 y Server 2019 esto parece genial en el futuro, creo que para PowerShell deberíamos pensar en una manera alrededor de esto que es más elegante que la solución sugerida actual @ SteveL-MSFT

A menos que también pueda portar ese cambio a un sistema operativo de nivel inferior como parte de un parche de seguridad, ya que no está realizando actualizaciones de funciones para ellos (lo cual dudo mucho que lo haga)

que el bit del subsistema indica que el shell de generación (cmd, pwsh, bash, ish) debe esperar a que salga el shell de generación (pwshw), lo que reduce la interferencia en los controles de E / S de la consola.

También debería funcionar para PowerShell. Quiero decir, si PowerShell llama a una aplicación de consola externa, también debería seguir la nueva política. ¿PowerShell obtendrá esto automáticamente o necesitamos agregar algo en PowerShell?

PowerShell tendría que optar por participar como se menciona en la especificación. Sin embargo, mencionaste un gran punto: creo que las aplicaciones generadas _por_ una aplicación "solo heredada" mostrarán ventanas de consola, y eso es _terrible_. Revisaré esto en la especificación, porque creo que sé cómo podemos abordarlo.

A menos que también pueda portar ese cambio al sistema operativo de nivel inferior

Tengo que terminar la función antes de que podamos evaluarla para su backporting, pero estoy 100% de acuerdo en que esto limita su utilidad.

Solo quiero decir que si está iniciando PowerShell desde otro programa, existe la posibilidad de que admita la ocultación de procesos secundarios. Por ejemplo, Autohotkey tiene un indicador "Ocultar" para el comando de ejecución.

¿Fue útil esta página
0 / 5 - 0 calificaciones