Hola comunidad de pila :)
Tengo un objetivo simple. Me gustaría iniciar un script de PowerShell desde otro script de Powershell, pero hay 3 condiciones:
- Tengo que pasar las credenciales (la ejecución se conecta a una base de datos que tiene un usuario específico)
- Tiene que tomar algunos parámetros
- Me gustaría pasar la salida a una variable
Hay una pregunta similar Enlace . Pero la respuesta es usar archivos como una forma de comunicarse entre 2 secuencias de comandos PS. Solo me gustaría evitar conflictos de acceso. @Update: el script principal va a iniciar algunos otros scripts. Por lo tanto, la solución con archivos puede ser complicada si la ejecución se realiza desde varios usuarios al mismo tiempo.
Script1.ps1 es el script que debe tener una cadena como salida. (Para ser claros, es un guión ficticio, el real tiene 150 filas, así que solo quería dar un ejemplo)
param(
[String]$DeviceName
)
#Some code that needs special credentials
$a = "Device is: " + $DeviceName
$a
ExecuteScripts.ps1 debería invocar a aquel con las 3 condiciones mencionadas anteriormente
Intenté múltiples soluciones. Este por ejemplo:
$arguments = "C:\..\script1.ps1" + " -ClientName" + $DeviceName
$output = Start-Process powershell -ArgumentList $arguments -Credential $credentials
$output
No obtengo ningún resultado de eso y no puedo simplemente llamar al script con
&C:\..\script1.ps1 -ClientName PCPC
Porque no puedo pasarle -Credential
parámetros ...
¡Gracias de antemano!
fuente
Respuestas:
Nota:
La siguiente solución funciona con cualquier programa externo y captura la salida invariablemente como texto .
Para invocar otra instancia de PowerShell y capturar su salida como objetos enriquecidos (con limitaciones), vea la solución variante en la sección inferior o considere la útil respuesta de Mathias R. Jessen , que usa el SDK de PowerShell .
Aquí hay una prueba de concepto basada en el uso directo de los tipos
System.Diagnostics.Process
ySystem.Diagnostics.ProcessStartInfo
.NET para capturar la salida del proceso en la memoria (como se indicó en su pregunta,Start-Process
no es una opción, ya que solo admite la captura de salida en archivos , como se muestra en esta respuesta ) :Nota:
Debido a que se ejecuta como un usuario diferente, esto solo es compatible con Windows (a partir de .NET Core 3.1), pero en ambas ediciones de PowerShell.
Debido a la necesidad de ejecutarse como un usuario diferente y la necesidad de capturar la salida,
.WindowStyle
no se puede utilizar para ejecutar el comando oculto (porque el uso.WindowStyle
debe.UseShellExecute
ser$true
, lo que es incompatible con estos requisitos); sin embargo, ya está siendo toda la salida capturado , el establecimiento.CreateNoNewWindow
de$true
resultados de eficacia en la ejecución oculto.Lo anterior produce algo como lo siguiente, mostrando que el proceso se ejecutó con éxito con la identidad de usuario dada:
Como está llamando a otra instancia de PowerShell , es posible que desee aprovechar la capacidad de PowerShell CLI para representar la salida en formato CLIXML, que permite deserializar la salida en objetos ricos , aunque con una fidelidad de tipo limitada , como se explica en esta respuesta relacionada .
Lo anterior genera algo como lo siguiente, mostrando que la salida de
[datetime]
instancia (System.DateTime
)Get-Date
fue deserializada como tal:fuente
Start-Process
sería mi último recurso para invocar PowerShell desde PowerShell, especialmente porque todas las E / S se convierten en cadenas y no en objetos (deserializados).Dos alternativas:
1. Si el usuario es un administrador local y PSRemoting está configurado
Si una sesión remota contra la máquina local (desafortunadamente restringida a administradores locales) es una opción, definitivamente elegiría
Invoke-Command
:$strings
contendrá los resultados.2. Si el usuario no es administrador en el sistema de destino
Puede escribir su propio "solo local
Invoke-Command
" girando un espacio de ejecución fuera de proceso de la siguiente manera:PowerShellProcessInstance
, bajo un inicio de sesión diferenteReuní dicha función a continuación, vea los comentarios en línea para un recorrido:
Luego use así:
fuente
rcv.ps1
ejecución desde otro script:
salida:
fuente
Lo que puede hacer es lo siguiente para pasar un parámetro a un script ps1.
El primer script puede ser origin.ps1 donde escribimos:
El script de destino dest.ps1 puede tener el siguiente código para capturar las variables
Y el resultado será
fuente
-Credential $credentials
parámetros a esta ejecución y obtener resultados de él en una variable. La ps1. La secuencia de comandos que estoy ejecutando es arrojar una cadena de palabra singe al final. Solo mira la forma en que lo hiceStart-process
pero esta función no genera salida$output
variable, es NULL. La otra idea que surgió de @ mklement0 es guardar la salida en un archivo. Pero en mi caso causará una gran cantidad de archivos en un solo lugar. Todo creado a partir de diferentes usuarios con diferentes scripts