Ejecute el script de PowerShell desde C# con argumentos de línea de comandos

Resuelto Mephisztoe asked hace 15 años • 9 respuestas

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?

Mephisztoe avatar Feb 09 '09 16:02 Mephisztoe
Aceptado

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();
Kosi2801 avatar Feb 09 '2009 10:02 Kosi2801

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
Jowen avatar Dec 23 '2010 16:12 Jowen

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 nullel 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();
}
twalker avatar Dec 10 '2009 21:12 twalker

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.

Andrew Chaa avatar Jul 09 '2014 13:07 Andrew Chaa

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.

James Pogran avatar Feb 09 '2009 22:02 James Pogran