¿Cómo ejecutar un script de PowerShell sin mostrar una ventana?

127

¿Cómo es posible ejecutar un script de PowerShell sin mostrar una ventana o cualquier otro signo al usuario?

En otras palabras, el script debe ejecutarse silenciosamente en segundo plano sin ningún signo para el usuario.

Crédito adicional por una respuesta que no utiliza componentes de terceros :)

Thomas Bratt
fuente
Consulte esta pregunta si está interesado en aprender: stackoverflow.com/questions/573623/powershell-vs-unix-shells
Thomas Bratt el
Esta solución también funciona para el Programador de tareas: stackoverflow.com/a/51007810/571591
Hilydrow

Respuestas:

128

Puede ejecutarlo así (pero esto muestra una ventana por un tiempo):

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

O usa un archivo auxiliar que creé para evitar la ventana llamada PsRun.exe que hace exactamente eso. Puedes descargar la fuente y el archivo exe Ejecutar tareas programadas con WinForm GUI en PowerShell . Lo uso para tareas programadas.

Editado: como señaló Marco, este parámetro -windowstyle está disponible solo para V2.

stej
fuente
66
Compilé el PsRun, sin embargo, si lo agrego a la tarea programada, también
muestra
2
Lo mismo aquí, tampoco funciona porque la ventana todavía aparece para ejecutar el script. Sale rápidamente pero estamos tratando de ejecutar esto en segundo plano sin interrupción.
Nathan McKaskle el
1
Sí, por eso hay "pero esto muestra una ventana por un tiempo" en la respuesta.
stej
21
@ThomasBratt Para las tareas programadas, he encontrado que los scripts de PowerShell se ejecutan silenciosamente sin -WindowStyle Hiddenque la tarea esté configurada Run whether user is logged on or noten la pestaña General en la sección "Opciones de seguridad".
Adam
1
El uso de la cuenta de usuario a SYSTEM también evita que se muestre una ventana.
Jon Eldridge
27

Estaba teniendo este mismo problema. Descubrí que si va a la Tarea en el Programador de tareas que ejecuta el script powershell.exe , puede hacer clic en " Ejecutar si el usuario inició sesión o no " y eso nunca mostrará la ventana de Powershell cuando se ejecuta la tarea.

Yusha
fuente
3
La mejor solución sin depender de una extensión de terceros, ejecutable o script de contenedor.
invertir el
1
Tenga en cuenta que esta opción requiere que el usuario tenga el privilegio "Iniciar sesión como trabajo por lotes"
gb96
Esta solución hace que mi script no se ejecute correctamente .
Martin Argerami
18

Puede usar las Extensiones de comunidad de PowerShell y hacer esto:

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

También puede hacer esto con VBScript: http://blog.sapien.com/index.php/2006/12/26/more-fun-with-scheduled-powershell/

(A través de este hilo del foro ).

hacha.
fuente
¿Hay un paquete NuGet para esto para que pueda ejecutarlo desde Visual Studio?
Piotr Kula
13

Aquí hay un enfoque que no requiere argumentos de línea de comando o un lanzador separado. No es completamente invisible porque una ventana se muestra momentáneamente al inicio. Pero luego se desvanece rápidamente. Donde está bien, creo que este es el enfoque más fácil si desea iniciar su secuencia de comandos haciendo doble clic en el explorador o mediante un acceso directo del menú Inicio (que incluye, por supuesto, el submenú Inicio). Y me gusta que sea parte del código del script en sí, no algo externo.

Pon esto al frente de tu 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
fuente
10

Aquí hay una frase:

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

Aunque es posible que esto muestre una ventana muy brevemente, eso debería ser algo raro.

Adam Taylor
fuente
En la mayoría de los casos, ejecutar Powershell.exe en el contexto de los usuarios registrados mostrará una ventana completa o parpadeará brevemente si usa -windowstyle hidden. Para eliminar completamente la ventana, puede hacer una de dos cosas: 1: Ejecutar en un contexto de usuario diferente, como una cuenta de administrador (no mostrará ninguna ventana al usuario que haya iniciado sesión). O 2: utilice un vbscript con objshell.run con un indicador de ventana oculto para iniciar cmd.exe / c powershel.exe -file c: \ script.ps1. Cuando se llama powershell desde cmd, se ejecutará en la ventana cmd existente que ya está oculta por wscript.exe // b / nologo c: \ launcher.vbs.
Iconiu
wow, de repente. Ni siquiera noté tu respuesta al principio. Respondí con un guión muy similar. Es agradable ver a una persona bien informada que da una respuesta real.
Gosha
Esta debería ser la respuesta aceptada, es el único método que parece funcionar en todas las situaciones (incluso dentro del programador de tareas, que era mi problema).
Martin Argerami
6

Estaba teniendo este problema cuando se ejecutaba desde c #, en Windows 7, el servicio "Detección de servicios interactivos" aparecía al ejecutar una ventana oculta de PowerShell como la cuenta SYSTEM.

El uso del parámetro "CreateNoWindow" evitó que el servicio ISD apareciera como advertencia.

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

Creo que la mejor manera de ocultar la pantalla de la consola de PowerShell cuando ejecuta scripts en segundo plano es este código ( respuesta " Bluecakes ").

Agrego este código al comienzo de todos mis scripts de PowerShell que necesito ejecutar en segundo plano.

# .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 esta respuesta fue de ayuda, vote a "Bluecakes" en su respuesta en esta publicación.

Gavraham
fuente
Para mí, la consola todavía se muestra durante aproximadamente un segundo.
Thdoan
3

ps1 oculto del Programador de tareas y acceso directo también

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

He creado una pequeña herramienta que pasa la llamada a cualquier herramienta de consola que desee iniciar sin ventanas al 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 con los parámetros habituales y no aparecerá una ventana emergente.

Si alguien tiene una idea de cómo verificar si el proceso creado está esperando la entrada, me complacerá incluir su solución :)

Chris
fuente
1
Esta es la mejor respuesta si desea ejecutar scripts de PowerShell utilizando MessageBoxsin ningún flash de la ventana al inicio (que requiere un EXE compilado como Winexe, no una aplicación de consola, y que requiere que el Programador de tareas se configure en "Ejecutar solo cuando el usuario ha iniciado sesión en "para que los cuadros de diálogo se muestren en la sesión de escritorio actual.) ¡Gracias por implementar esto, powershellw.exe ha estado en mi lista de deseos durante años!
Carl Walsh
PD: ¡he incluido la solución para "esperar la entrada" hace un tiempo (así como un par de correcciones de errores)!
Chris
@CarlWalsh, supongo que quiere decir que no es una aplicación de consola, sino una aplicación de formularios de ganancias, lo cual es correcto. simplemente no incluye ninguna ventana. pero el tipo de proyecto debería definirse en el archivo csproj y no debería necesitar establecer un tipo de salida específico después de abrirlo con Visual Studio
Chris
2

Aquí hay una solución de trabajo en Windows 10 que no incluye ningún componente de terceros. Funciona envolviendo el script de PowerShell en VBScript.

Paso 1: necesitamos cambiar algunas características de Windows para permitir que VBScript ejecute PowerShell y abrir archivos .ps1 con PowerShell de manera predeterminada.

-Ir a ejecutar y escribir "regedit". Haga clic en Aceptar y luego permita que se ejecute.

-pega esta ruta "HKEY_CLASSES_ROOT \ Microsoft.PowerShellScript.1 \ Shell" y presiona Enter.

-ahora abra la entrada a la derecha y cambie el valor a 0.

-Abra PowerShell como administrador y escriba "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned", presione enter y confirme el cambio con "y" y luego ingrese.

Paso 2: Ahora podemos comenzar a ajustar nuestro script.

-Guarde su script Powershell como un archivo .ps1.

-crear un nuevo documento de texto y pegar este 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

-ahora cambie la ruta del archivo a la ubicación de su script .ps1 y guarde el documento de texto.

-Ahora haga clic derecho en el archivo y vaya a cambiar el nombre. Luego cambie la extensión del nombre de archivo a .vbs y presione Entrar y luego haga clic en Aceptar.

¡HECHO! Si ahora abre .vbs, no debería ver ninguna ventana de consola mientras su script se ejecuta en segundo plano.

¡asegúrate de votar si esto funcionó para ti!

neobihli
fuente
1

Aquí hay una demostración divertida de controlar los diversos estados de la consola, incluidos minimizar y ocultar.

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
fuente