variable print powershell process

print - powershell set variable



¿Cómo capturo el resultado en una variable de un proceso externo en PowerShell? (8)

Me gustaría ejecutar un proceso externo y capturar su salida de comando a una variable en PowerShell. Actualmente estoy usando esto:

$params = "/verify $pc /domain:hosp.uhhg.org" start-process "netdom.exe" $params -WindowStyle Hidden -Wait

Confirmé que el comando se está ejecutando, pero necesito capturar el resultado en una variable. Esto significa que no puedo usar -RedirectOutput porque esto solo redirige a un archivo.


Estoy intentando ejecutar comandos git (y capturar salida en variables) en un script powershell, usando la información en este hilo, puedo ejecutar comandos muy fácilmente, simplemente por:

# Make sure we''re in the correct folder cd myGitRepo # Fetch sha1 of a specific commit into a Powershell variable - works fine without variable assignment git log --grep=''My specific commit message here'' --format=%H # This does not work, git reports ''not a git repository'' $myVar = git log.... # git fatal: not a git repo

Parece que la funcionalidad de asignación de variables de alguna manera ignora la ruta actual y hace que el comando se ejecute en la carpeta raíz (que no es un repositorio git). ¿Alguien sabe por qué sucede esto y cómo puedo solucionarlo?

Actualización 2 : cd es un alias para Set-Location, así que debo haber obtenido algo completamente erróneo.

Actualización : Por extraño que parezca, haciendo Set-Location (en lugar de cd) myGitRepo parece solucionar el problema, es decir, esto funciona:

Set-Location ''./myGitRepo'' $myVar = git log .....


Has probado:

$OutputVariable = (Shell command) | Out-String


Intenté las respuestas, pero en mi caso no obtuve la salida en bruto. En cambio, se convirtió en una excepción Powershell.

El resultado bruto que obtuve:

$rawOutput = (cmd /c <command> 2`>`&1)


O prueba esto Capturará el resultado en la variable $ scriptOutput:

& "netdom.exe" $params | Tee-Object -Variable scriptOutput | Out-Null $scriptOutput


Otro ejemplo de la vida real:

$result = & "$env:cust_tls_store/Tools/WDK/x64/devcon.exe" enable $strHwid 2>&1 | Out-String

Tenga en cuenta que este ejemplo incluye una ruta (que comienza con una variable de entorno). Tenga en cuenta que las comillas deben rodear el camino y el exe , ¡pero no los parámetros!

Nota: No olvide el carácter & delante del comando pero fuera de las comillas.

El resultado de error también se recopila.

Me llevó un tiempo lograr que funcionara esta combinación, así que pensé que la compartiría.


Si también desea redirigir el resultado del error, debe hacer lo siguiente:

$cmdOutput = command 2>&1

o, si el nombre del programa tiene espacios en él:

$cmdOutput = & "command with spaces" 2>&1


Si todo lo que intenta hacer es capturar el resultado de un comando, entonces esto funcionará bien. Lo uso para cambiar la hora del sistema ya que [timezoneinfo]::local siempre produce la misma información, incluso después de haber realizado cambios en el sistema. Esta es la única forma en que puedo validar y registrar el cambio en la zona horaria:

$NewTime = (powershell.exe -command [timezoneinfo]::local) $NewTime | Tee-Object -FilePath $strLFpath/$strLFName -Append

lo que significa que tengo que abrir una nueva sesión de PowerShell para volver a cargar las variables del sistema


Fundamentalmente , la captura de resultados de utilidades externas funciona de la misma manera que con los comandos nativos de PowerShell (es posible que desee una actualización sobre cómo ejecutar herramientas externas ):

$cmdOutput = <command> # captures the command''s success stream / stdout

Para capturar resultados en una variable e imprimir en la pantalla :

<command> | Tee-Object -Variable cmdOutput # Note how the var name is NOT $-prefixed

O bien, si <command> es un cmdlet o una función avanzada , puede usar un parámetro común
-OutVariable / -ov :

<command> -OutVariable cmdOutput # cmdlets and advanced functions only

Para capturar el resultado de múltiples comandos , use una subexpresión ( $(...) ) o llame ( & or . ) A un bloque de script ( { ... } ):

$cmdOutput = $(<command>; ...) # subexpression $cmdOutput = & {<command>; ...} # or: script block with &; creates child scope for vars. $cmdOutput = . {<command>; ...} # or: script block with .; no child scope

Tenga en cuenta que la necesidad general de prefijar con & (el operador de llamada) un comando individual cuyo nombre / ruta se cita - por ejemplo, $cmdOutput = & ''netdom.exe'' ... - no está relacionado con programas externos per se (es igual se aplica a las secuencias de comandos de PowerShell), pero es un requisito de sintaxis : PowerShell analiza una instrucción que comienza con una cadena entrecomillada en el modo de expresión de forma predeterminada, mientras que el modo de argumento es necesario, que es lo que garantiza.

Las redirecciones también funcionan de la misma manera, fundamentalmente (pero vea las advertencias a continuación):

$cmdOutput = <command> 2>&1 # redirect error stream (2) to success stream (1)

Sin embargo, para comandos externos, lo siguiente es más probable que funcione como se espera:

$cmdOutput = cmd /c <command> ''2>&1'' # Let cmd.exe handle redirection - see below.

Consideraciones específicas para programas externos :

  • Los programas externos , debido a que operan fuera del sistema de tipos de PowerShell, solo devuelven cadenas a través de su secuencia de éxito (stdout).

  • Si la salida contiene más de 1 línea , PowerShell la divide de manera predeterminada en una matriz de cadenas . Más exactamente, las líneas de salida se almacenan en una matriz de tipo [System.Object[]] cuyos elementos son cadenas ( [System.String] ).

  • Si desea que la salida sea una cadena única , potencialmente multi-línea , canalice a Out-String :
    $cmdOutput = <command> | Out-String

  • Redirigir stderr a stdout con 2>&1 , a fin de capturarlo también como parte de la secuencia de éxito, viene con advertencias :

    • Para hacer que 2>&1 fusione stdout y stderr en el origen , deje que cmd.exe maneje la redirección , utilizando los siguientes modismos:
      $cmdOutput = cmd /c <command> ''2>&1'' # *array* of strings (typically)
      $cmdOutput = cmd /c <command> ''2>&1'' | Out-String # single string

      • cmd /c invoca cmd.exe con el comando <command> y sale después de que <command> haya finalizado.
      • Tenga en cuenta las comillas simples alrededor de 2>&1 , lo que garantiza que la redirección se pase a cmd.exe lugar de ser interpretada por PowerShell.
      • Tenga en cuenta que la participación de cmd.exe significa que sus reglas para el escape de caracteres y la expansión de variables de entorno entran en juego, de manera predeterminada, además de los requisitos de PowerShell; en PS v3 + puede usar un parámetro especial --% (el denominado símbolo de detención de análisis ) para desactivar la interpretación de los parámetros restantes por parte de PowerShell, excepto las referencias de variable de entorno de estilo cmd.exe , como %PATH% .

      • Tenga en cuenta que dado que fusiona stdout y stderr en la fuente con este enfoque, no podrá distinguir entre líneas originadas en stdout y originadas en stderr en PowerShell; si necesita esta distinción, use el propio redireccionamiento 2>&1 PowerShell, consulte a continuación.

    • Utilice la redirección 2>&1 PowerShell para saber qué líneas provienen de qué secuencia :

      • La salida Stderr se captura como registros de errores ( [System.Management.Automation.ErrorRecord] ), no como cadenas, por lo que la matriz de salida puede contener una combinación de cadenas (cada cadena representa una línea stdout) y registros de errores (cada registro representa una línea stderr ) Tenga en cuenta que, según lo solicitado por 2>&1 , tanto las cadenas como los registros de errores se reciben a través del flujo de salida de éxito de PowerShell).

      • En la consola, los registros de error se imprimen en rojo , y el 1er por defecto produce una visualización de varias líneas , en el mismo formato que el error sin terminación del cmdlet; los registros de errores posteriores también se imprimen en rojo, pero solo imprimen su mensaje de error en una sola línea .

      • Cuando se envían a la consola , las cadenas normalmente aparecen primero en la matriz de salida, seguidas por los registros de errores (al menos entre un lote de líneas stdout / stderr que salen "al mismo tiempo"), pero afortunadamente cuando se captura la salida , está intercalado correctamente , utilizando la misma orden de salida que obtendría sin 2>&1 ; en otras palabras: al enviar a la consola , la salida capturada NO refleja el orden en que las líneas stdout y stderr fueron generadas por el comando externo.

      • Si captura la salida completa en una sola cadena con Out-String , PowerShell agregará líneas adicionales , porque la representación de cadena de un registro de error contiene información adicional, como ubicación ( At line:... ) y categoría ( + CategoryInfo ... ); curiosamente, esto solo se aplica al primer registro de error.

        • Para evitar este problema, aplique el método .ToString() a cada objeto de salida en lugar de conectarlo a Out-String :
          $cmdOutput = <command> 2>&1 | % { $_.ToString() } $cmdOutput = <command> 2>&1 | % { $_.ToString() } ;
          en PS v3 + puedes simplificarlo a:
          $cmdOutput = <command> 2>&1 | % ToString
          (Como beneficio adicional, si la salida no se captura, esto produce una salida correctamente intercalada incluso cuando se imprime en la consola.)
      • Alternativamente, filtre los registros de errores y envíelos a la secuencia de errores de PowerShell con Write-Error (como extra, si la salida no se captura, esto produce una salida correctamente entrelazada incluso cuando se imprime en la consola):

$cmdOutput = <command> 2>&1 | ForEach-Object { if ($_ -is [System.Management.Automation.ErrorRecord]) { Write-Error $_ } else { $_ } }