14

From the command line I can do.

.\test.ps1 1

How do I pass the parameter when doing this from C#? I've tried

   .AddArgument(1)
   .AddParameter("p", 1)

And I have tried passing values in as IEnumerable<object> in the .Invoke() but $p does not get the value.

namespace ConsoleApplication1
{
    using System;
    using System.Linq;
    using System.Management.Automation;

    class Program
    {
        static void Main()
        {
            // Contents of ps1 file
            //  param($p)
            //  "Hello World ${p}"

            var script = @".\test.ps1";

            PowerShell
                .Create()
                .AddScript(script)
                .Invoke().ToList()
                .ForEach(Console.WriteLine);
        }
    }
}
4
  • This seems to indicate that .AddParameter("p", 1) should work. Commented Jul 10, 2012 at 2:01
  • Yeah, agreed. So far it doesn't pass through to the script. Commented Jul 10, 2012 at 2:06
  • You've probably found this, where Don Jones uses it and adds a scriptblock parameter Commented Jul 10, 2012 at 2:15
  • Yeah, that's a bit different. If I called test.ps from the cmdline i could do .\test.ps1 (new-object PSObject). I'm trying to figure out how to do that in code. Commented Jul 10, 2012 at 2:22

3 Answers 3

10

How's this?

static void Main()
{
    string script = @"C:\test.ps1 -arg 'hello world!'";
    StringBuilder sb = new StringBuilder();

    PowerShell psExec = PowerShell.Create();
    psExec.AddScript(script);
    psExec.AddCommand("out-string");

    Collection<PSObject> results;
    Collection<ErrorRecord> errors;
    results = psExec.Invoke();
    errors = psExec.Streams.Error.ReadAll();

    if (errors.Count > 0)
    {
        foreach (ErrorRecord error in errors)
        {
            sb.AppendLine(error.ToString());
        }
    }
    else
    {
        foreach (PSObject result in results)
        {
            sb.AppendLine(result.ToString());
        }
    }

    Console.WriteLine(sb.ToString());
}

Here's a similar version that passes an instance of a DateTime

static void Main()
{
    StringBuilder sb = new StringBuilder();

    PowerShell psExec = PowerShell.Create();
    psExec.AddCommand(@"C:\Users\d92495j\Desktop\test.ps1");
    psExec.AddArgument(DateTime.Now);

    Collection<PSObject> results;
    Collection<ErrorRecord> errors;
    results = psExec.Invoke();
    errors = psExec.Streams.Error.ReadAll();

    if (errors.Count > 0)
    {
        foreach (ErrorRecord error in errors)
        {
            sb.AppendLine(error.ToString());
        }
    }
    else
    {
        foreach (PSObject result in results)
        {
            sb.AppendLine(result.ToString());
        }
    }

    Console.WriteLine(sb.ToString());
}
Sign up to request clarification or add additional context in comments.

6 Comments

I'm not seeing how you passed any parameters to a script.
I understand your question now. I've updated my answer to show a script and passing an argument to it. The easiest way I know to do it is to include the arguments in string you pass psExec.AddScript(script)
Wasn't my question, just something I'm interested in and happened to see your answer after it was posted.
That works for strings. What if I want to pass in an instance of class?
Yup, the difference is. I was using AddScript. Your example uses AddCommand. This lets AddParameter be used as well.
|
4

So, to make a long answer short: Use AddCommand instead of AddScript

Comments

3

another way is to fill the runspace with variables.

    public static string RunPs1File(string filePath, Dictionary<string, object> arguments)
    {
        var result = new StringBuilder();

        using (Runspace space = RunspaceFactory.CreateRunspace())
        {
            space.Open();

            foreach (KeyValuePair<string, object> variable in arguments)
            {
                var key = new string(variable.Key.Where(char.IsLetterOrDigit).ToArray());
                space.SessionStateProxy.SetVariable(key, variable.Value);
            }

            string script = System.IO.File.ReadAllText(filePath);
            using (PowerShell ps1 = PowerShell.Create())
            {
                ps1.Runspace = space;
                ps1.AddScript(script);

                var psOutput = ps1.Invoke();

                var errors = ps1.Streams.Error;
                if (errors.Count > 0)
                {
                    var e = errors[0].Exception;
                    ps1.Streams.ClearStreams();
                    throw e;
                }

                foreach (var line in psOutput)
                {
                    if (line != null)
                    {
                        result.AppendLine(line.ToString());
                    }
                }
            }
        }

        return result.ToString();
    }

1 Comment

Actually, the best way to do it!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.