Hey PowerShell gurus – I’ve got a strange one for you. 

In the process of creating and running commands programatically, I’ve hit a very frustrating scenario.  I’m attempting to invoke new-item by creating an instance of a Command with parameters specified in the Parameters collection:

1 string command = "new-item"; 2 var inputs = new Dictionary<string, object>() 3 { 4 {"Value", value.ToString()}, 5 {"Path", "function:" + functionName} 6 }; 7 var cmd = new Command(command, true); 8 inputs.ToList().ForEach( 9 pair => cmd.Parameters.Add( 10 pair.Key, pair.Value 11 ) 12 ); 13 14 var pipe = _runspace.CreatePipeline(); 15 pipe.Commands.Add(cmd); 16 pipe.Invoke();

In this case I’m attempting to create a function.  When I invoke this pipeline, I expect the Path and Value command parameters I’ve specified to be used to resolve the required fields of the new-item cmdlet.

Instead, PowerShell prompts me for the Path parameter:

cmdlet New-Item at command pipeline position 1
Supply values for the following parameters:
Path:

If I specify a valid path value at this prompt, PowerShell raises an error that the Value parameter is null.  So it seems clear that I’m missing something in the way I’m using the Command.Parameters collection.

A few other insights:

  1. I’ve verified in the debugger that the pipeline contains the command, and that the command’s Parameters collection contains the Value and Path parameters.
  2. Specifying the parameters as part of the command string works; however I do not want to be limited to passing strings around.
  3. I’ve tried prepending the parameter names with a hyphen (-), doesn’t appear to make a difference.

Any idears out there?

UPDATE 12.14.2010

Many thanks to Oisin Grehan; he helped me solve the problem, albeit indirectly.  Another blog post is coming on that one.

The named parameters are used as expected when the isScript parameter of the Command constructor is false:

1 string command = "new-item"; 2 var inputs = new Dictionary<string, object>() 3 { 4 {"Value", value.ToString()}, 5 {"Path", "function:" + functionName} 6 }; 7 8 // set isScript to false to use parameters 9 var cmd = new Command(command, false); 10 11 inputs.ToList().ForEach( 12 pair => cmd.Parameters.Add( 13 pair.Key, pair.Value 14 ) 15 ); 16 17 var pipe = _runspace.CreatePipeline(); 18 pipe.Commands.Add(cmd); 19 pipe.Invoke();