5

I'm trying to call a function in a powershell file as follows:

    string script = System.IO.File.ReadAllText(@"C:\Users\Bob\Desktop\CallPS.ps1");

    using (Runspace runspace = RunspaceFactory.CreateRunspace())
    {
        runspace.Open();
        using (Pipeline pipeline = runspace.CreatePipeline(script))
        {
            Command c = new Command("BatAvg",false); 
            c.Parameters.Add("Name", "John"); 
            c.Parameters.Add("Runs", "6996"); 
            c.Parameters.Add("Outs", "70"); 
            pipeline.Commands.Add(c); 

            Collection<PSObject> results = pipeline.Invoke();
            foreach (PSObject obj in results)
            {
                // do somethingConsole.WriteLine(obj.ToString());
            }
        }
    }

The powershell function is in CallPS.ps1:

Function BatAvg
{
    param ($Name, $Runs, $Outs)
    $Avg = [int]($Runs / $Outs*100)/100 
    Write-Output "$Name's Average = $Avg, $Runs, $Outs "
}

I'm getting the following exception:

The term 'BatAvg' is not recognized as the name of a cmdlet, function, script file, or operable program.

What am I doing wrong, I admit, I know very little about PowerShell.

user577240
  • 460
  • 1
  • 7
  • 14

3 Answers3

8

This seems to work for me:

using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
    runspace.Open();
    PowerShell ps = PowerShell.Create();
    ps.Runspace = runspace;
    ps.AddScript(script);
    ps.Invoke();
    ps.AddCommand("BatAvg").AddParameters(new Dictionary<string, string>
    {
        {"Name" , "John"},
        {"Runs", "6996"},
        {"Outs","70"}
    });

    foreach (PSObject result in ps.Invoke())
    {
        Console.WriteLine(result);
    }
}
pkuderov
  • 3,501
  • 2
  • 28
  • 46
manojlds
  • 290,304
  • 63
  • 469
  • 417
1

The solution can be simplified further as in this case a non-default Runspace is not needed.

var ps = PowerShell.Create();
ps.AddScript(script);
ps.Invoke();
ps.AddCommand("BatAvg").AddParameters(new Dictionary<string, string>
{
     {"Name" , "John"}, {"Runs", "6996"}, {"Outs","70"}
});
foreach (var result in ps.Invoke())
{
     Console.WriteLine(result);
}

One other pitfall would be to use AddScript(script, true) in order to use a local scope. The same exception would be encountered (i.e. "The term 'BatAvg' is not recognized as the name of a cmdlet, function, script file, or operable program.").

1

As it seems the Runspace need to be connected to a Powershell to make that work - see the sample code at MSDN.

Yahia
  • 69,653
  • 9
  • 115
  • 144
  • Nope, still get the same exception: runspace.Open(); PowerShell ps = PowerShell.Create(); ps.Runspace = runspace; ps.AddScript(script); Command c = new Command("BatAvg",false); ps.AddCommand("BatAvg",false); ps.AddParameter("Name", "John"); ps.AddParameter("Runs", "6996"); ps.AddParameter("Outs", "70"); foreach (PSObject obj in ps.Invoke()) { // do somethingConsole.WriteLine(obj.ToString()); } – user577240 Sep 03 '11 at 17:58