4

I have a large number of commands and would rather not change all of them. So I want to turn command objects into codeblock objects and add their parameters to an invoke so I can later on execute them on another computer.

The end result is the following code: string server=cpu1.com

    public void ExecuteRemote(Command basis) {

        RunspaceInvoke invoke = new RunspaceInvoke();
        Runspace runspace = RunspaceFactory.CreateRunspace();
        runspace.Open();
        Pipeline pipeLine = runspace.CreatePipeline();
        ScriptBlock s=basis.CommandText);//<<<<this does not work, how can I fix this?

        Command invokeScript = new Command("Invoke-Command");

        invokeScript.Parameters.Add("ComputerName", server);
        invokeScript.Parameters.Add("scriptBlock", s);
        invokeScript.Parameters.Join(basis.Parameters); // and this does not work either?

        pipeLine.Commands.Add(invokeScript);
        Collection<PSObject> commandResults = pipeLine.Invoke();
 }

So anybody know how to do this?

The two lines that I marked are not working (don't compile) and I would like to know how I could fix them.

    ScriptBlock s=basis.CommandText);//<<<<this does not work, how can I fix this?

should load the command from basis into the scriptblock so it can later be used for executing the code and

    invokeScript.Parameters.Join(basis.Parameters); // and this does not work either?

Is an attempt to move the parameters from basis into the invokescript.

I have based my answer on Invoke remote powershell command from C# however as I cannot change the parameters for each function (there are a lot of commands to work trough) I would like to just take the command and execute that.

Edit after looking at @Keith hill's answer

Console.WriteLine("creating invoke"); RunspaceInvoke invoke = new RunspaceInvoke();

        Runspace runspace = RunspaceFactory.CreateRunspace();
        runspace.Open();
        Console.WriteLine("creating pipeline");

        Pipeline pipeLine = runspace.CreatePipeline();
        Console.WriteLine("creating scriptblock");
        ScriptBlock s = ScriptBlock.Create(basis.CommandText);
        Command invokeScript = new Command("Invoke-Command");
        Console.WriteLine("adding parameter1");
        invokeScript.Parameters.Add("ComputerName", "test1.com");

        invokeScript.Parameters.Add("scriptBlock", s);

        foreach (var p in basis.Parameters)            {

            invokeScript.Parameters.Add(p.Name, p.Value);
        }

        pipeLine.Commands.Add(invokeScript); Console.WriteLine("res");
        Collection<PSObject> commandResults = pipeLine.Invoke();

I get the error that no parameter could be found by the name "Name" when asked to add the followign command: Command MaakActiveDirectoryOU = new Command("New-ADOrganizationalUnit");

        MaakActiveDirectoryOU.Parameters.Add("Name", KlantNaam);
        MaakActiveDirectoryOU.Parameters.Add("Path", WebConfigurationManager.AppSettings["SharedOU"].ToString());
        ExecuteRemote2(MaakActiveDirectoryOU);

This command works fine when executed locally anybody got a clue?

Thijser
  • 2,625
  • 1
  • 36
  • 71
  • Why the downvote? Care to explain? – Thijser Sep 26 '15 at 19:58
  • And now I'm curious why two people decided to downvote, I think this is a reasonable question? – Thijser Sep 26 '15 at 20:15
  • I don't know either - this is a good question, you're laying out the problems quite clearly, you're showing your own research efforts, and the question is asked quite nicely and in perfect English (no typos, clear language). I upvoted once to at least compensate for one unexplained downvote ..... – marc_s Sep 26 '15 at 20:40
  • first I did not downvote! But I understand the two downvotes because the question is really unclear: yes you write where it fails but not with what error/exception – Random Dev Sep 26 '15 at 20:44
  • Hey at least you didn't ask someone to write your script for you. That's worth an upvote. :-) That said, in the future, it is helpful to see a simple explanation of the error you are seeing e.g. this line would not compile with error blah. Or at runtime, the program throws an InvalidCastException. In the end, it will help you get a better answer, faster. – Keith Hill Sep 26 '15 at 20:48

1 Answers1

4

You can't assign a string to a variable of type ScriptBlock. You need to create the script block using the static create method (Note: the ScriptBlock constructor is protected so you can't use it) e.g.:

var s = ScriptBlock.Create(command.CommandText);

As for adding the parameters, try this:

foreach (var p in basis.Parameters) {
    invokeScript.Parameters.Add(p.Name, p.Value);
}

The Join Linq command combines two sequences but the combined sequence is output as a result of the Join command. It doesn't modify either of the original two sequences.

Keith Hill
  • 194,368
  • 42
  • 353
  • 369