C# passing an array to a powershell script - c#

I'm attempting to run a powershell script from C#. I have no problem passing strings to the script however when I try to pass an array to the powershell script an exception gets thrown.
Here is the C# code:
string [] test = {"1","2","3","4"};
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.ApartmentState = System.Threading.ApartmentState.STA;
runspace.ThreadOptions = PSThreadOptions.UseCurrentThread;
runspace.Open();
RunspaceInvoke invoker = new RunspaceInvoke();
invoker.Invoke("Set-ExecutionPolicy Unrestricted");
Pipeline pipeline = runspace.CreatePipeline();
Command myCmd = new Command(#"C:\test.ps1");
CommandParameter param = new CommandParameter("responseCollection", test);
myCmd.Parameters.Add(param);
pipeline.Commands.Add(myCmd);
// Execute PowerShell script
Collection<PSObject> results = pipeline.Invoke();
Here is the powershell script:
param([string[]] $reponseCollection)
$a = $responseCollection[0]
Every time this code executes it throws:
Cannot index into a null array.
I know that the code to execute the powershell script is correct when passing strings to the powershell script, it has been thoroughly tested.

It works perfectly fine for me.
Only thing I notice is that, in your script params you have $reponseCollection - the s is missing in response. Unless you made a mistake in entering it here, that would be the reason.
It might have seemed to work with string because Powershell doesn't care ( normally) when you assign / use a non-existing variable. But when you index into a null / non-existing variable, it does throw the error.

I think that you need to pass the array to powershell as a string in powershell array format, i.e.,
string test = "('1','2','3','4')";

Related

How to execute a powershell script using c# and setting execution policy?

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.
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.

How to create powershell script dynamically from c# based on input params without having physical script file in machine

I know we can can run physical powershell script from c# but how to create powershell script file itself dynamically based on input params.
Kindly suggest.
you can execute powershell script/ commands directly from your c# project.
you'll need to add a reference to system.managment.automation dll in project's references.
example:
function that will take script as a string , execute it and then returns a result:
private string RunScript(string script)
{
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipline = runspace.CreatePipeline();
pipline.Commands.AddScript(script);
pipline.Commands.Add("Out-String");
Collection<PSObject> results = pipline.Invoke();
runspace.Close();
StringBuilder stringBuilder = new StringBuilder();
foreach(PSObject pSObject in results)
{
stringBuilder.AppendLine(pSObject.ToString());
}
return stringBuilder.ToString();
}
function call be like:
Console.WriteLine(RunScript("Your Powershell Script"));
you can check out the full code examples on github - PowershellCommand-CSharp

C# - Utilize Quest active directory cmdlets for Powershell by calling PS script

C# code (Source):
private string RunScript(string scriptText)
{
// create Powershell runspace
Runspace runspace = RunspaceFactory.CreateRunspace();
// open it
runspace.Open();
// create a pipeline and feed it the script text
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
// add an extra command to transform the script
// output objects into nicely formatted strings
// remove this line to get the actual objects
// that the script returns. For example, the script
// "Get-Process" returns a collection
// of System.Diagnostics.Process instances.
pipeline.Commands.Add("Out-String");
// execute the script
Collection<psobject /> results = pipeline.Invoke();
// close the runspace
runspace.Close();
// convert the script result into a single string
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
stringBuilder.AppendLine(obj.ToString());
}
return stringBuilder.ToString();
}
Powershell code
#Dummy code for example purpose
ASNP Quest*
#Example of cmdlet I want to use
$Users = Get-QADGroupMember -Identity $Group -Enabled
return $Users.count
As you can see, my goal is to call the script utilizing RunScript above in a Button_Click event in my WPF app. I've been able to correctly call the script but the call to Quest cmdlets clearly doesn't go trough as wanted since I would receive 0 in the above example.
TL;DR
Script is running correctly but calls to Quest cmdlets don't work since it return nothing (or 0 in the above example). Is there something I'm missing ?
EDIT
Important to note that the exact same script ran in Powershell returns the correct values. Calling it from C# don't.

Run Powershell from C#

I need to start a powershell script from C# and get the PSSSecurityException on pipeline.Invoke()
AuthorizationManager check failed.
My code:
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
using (Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration))
{
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
Command scriptCommand = new Command(scriptfile);
pipeline.Commands.Add(scriptCommand);
pipeline.Invoke();
}
Questions
I suspect that I need to set PSCredential. But I can not promt for it, so I have to handle this in code. Can this be done in a secure way? (This was not the case)
Check out this SuperUser post: https://superuser.com/questions/106360/how-to-enable-execution-of-powershell-scripts
You probably just need to allow unsigned scripts to run. In the PS console, type the following:
set-executionpolicy remotesigned
Another resource echoes this: http://tgnp.me/2011/09/powershell-authorizationmanager-check-failed-resolution/
Give that a try and let me know what happens.
To capture the output from the script, try this:
Collection output = pipeline.Invoke();
foreach (PSObject psObject in output)
{
<here you can ToString the psObject for the output and write it line by line to your log>
}
The problem was that the script was placed on a share. To run scripts on this share I needed to add the share to Trusted Sites.

Powershell command through C# code

I want to add through C# code Powershell command or script (what is correct?) variable declaration with default value stored in C# variable.
For example, in Powershell I typing following line
$user = 'Admin'
I want to add this line in C# code.
powershell.AddScript(String.Format("$user = \"{0}\"", userName));
or
powershell.AddCommand(String.Format("$user = \"{0}\"", userName));
I try with AddCommand() but it throws exception. I use PS 2.0.
According to this article How to run PowerShell scripts from C#, you will need something like this:
// create Powershell runspace
Runspace runspace = RunspaceFactory.CreateRunspace();
// open it
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(String.Format("$user = \"{0}\"", userName));
pipeline.Commands.AddScript("#your main script");
// execute the script
Collection<psobject> results = pipeline.Invoke();
// close the runspace
runspace.Close();
Also see Run Powershell-Script from C# Application question here on Stackoverflow.

Categories