2010-08-05 21 views
8

Espero que el título sea conciso, pero por las dudas:¿Llamar a PowerShell por lotes y recuperar el nuevo valor de una variable de entorno temporal establecida en el script?

Estoy llamando a un script de PowerShell desde un archivo por lotes. Quiero que el script de PowerShell establezca el valor de una variable de entorno y que ese nuevo valor esté disponible en el archivo por lotes cuando finalice el script de PowerShell.

Sé que es posible establecer una variable de entorno usando $ env en PowerShell, pero el valor no persiste cuando termina el script de PowerShell. Imagino que esto es probablemente porque PowerShell se ejecuta en un proceso separado.

Soy consciente de que puedo devolver un código de salida y usar% ErrorLevel%, pero eso solo me dará números, y habrá un conflicto, ya que 1 indica una excepción de PowerShell en lugar de un número útil.

Ahora, aquí está la advertencia: no quiero que la variable de entorno persista. Es decir, no quiero que se defina para el usuario o el sistema y, por lo tanto, quiero que no esté disponible tan pronto como se cierre el archivo por lotes. En última instancia, simplemente quiero comunicar los resultados de una secuencia de comandos de PowerShell al archivo por lotes de la llamada.

¿Esto es posible?

Gracias de antemano :)

Nick

Respuesta

-1

La forma más directa para capturar los resultados de PowerShell es utilizar la salida estándar en PowerShell. Por ejemplo, esto ahorra la fecha a la d env var en cmd.exe

set d = powershell -noprofile "& { get-date }" 
+0

Buena solución. Dudo que haya otro que sea tan fácil y directo. – stej

+2

Gracias por la respuesta, pero no creo que lo anterior funcione? Lo que esperaría que sucediera en este caso es que el valor de la variable de entorno 'd' será 'powershell -noprofile' y {get-date} "'. IE: los contenidos del lado derecho de la expresión no son evaluados. –

+0

@Nicholas, tienes razón. Lo he intentado ahora y realmente solo hay una cadena almacenada en la variable. – stej

10

Para obtener idea de Keith de utilizar la salida estándar para trabajar, puede invocar powershell de su escritura de la hornada así:

FOR /F "usebackq delims=" %v IN (`powershell -noprofile "& { get-date }"`) DO set "d=%v" 

un poco incómodo, pero funciona:

C:\>FOR /F "usebackq delims=" %v IN (`powershell -noprofile "& { get-date }"`) DO set "d=%v" 
C:\>set d 
d=August 5, 2010 11:04:36 AM 
+1

Además, si está ejecutando este código en un archivo de proceso por lotes y no desde la línea de comandos, necesitará usar signos de porcentaje dobles delante de su nombre de variable (es decir, cambie% v a %% v en ambos lugares en el ejemplo anterior) – deadlydog

+0

Si desea obtener más información, puede verla en https://blogs.msdn.microsoft.com/oldnewthing/20120731-00/?p=7003 – Arithmomaniac

0

sé que es un poco tarde para responder a esta pregunta, pero me gustaría probarlo por si acaso alguno necesita una solución más detallada. Entonces, aquí va.

he creado una función de la hornada que ejecutar un script ps para usted y devolver un valor, algo parecido a esto:

:: A function that would execute powershell script and return a value from it. 
:: <PassPSCMD> pass the powreshell command, notice that you need to add any returning value witth Write-Host 
:: <RetValue> the returned value 
:RunPS <PassPSCMD> <RetValue> 
    Powershell Set-ExecutionPolicy RemoteSigned -Force 
    for /F "usebackq tokens=1" %%i in (`Powershell %1`) do set returnValue=%%i 
    set "%2=%returnValue%" 
Goto:eof 
:: End of :RunPS function 

Ahora bien, como un ejemplo para usarlo:

set psCmd="&{ Write-Host 'You got it';}" 
call :RunPS %psCmd% RetValue 
echo %RetValue% 

Esta voluntad mostrar en la pantalla de la consola Lo tienes

Como un ejemplo más complicado, agregaría:

Supongamos que queremos comprobar si una máquina virtual está arriba o abajo, es decir, si está encendido o apagado, por lo que podemos hacer lo siguiente:

:CheckMachineUpOrDown <returnResult> <passedMachineName> 
    set userName=vCenterAdministratorAccount 
    set passWord=vCenterAdminPW 
    set vCenterName=vcenter.somedmain.whatever 
    set psCmd="&{Add-PSSnapin VMware.VimAutomation.Core; Connect-VIServer -server %%vCenterName%% -User %userName% -Password %passWord%; $vmServer = Get-VM %2;Write-Host ($vmServer.PowerState -eq 'PoweredOn')}" 

    call :RunPS %psCmd% RetValue 
    if "%RetValue%" EQU "True" (set "%1=Up") else (set "%1=Down") 
Goto:eof 

:: A function that would execute powershell script and return a value from it. 
:: <PassPSCMD> pass the powreshell command, notice that you need to add any returning value witth Write-Host 
:: <RetValue> the returned value 
:RunPS <PassPSCMD> <RetValue> 
    Powershell Set-ExecutionPolicy RemoteSigned -Force 
    for /F "usebackq tokens=1" %%i in (`Powershell %1`) do set returnValue=%%i 
    set "%2=%returnValue%" 
    Goto:eof 
:: End of :RunPS function 

Ahora, cómo utilizar: función CheckMachineUpOrDown?

solo sigue este ejemplo:

set Workstation=MyVMName 
call :CheckMachineUpOrDown VMStatus %Workstation% 
echo %VMStatus% 

Esto mostrará arriba si la máquina virtual está encendido o hacia abajo si la máquina está apagada.

Espero que esto sea útil.

Gracias

Cuestiones relacionadas