116 votes

Exécuter le script PowerShell à partir de C# avec des arguments de ligne de commande

Je dois exécuter un script PowerShell à partir de C#. Le script a besoin d'arguments de ligne de commande.

Voici ce que j'ai fait jusqu'à présent :

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 contient quelque chose comme " C:\Program Fichiers \MyProgram\Whatever.ps1 ".

Le script utilise un argument de ligne de commande tel que "-key Value" alors que Value peut être quelque chose comme un chemin qui peut aussi contenir des espaces.

Je n'arrive pas à le faire fonctionner. Quelqu'un sait-il comment passer des arguments de ligne de commande à un script PowerShell depuis C# et s'assurer que les espaces ne posent pas de problème ?

1 votes

Juste pour clarifier pour les futurs utilisateurs, la réponse acceptée résout le problème pour les personnes ayant des problèmes avec les espaces même sans les paramètres d'utilisation. Utilisation : Command myCommand = new Command(scriptfile); et ensuite pipeline.Commands.Add(myCommand); résoudre le problème de l'échappement.

120voto

Kosi2801 Points 9487

Essayez de créer scriptfile comme une commande séparée :

Command myCommand = new Command(scriptfile);

vous pouvez alors ajouter des paramètres avec

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

et enfin

pipeline.Commands.Add(myCommand);

Voici le code complet, édité :

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();

0 votes

Je semble toujours avoir le problème que si la valeur est quelque chose comme c : \program fichiers \myprogram la clé est fixée à c : \program. :(

2 votes

Ne vous inquiétez pas. Parfois, il est utile de savoir comment diviser correctement les chaînes de caractères ;-) Merci encore, votre solution m'a aidé à résoudre mon problème !

0 votes

@Tronex - vous devriez définir la clé comme étant un paramètre pour votre script. PowerShell possède d'excellents outils intégrés pour travailler avec les chemins. Vous pouvez peut-être poser une autre question à ce sujet. @Kosi2801 a la bonne réponse pour l'ajout de paramètres.

44voto

Jowen Points 1307

J'ai une autre solution. Je veux juste tester si l'exécution d'un script powershell réussit, car peut-être quelqu'un pourrait changer la politique. Comme argument, je spécifie simplement le chemin du script à exécuter.

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));

Le contenu du script étant :

$someVariable = "StringToBeVerifiedInAUnitTest"
$someVariable

2 votes

Bonjour. Avez-vous une idée de la raison pour laquelle le lancement de powershell comme vous l'avez décrit et l'exécution de toutes les commandes du processus (dans notre cas) ne se termine pas ?

0 votes

Quelle bibliothèque utilisez-vous ?

11voto

twalker Points 41

Y a-t-il une chance que je puisse obtenir plus de clarté sur le passage des paramètres à la méthode Commands.AddScript ?

C:\Foo1.PS1 Bonjour la faim dans le monde C:\Foo2.PS1 Bonjour le monde

scriptFile = " C:\Foo1.PS1 "

parameters = "parm1 parm2 parm3" ... longueur variable des paramètres

Résolution de ce problème ... en passant null comme nom et le paramètre comme valeur dans une collection de CommandParameters.

voici ma fonction :

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();
}

0 votes

Je viens de l'ajouter : using (Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration))...usi‌​ng (Pipeline pipeline = runspace.CreatePipeline())

0 votes

Lorsque je passe plusieurs paramètres, l'erreur suivante se produit : Une exception non gérée de type 'System.Management.Automation.ParseException' s'est produite dans System.Management.Automation.dll.

5voto

James Pogran Points 1764

Vous pouvez aussi simplement utiliser le pipeline avec la méthode 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;

Elle prendra une chaîne de caractères, et les paramètres que vous lui passerez.

3voto

Ruud Points 20

Voici une manière d'ajouter des paramètres au script si vous avez utilisé

pipeline.Commands.AddScript(Script);

Il s'agit d'utiliser un HashMap comme paramètres, la clé étant le nom de la variable dans le script et la valeur étant la valeur de la variable.

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

Et la méthode de la variable de remplissage est :

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 cette façon, vous pouvez facilement ajouter plusieurs paramètres à un script. J'ai aussi remarqué que si vous voulez obtenir une valeur d'une variable dans votre script comme ceci :

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

//résultat étant le nom de la v

tu devras le faire de la manière que j'ai montrée parce que pour une raison quelconque si tu le fais de la manière que Kosi2801 suggère la liste de variables script ne se remplit pas avec vos propres variables.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X