Ejecute la secuencia de comandos de PowerShell desde C # con argumentos de línea de comando

Necesito ejecutar un script de PowerShell desde C #. La secuencia de comandos necesita argumentos de línea de comandos.

Esto es lo que he hecho hasta ahora:

RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create(); Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration); runspace.Open(); RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace); Pipeline pipeline = runspace.CreatePipeline(); pipeline.Commands.Add(scriptFile); // Execute PowerShell script results = pipeline.Invoke(); 

scriptFile contiene algo así como “C: \ Program Files \ MyProgram \ Whatever.ps1”.

La secuencia de comandos utiliza un argumento de la línea de comandos como “-key Value”, mientras que Value puede ser algo así como una ruta que también puede contener espacios.

No logro que esto funcione. ¿Alguien sabe cómo pasar argumentos de línea de comandos a un script de PowerShell desde C # y asegurarse de que los espacios no sean un problema?

Intente crear archivos de comandos como un comando separado:

 Command myCommand = new Command(scriptfile); 

entonces puedes agregar parámetros con

 CommandParameter testParam = new CommandParameter("key","value"); myCommand.Parameters.Add(testParam); 

y finalmente

 pipeline.Commands.Add(myCommand); 

Aquí está el código completo y editado:

 RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create(); Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration); runspace.Open(); RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace); Pipeline pipeline = runspace.CreatePipeline(); //Here's how you add a new script with arguments Command myCommand = new Command(scriptfile); CommandParameter testParam = new CommandParameter("key","value"); myCommand.Parameters.Add(testParam); pipeline.Commands.Add(myCommand); // Execute PowerShell script results = pipeline.Invoke(); 

Tengo otra solución. Solo quiero probar si la ejecución de un script de PowerShell es exitosa, porque tal vez alguien podría cambiar la política. Como argumento, solo especifico la ruta del script para ser ejecutado.

 ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = @"powershell.exe"; startInfo.Arguments = @"& 'c:\Scripts\test.ps1'"; startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardError = true; startInfo.UseShellExecute = false; startInfo.CreateNoWindow = true; Process process = new Process(); process.StartInfo = startInfo; process.Start(); string output = process.StandardOutput.ReadToEnd(); Assert.IsTrue(output.Contains("StringToBeVerifiedInAUnitTest")); string errors = process.StandardError.ReadToEnd(); Assert.IsTrue(string.IsNullOrEmpty(errors)); 

Con los contenidos del script siendo:

 $someVariable = "StringToBeVerifiedInAUnitTest" $someVariable 

¿Hay alguna posibilidad de que tenga más claridad sobre los parámetros para pasar al método Commands.AddScript?

C: \ Foo1.PS1 Hello World Hunger C: \ Foo2.PS1 Hello World

scriptFile = “C: \ Foo1.PS1”

parameters = “parm1 parm2 parm3” … longitud variable de params

Resolvió esto … pasando null como el nombre y el param como valor en una colección de CommandParameters

Aquí está mi función:

 private static void RunPowershellScript(string scriptFile, string scriptParameters) { RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create(); Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration); runspace.Open(); RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace); Pipeline pipeline = runspace.CreatePipeline(); Command scriptCommand = new Command(scriptFile); Collection commandParameters = new Collection(); foreach (string scriptParameter in scriptParameters.Split(' ')) { CommandParameter commandParm = new CommandParameter(null, scriptParameter); commandParameters.Add(commandParm); scriptCommand.Parameters.Add(commandParm); } pipeline.Commands.Add(scriptCommand); Collection psObjects; psObjects = pipeline.Invoke(); } 

También puede usar la tubería con el método AddScript:

 string cmdArg = ".\script.ps1 -foo bar" Collection psresults; using (Pipeline pipeline = _runspace.CreatePipeline()) { pipeline.Commands.AddScript(cmdArg); pipeline.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output); psresults = pipeline.Invoke(); } return psresults; 

Tomará una cadena y los parámetros que pases.

Aquí hay una manera de agregar Parámetros al script si usó

 pipeline.Commands.AddScript(Script); 

Esto es mediante el uso de un HashMap como parámetros, siendo la clave el nombre de la variable en el script y el valor es el valor de la variable.

 pipeline.Commands.AddScript(script)); FillVariables(pipeline, scriptParameter); Collection results = pipeline.Invoke(); 

Y el método de la variable de relleno es:

 private static void FillVariables(Pipeline pipeline, Hashtable scriptParameters) { // Add additional variables to PowerShell if (scriptParameters != null) { foreach (DictionaryEntry entry in scriptParameters) { CommandParameter Param = new CommandParameter(entry.Key as String, entry.Value); pipeline.Commands[0].Parameters.Add(Param); } } } 

De esta forma, puede agregar fácilmente múltiples parámetros a un script. También he notado que si quieres obtener un valor de una variable en tu script, hazlo de la siguiente manera:

 Object resultcollection = runspace.SessionStateProxy.GetVariable("results"); 

// resultados siendo el nombre de la v

Tendrás que hacerlo de la forma en que lo hice porque, por alguna razón, si lo haces como Kosi2801 sugiere, la lista de variables del script no se llena con tus propias variables.

El mío es un poco más pequeño y simple:

 ///  /// Runs a PowerShell script taking it's path and parameters. ///  /// The full file path for the .ps1 file. /// The parameters for the script, can be null. /// The output from the PowerShell execution. public static ICollection RunScript(string scriptFullPath, ICollection parameters = null) { var runspace = RunspaceFactory.CreateRunspace(); runspace.Open(); var pipeline = runspace.CreatePipeline(); var cmd = new Command(scriptFullPath); if (parameters != null) { foreach (var p in parameters) { cmd.Parameters.Add(p); } } pipeline.Commands.Add(cmd); var results = pipeline.Invoke(); pipeline.Dispose(); runspace.Dispose(); return results; } 

Para mí, la forma más flexible de ejecutar el script de PowerShell desde C # era usar PowerShell.Create (). AddScript ()

El fragmento del código es

 string scriptDirectory = Path.GetDirectoryName( ConfigurationManager.AppSettings["PathToTechOpsTooling"]); var script = "Set-Location " + scriptDirectory + Environment.NewLine + "Import-Module .\\script.psd1" + Environment.NewLine + "$data = Import-Csv -Path " + tempCsvFile + " -Encoding UTF8" + Environment.NewLine + "New-Registration -server " + dbServer + " -DBName " + dbName + " -Username \"" + user.Username + "\" + -Users $userData"; _powershell = PowerShell.Create().AddScript(script); _powershell.Invoke(); foreach (var errorRecord in _powershell.Streams.Error) Console.WriteLine(errorRecord); 

Puede verificar si hay algún error al verificar Streams.Error. Fue realmente útil para verificar la colección. El usuario es el tipo de objeto que devuelve el script de PowerShell.