Espera En La Pizca
Estoy tratando de ejecutar un programa de PowerShell, esperar a que la salida, a continuación, obtener acceso a la ExitCode, pero no tener mucha suerte. No quiero usar - Wait con Start-Process, ya que necesito algún procesamiento para continuar en el fondo. Heres un script de prueba simplificado: Ejecutar este script hará que notepad se inicie. Después de que se cierra manualmente, se imprimirá el código de salida y se iniciará de nuevo sin utilizar - wait. No se proporciona ExitCode cuando esto está cerrado: Tengo que poder realizar procesamiento adicional entre iniciar el programa y esperar a que lo deje, así que no puedo hacer uso de - Wait. Cualquier idea de cómo puedo hacer esto y aún tener acceso a la propiedad. ExitCode de este proceso se preguntó Apr 21 12 at 19:23 Hay dos cosas a recordar aquí. Uno es agregar el argumento - PassThru y dos es añadir el argumento - Wait. Usted necesita agregar el argumento de la espera debido a este defecto connect. microsoft/PowerShell/feedback/details/520554/start-process-does-not-return-exitcode-property Una vez que usted hace esto un objeto del proceso se pasa detrás y usted puede mirar En la propiedad ExitCode de ese objeto. Aquí está un ejemplo: Si lo ejecuta sin - PassThru o - Wait, no imprimirá nada. Uso de Windows PowerShell Jobs Resumen: Microsoft Scripting Guy, Ed Wilson, muestra un extracto de su nuevo libro paso a paso sobre el uso de Windows Trabajos de PowerShell. El chico de Microsoft Scripting, Ed Wilson, está aquí. Hoy quiero compartir una parte de mi nuevo libro de Microsoft Press Windows PowerShell 3.0 paso a paso. Este libro está disponible ahora para preorder. Uso de trabajos de Windows PowerShell Puede iniciar un nuevo trabajo de Windows PowerShell mediante el cmdlet Start-Job. El comando para ejecutar como un trabajo se coloca en un bloque de secuencia de comandos y los trabajos se denominan secuencialmente Job1, Job2 hellip Esto se muestra aquí. PS C: gt Inicio de trabajo - ScriptBlock Id Nombre PSJobTypeName Estado HasMoreData Ubicación 8212 8212 8212821282128212 82128211 8212821282128211 821282128211 10 Job10 BackgroundJob Ejecución true localhost PS C: gt Los trabajos reciben ID de trabajo que también están numerados secuencialmente. El primer trabajo creado en una consola de Windows PowerShell siempre es ID de trabajo 1. Puede utilizar el ID de tarea o el nombre del trabajo para obtener información sobre el trabajo. Esto se ve aquí. PS C: GT Get-Job - Nombre job10 Id Nombre PSJobTypeName Estado HasMoreData Ubicación 8212 8212- 8212821282128212- 82128211 8212821282128211 821282128211 10 Job10 BackgroundJob Completado verdadera localhost PS C: GT Get-Job - Id 10 Id Nombre PSJobTypeName Estado HasMoreData Ubicación 8212- 8212 8212821282128212 - 82128211 8212821282128211 821282128211 10 Job10 BackgroundJob Completed True localhost Una vez que vea que el trabajo se ha completado, puede recibir el trabajo. El cmdlet Receive-Job devuelve la misma información que se devuelve si no se utiliza un trabajo. La salida de Job1 que se ve aquí (truncada para ahorrar espacio). PS C: gt Tarea de recepción-Nombre job10 Manejo NPM (K) PM (K) CPU (s) CPU (s) VM (M) Id Nombre de proceso 82128212- 82128212 82128211 82128211 82128211 82128212 8212 8212821282128211 62 9 1672 6032 80 0,00 1408 apdproxy 132 9 2316 5632 62 1364 atieclxx 122 7 1716 4232 32 948 atiesrxx 114 9 14664 15372 48 1492 audiodg 556 62 53928 5368 616 3.17 3408 CCC 58 8 2960 7068 70 0,19 928 conhost 32 5 1468 3468 52 0.00 5068 conhost 784 14 3284 5092 56 416 csrss 529 27 2928 17260 145 496 csrss 182 13 8184 11152 96 0.50 2956 DCPSysMgr 135 11 2880 7552 56 2056 DCPSysMgrSvc 8230 (salida truncada) Una vez que se ha recibido un trabajo, es decir, los datos se han ido, a menos que lo guarde una variable. El siguiente código ilustra este concepto. PS C: gt Trabajo de nombre de trabajo de recepción 10 PS C: gt Lo que puede ser confuso es que el trabajo sigue existiendo y el cmdlet Get-Job continúa recuperando información sobre el trabajo. Esto se ve aquí. PS C: gt Get-Job - Id 10 Id Nombre PSJobTypeName Estado HasMoreData Ubicación 8212 8212- 8212821282128212- 82128211 8212821282128211 821282128211 10 Job10 BackgroundJob Completado localhost Falso Como práctica recomendada, utilice el cmdlet Remove-Job para eliminar restos de los trabajos terminados cuando estás Terminado con el objeto de trabajo. Esto evitará confusiones con respecto a los trabajos activos, los trabajos terminados y los trabajos que esperan ser procesados. Después de que se haya eliminado un trabajo, el cmdlet Get-Job devuelve un error si intenta recuperar información sobre el trabajo mdash porque ya no existe. Esto se ilustra aquí. PS C: gt Eliminar trabajo-Nombre job10 PS C: gt Obtener trabajo - Id 10 Get-Job. El comando no puede encontrar un trabajo con el identificador de trabajo 10. Compruebe el valor del parámetro Id y vuelva a intentar el comando. En la línea: 1 char: 1 Get-Job - Id 10 CategoryInfo. ObjectNotFound: (10: Int32) Get-Job, PSArgumentExcepción FullyQualifiedErrorId. JobWithSpecifiedSessionNotFound, Microsoft. PowerShell. Commands. GetJobCommand Al trabajar con los cmdlets de trabajo, me gusta dar a los trabajos su propio nombre. Un trabajo que devuelve objetos de proceso a través del cmdlet Get-Process podría llamarse getProc. Un esquema de nomenclatura contextual funciona mejor que tratar de mantener un registro de nombres como Job1 o Job2. No se preocupe por hacer que sus nombres de trabajo sean demasiado largos, ya que puede utilizar caracteres comodín para simplificar el requisito de escritura. Cuando reciba el trabajo, asegúrese de almacenar los objetos devueltos en una variable. Esto se muestra aquí. PS C: GT Start-Job - Nombre getProc - ScriptBlock Id Nombre PSJobTypeName Estado HasMoreData Ubicación 8212 8212- 8212821282128212- 82128211 8212821282128211 821282128211 12 getProc BackgroundJob Correr verdadera localhost PS C: GT Get-Job - Nombre obtener Id Nombre PSJobTypeName Estado HasMoreData Localización 8212 8212 - 8212821282128212- 82128211 8212821282128211 821282128211 12 getProc BackgroundJob Completed True localhost PS C: gt procObj Recibir-Trabajo - Name get PS C: gt Una vez que el objeto devuelto en una variable, puede utilizar el objeto con otros cmdlets de Windows PowerShell. Una cosa a tener en cuenta es que el objeto es deserializado. Esto se ve aquí donde uso gm como un alias para el cmdlet Get-Member. PS C: gt procObj gm TipoName: Deserialized. System. Diagnostics. Process Esto significa que no todos los miembros normales del objeto System. Diagnostics. Process. NET Framework están disponibles. Los métodos normales se muestran aquí (gps es un alias para el cmdlet Get-Process, gm un alias para Get-Member y ndashm es suficiente del parámetro ndashmembertype para distinguirlo en la línea de consola de Windows PowerShell). PS C: gt gps g método - m TypeName: Nombre System. Diagnostics. Process MemberType Definición 8212- 821282128212- 821282128212- BeginErrorReadLine Método System. Void BeginErrorReadLine () Método BeginOutputReadLine System. Void BeginOutputReadLine () Método CancelErrorRead System. Void CancelErrorRead () CancelOutputRead Método System. Void CancelOutputRead () Cerrar Método System. Void Cerrar () CloseMainWindow Método bool CerrarMainWindow () CreateObjRef Método System. Runtime. Remoting. ObjRef CreateObjRef (type requestedType) Dispose Método System. Void Dispose () Equals Método bool Equals (System. Object obj) Método GetHashCode int GetHashCode () Método GetLifetimeService System. Object GetLifetimeService () Método GetType tipo GetType () Método InitializeLifetimeService System. Object InitializeLifetimeService () Método de muertes System. Void Kill () método Refresh System. Void Actualizar () Método de inicio bool start () método toString string toString () WaitForExit WaitForExit Método bool (int milisegundos), se muestran System. Void WaitForExit () Método WaitForInputIdle bool WaitForInputIdle (int milisegundos), bool WaitForInputIdle () Métodos del objeto deserializado aquí donde utilizo el mismo Comando que usé anteriormente. PS C: gt procObj gm TypeName método - m: Nombre Deserialized. System. Diagnostics. Process MemberType Definición 8212- 821282128212- 821282128212- ToString cadena Método ToString (), String toString (formato de cadena, System. IFormatProvider formatProvider) PS C: GT Únete Me mañana para un puesto de invitado por Microsoft MVP y Scripting Honorario Guy Don Jones en nuevas resoluciones yearrsquos. Te invito a que me sigas en Twitter y Facebook. Si tiene alguna pregunta, envíeme un correo electrónico a scriptermicrosoft. O publicar sus preguntas en el Foro Oficial de Scripting Guys. Te veo mañana. Hasta entonces, paz. Devolver un código de salida de un script de PowerShell Martes, 13 de Julio de 2010 Devolver un código de salida de un script de PowerShell parece fácil pero no es tan obvio. En esta entrada de blog te mostraré una aproximación que funciona para los scripts de PowerShell que se pueden llamar desde PowerShell y secuencias de comandos por lotes, donde el comando a ejecutar puede especificarse en una cadena, ejecutar en su propio contexto y siempre devolver el error correcto código. A continuación se muestra una especie de transcripción de los pasos que tomé para llegar a un enfoque que funciona para mí. Es una transcripción de los pasos que tomé, para que las conclusiones salten al final. En muchas publicaciones de blog, puede leer acerca de cómo llamar a un script de PowerShell al que llama desde un script de proceso por lotes y cómo devolver un código de error. Esto se reduce a lo siguiente: Write-Host quotExiting con código 12345quot exit 12345 PowerShell - NonInteractive - NoProfile - Command quotamp quot echo De Cmd. exe: Exit. ps1 salió con código de salida errorlevel Ejecutar c: temptestexit. cmd da como resultado la siguiente salida : Saliendo con el código 12345 De Cmd. exe: Exit. ps1 salió con el código de salida 12345 Pero ahora queremos llamarlo desde otro script de PowerShell, ejecutando PowerShell: PowerShell - NonInteractive - NoProfile - Command c: tempexit. ps1 Write-Host quotFrom PowerShell: Exit. ps1 salió con el código de salida LastExitCodequot Ejecutar c: temptestexit. ps1 resulta en la salida siguiente: Salir con el código 12345 De PowerShell: Exit. ps1 salió con código de salida 1 Esto no es lo que esperábamos ¿Qué pasa si el script acaba de regresar El código de salida es 0, de lo contrario el código de salida es 1, incluso si sale con un código de salida Pero lo que si llamamos a la secuencia de comandos directamente, en lugar de a través del comando PowerShell Cambiar exit. ps1 a: Write-Host quotGlobal valor de la variable: globalvariablequot Write-Host quotExiting con el código de salida 12345 12345quot Y cambiamos testexit. ps1 a: mundial: GLOBALVariable quotMy mundial valuequot variable de amperios c: tempexit. ps1 Write-Host quotFrom PowerShell: Exit. ps1 salió con el código de salida LastExitCodequot Ejecución c: temptestexit. Ps1 da como resultado la siguiente salida: Valor de la variable global: Mi valor de la variable global Saliendo con el código 12345 De PowerShell: Exit. ps1 salió con el código de salida 12345 Esto es lo que queríamos Pero ahora estamos ejecutando el script exit. ps1 en el contexto de la Testexit. ps1 script, la variable global definida globalvariable es aún conocida. Esto no es lo que queremos. Queremos ejecutarlo es aislamiento. Cambiamos c: temptestexit. ps1 a: mundial: GLOBALVariable quotMy valuequot variable global PowerShell - NonInteractive - NoProfile - Command c: tempexit. ps1 Write-Host quotFrom PowerShell: Exit. ps1 salió con el código de salida LastExitCodequot Ejecución c: resultados en temptestexit. ps1 La salida siguiente: Valor de variable global: Saliendo con código 12345 De PowerShell: Exit. ps1 salió con código de salida 1 No estamos ejecutando exit. ps1 en el contexto de testexit. ps1, que es bueno. Pero, ¿cómo podemos llegar al santo grial? Escribir un script de PowerShell que se puede ejecutar a partir de secuencias de comandos de lotes y de PowerShell Que devuelve un código de error específico Puede especificarse como una cadena Puede ejecutarse tanto en el contexto de un script de PowerShell de llamada Y Una llamada a PowerShell) en su propio espacio de ejecución Cambiamos c: temptestexit. ps1 a: global: globalvariable quotMy variable global valuequot PowerShell - NonInteractive - NoProfile - Command160 Write-Host quotDesde PowerShell: Exit. ps1 salió con código de salida LastExitCodequot Esta es la El mismo enfoque que cuando lo llamamos desde el script por lotes. Ejecutar c: temptestexit. ps1 produce la salida siguiente: Valor de la variable global: Salir con el código 12345 Desde PowerShell: Exit. ps1 salió con el código de salida 12345 Esto está cerca. Pero queremos ser capaces de especificar el comando a ejecutar como cadena, por ejemplo: comando quotc: tempexit. ps1 - param1 x - param2 yquot Cambiamos c: tempexit. ps1 a: (soporte para variables, prueba si en su propio contexto) param (param1, param2) Write-Host quotparam1param1 param2param2quot Write-Host quotGlobal valor de la variable: globalvariablequot Write-Host quotExiting con el código de salida 12345 12345quot Si cambiamos c: temptestexit. ps1 a: mundial: quotMy quotc comando valuequot variable global GLOBALVariable: Tempexit. ps1 - param1 x - param2 yquot Invoke-Expression - Command comando Write-Host quotDesde PowerShell: Exit. ps1 salió con código de salida LastExitCodequot Obtenemos un buen código de salida, pero todavía estamos ejecutando en el contexto de testexit. ps1. Si utilizamos el mismo truco que en la llamada desde un script por lotes, que funcionó antes de Cambiar c: temptestexit. ps1 a: global: globalvariable quotMy variable global valuequot comando quotc: tempexit. ps1 - param1 x - param2 yquot PowerShell - NonInteractive - NoProfile - Command Write-Host quotDesde PowerShell: Exit. ps1 salió con código de salida LastExitCodequot La ejecución de c: temptestexit. ps1 resulta en la siguiente salida: De PowerShell: Exit. ps1 salió con código de salida 0 Ok, vamos a usar la Invoke-Expression nuevamente. Cambiamos c: temptestexit. ps1 a: mundial: GLOBALVariable quotMy comando quotc mundial valuequot variables: tempexit. ps1 - param1 x - param2 yquot PowerShell - NonInteractive - NoProfile - Command Write-Host quotFrom PowerShell: Exit. ps1 salió con el código de salida LastExitCodequot Ejecución C: temptestexit. ps1 da como resultado la siguiente salida: No se puede enlazar argumento al parámetro Command porque es null. Debería volver a ejecutar el comando como una cadena, por lo que no entre paréntesis (en un bloque de secuencia de comandos). Cambiamos c: temptestexit. ps1 a: mundial: GLOBALVariable quotMy comando quotc mundial valuequot variables: tempexit. ps1 - param1 x - param2 yquot PowerShell - NonInteractive - NoProfile - Command comando Write-Host quotFrom PowerShell: Exit. ps1 salió con el código de salida LastExitCodequot Ejecutando c: temptestexit. ps1 resulta en la siguiente salida: param1x param2y Valor de la variable global: Saliendo con el código 12345 De PowerShell: Exit. ps1 salió con el código de salida 1 Ok, podemos ejecutar el texto del comando especificado como si fuera un comando de PowerShell. Pero todavía tenemos el problema de código de salida, sólo se devuelve 0 o 1. Vamos a probar algo completamente diferente. Cambiamos c: tempexit. ps1 a: param (param1, param2) Función ExitWithCode 160 160 160 160 160 160 param (160160160160160160160 exitcode 160160160) 160160160 host. SetShouldExit (código de salida) 160160160 salida Write-Host quotparam1param1 param2param2quot Write-Host quotGlobal valor de la variable: globalvariablequot Write-Host QuotExiting with code 12345quot ExitWithCode - exitcode 12345 Write-Host quotAfter exitquot Lo que hacemos es especificar al host el código de salida que queremos usar, y luego salir, todo en la función de utilidad más simple. Ejecutando c: temptestexit. ps1 resulta en la salida siguiente: param1x param2y Valor de variable global: Saliendo con código 12345 De PowerShell: Exit. ps1 salió con código de salida 12345 Ok, esto cumple todos nuestros sueños de santo graal Pero no podríamos hacer la llamada de la escritura de la hornada también más sencillo el cambio c: temptestexit. cmd a: PowerShell - NonInteractive - NoProfile - Command quotc: tempexit. ps1 - param1 x - param2 yquot eco de cmd. exe: Exit. ps1 salió con el código de salida de nivel de error Ejecución c: temptestexit. cmd Resulta en la siguiente salida: param1x param2y Valor de la variable global: Saliendo con el código 12345 De Cmd. exe: Exit. ps1 salió con código de salida 12345 Esto es aún más simple Ahora podemos llamar al código de PowerShell, sin la salida de LastExitCode truco Y ahora el Conclusiones después de esta larga historia larga, que tomó mucho tiempo para averiguar (y para leer para usted): No utilice exit para devolver un valor del código de PowerShell, pero utilice la función siguiente: function ExitWithCode 160160160 parámetro 160160160 (160160160160160160160 código de salida 160160160 ) 160 160 160 host. SetShouldExit (código de salida) de la escritura llamada 160160160 salida de lotes usando: PowerShell - NonInteractive - NoProfile - Command quotc: tempexit. ps1 - param1 x - param2 yquot eco errorlevelCall de PowerShell con: (comando especificado en cadena, ejecutar en el propio contexto ) Comando quotc: tempexit. ps1 - param1 x - param2 yquot PowerShell - NonInteractive - NoProfile - Command command LastExitCode contiene el código de salida Llamada de PowerShell con: (comando directo, ejecutar en su propio contexto) PowerShell - NonInteractive - NoProfile - Command LastExitCode contiene el código Exit codeCall de Powershell con: (comando especificado en cadena, invocar en el contexto del llamante) comando quotc: tempexit. ps1 - param1 x - param2 yquot Invoke-Expression - Command command LastExitCode contiene la salida codeCall de PowerShell con: (comando directo, ejecutar en Contexto de la persona que llama) amp c: tempexit. ps1 - param1 x - param2 y LastExitCode contiene el código de salida 9 Comentarios Nice post, pero por qué haven39t usaste el switch de archivo en lugar del switch de comando Si solo quieres ejecutar un script y estás interesado en Su código de salida me parece mucho más simple: powershell - noprofile - noninteractive - file C: tempexit. ps1 Con - file usted can39t especificar cualquier argumento. En realidad, puede especificar argumentos, al menos en v2 PowerShell. Powershell - File myscript. ps1 - param1 value1 - param2 value2. Etc esto está funcionando bien para mí. Gracias por compartir. En la función ExitWithCode, don39t que desea quotexit exitcodequot Eso no funciona para mí (XP / PS1), en lote ejecutar mi código de salida es 0, no importa lo que he establecido en el script ps. En otras palabras, lo que es el valor de exitcode para poner en host. SetShouldExit (exitcode), errorlevel devolver 0 o lo que especifico para el comando exit, así quotexit 358quot funciona y me da código de salida 358. Increíble post. Pregunta rápida: No debería ser una de las explicaciones en la Conclusión de cómo llamarla incluir el carácter 39amp39 para - Command Highly descriptive post, me encantó ese bit. Habrá una parte 2 Hola allí sólo deseo ofrecerle un gran pulgar hacia arriba para su excelente información que tienes aquí en este post. Volveré a su sitio para más pronto. Los comentarios han sido deshabilitados para este contenido.
Comments
Post a Comment