Ejecute el script de PowerShell desde C# con argumentos de línea de comandos
Necesito ejecutar un script de PowerShell desde C#. El script necesita argumentos de línea de comando.
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 como "C:\Program Files\MyProgram\Whatever.ps1".
El script utiliza un argumento de línea de comando como "-key Value", mientras que Value puede ser algo así como una ruta que también puede contener espacios.
No consigo 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 un archivo de script 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();
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. Sólo quiero probar si la ejecución de un script de PowerShell tiene éxito, porque tal vez alguien pueda cambiar la política. Como argumento, simplemente especifico la ruta del script que se ejecutará.
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));
Siendo el contenido del guión:
$someVariable = "StringToBeVerifiedInAUnitTest"
$someVariable
Tuve problemas para pasar parámetros al método Commands.AddScript.
C:\Foo1.PS1 Hello World Hunger
C:\Foo2.PS1 Hello World
scriptFile = "C:\Foo1.PS1"
parameters = "parm1 parm2 parm3" ... variable length of params
Resolví esto pasando null
el nombre y el parámetro como valor a una colección deCommandParameters
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<CommandParameter> commandParameters = new Collection<CommandParameter>();
foreach (string scriptParameter in scriptParameters.Split(' '))
{
CommandParameter commandParm = new CommandParameter(null, scriptParameter);
commandParameters.Add(commandParm);
scriptCommand.Parameters.Add(commandParm);
}
pipeline.Commands.Add(scriptCommand);
Collection<PSObject> psObjects;
psObjects = pipeline.Invoke();
}
Para mí, la forma más flexible de ejecutar el script de PowerShell desde C# era usarPowerShell.Create().AddScript()
Primero deberá instalar el paquete nuget Microsoft.PowerShell.SDK . O si apunta a .net framework necesitará Microsoft.PowerShell.5.ReferenceAssemblies
El fragmento del código es
using System.Management.Automation;
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<User>();
foreach (var errorRecord in _powershell.Streams.Error)
Console.WriteLine(errorRecord);
Puede comprobar si hay algún error marcando Streams.Error. Fue muy útil comprobar la colección. Usuario es el tipo de objeto que devuelve el script de PowerShell.
También puedes usar la canalización con el método AddScript:
string cmdArg = ".\script.ps1 -foo bar"
Collection<PSObject> 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 cualquier parámetro que le pase.