3

I tried to combine two answers from stackoverflow (first & second)

InitialSessionState iss = InitialSessionState.CreateDefault();
// Override ExecutionPolicy

PropertyInfo execPolProp = iss.GetType().GetProperty(@"ExecutionPolicy");
if (execPolProp != null && execPolProp.CanWrite)
{
    execPolProp.SetValue(iss, ExecutionPolicy.Bypass, null);
}
Runspace runspace = RunspaceFactory.CreateRunspace(iss);
runspace.Open();

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

In my powershell script I have the following parameter:

Param(
[String]$key
)

However, when I execute this, then I get the following exception:

System.Management.Automation.CmdletInvocationException: Cannot validate argument on parameter 'Session'. 
The argument is null or empty. 
Provide an argument that is not null or empty, and then try the command again.
mklement0
  • 382,024
  • 64
  • 607
  • 775
3r1c
  • 376
  • 5
  • 20

1 Answers1

5

Without knowing what your specific problem was, note that your C# code can be greatly streamlined, which may also resolve your problem:

  • There is no need to resort to reflection in order to set a session's execution policy.

  • Using an instance of the PowerShell class greatly simplifies command invocation.

// Create an initial default session state.
var iss = InitialSessionState.CreateDefault2();
// Set its script-file execution policy (for the current session only).
iss.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Bypass;

// Create a PowerShell instance with a runspace based on the 
// initial session state.
PowerShell ps = PowerShell.Create(iss);

// Add the command (script-file call) and its parameters, then invoke.
var results =
  ps
   .AddCommand(scriptfile)
   .AddParameter("key", "value")
   .Invoke();

Note: The .Invoke() method only throws an exception if a terminating error occurred during execution of the PowerShell script. The more typical non-terminating errors are instead reported via .Streams.Error.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • This is interesting. So, in C# you don't have to mark a line continuation like you would in PowerShell (i.e. : the backtick ( ` ) )? – Abraham Zinala Aug 26 '21 at 18:15
  • 2
    @AbrahamZinala: There is no line-continuation char. in C#, because the logic is reversed: a statement, irrespective of how many lines it spans, is only terminated by `;` In PowerShell, which doesn't require explicit statement termination, you can _situationally_ get away without a line-ending backtick, namely when the statement is unambiguously _incomplete_, notably after a line-ending `|` and, similarly, but not identically, to the `ps` example above: a line-ending `.` - that is, the `.` must be at the _end_ of the line for PowerShell to know that the statement continues. – mklement0 Aug 26 '21 at 18:57
  • 3
    @AbrahamZinala: As an explicit exception, _PowerShell (Core) 7+_ now allows you to place a `|` on the _next_ line in order to continue a pipeline. That is, while Windows PowerShell only supports, e.g. `Get-Date | Format-List`, PowerShell (Core) 7+ now also supports `Get-Date| Format-List`, albeit only in _scripts_, because _interactively_ `Get-Date` would execute by itself before you get a chance to continue the statement (except inside `{ ... }`). – mklement0 Aug 26 '21 at 19:03