Is it possible to execute PowerShell script inside c# the same way PowerShell is able to run vb/macro script inside PowerShell like so:
$script = #' (vb script) '
$excel.Run('Script', 'arg1', 'arg2', ...)
This can be seen as a duplicate of this stackoverflow discussion(s)
Execute PowerShell Script from C# with Commandline Arguments
To call a powershell script file (example.ps1) from C#
Try creating scriptfile as a separate command:
Command myCommand = new Command(scriptfile);
then you can add parameters with
CommandParameter testParam = new CommandParameter("key","value");
myCommand.Parameters.Add(testParam);
and finally
pipeline.Commands.Add(myCommand);
Here is the complete, edited code:
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
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();
Related
I need to execute a powershell script from my asp.net MVC Web application. My requirement is to create site collections dynamically. I have the script for it and it works perfectly.There are no arguments which are to be passed to the script. The code which I have been using has been displayed below:
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
Pipeline pipeline = runspace.CreatePipeline();
//Here's how you add a new script with arguments
Command myCommand = new Command(scriptfiellocation);
pipeline.Commands.Add(myCommand);
pipeline.Commands.Add("Out-String");
// Execute PowerShell script
var result = pipeline.Invoke();
On executing the code, when I check the count of variable result it gives the count as 1. However on checking my site, there is no site collection that has been created. I am not able to identify where I am going wrong as there is no run time error and the Invoke command also seems to be running properly.
Could anyone tell me where I might be going haywire ? Considering that the PowerShell script works perfectly when running through Management shell.
I had to forego the pipeline approach as I was not able to figure out what the issue was. Also another problem with that approach is that it threw the error: "Get-SPWbTemplate is not recognized as an cmdlet". The following code worked perfectly fine for me and created the required site collections:
PowerShell powershell = PowerShell.Create();
//RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
//Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration)
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
//RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
//scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted");
powershell.Runspace = runspace;
//powershell.Commands.AddScript("Add-PsSnapin Microsoft.SharePoint.PowerShell");
System.IO.StreamReader sr = new System.IO.StreamReader(scriptfilepath);
powershell.AddScript(sr.ReadToEnd());
//powershell.AddCommand("Out-String");
var results = powershell.Invoke();
if (powershell.Streams.Error.Count > 0)
{
// error records were written to the error stream.
// do something with the items found.
}
}
Also there was no requirement to set the execution policy.
well don't know if its help but i never use pipeline to run Command shell not sure how that work.
But here a quick example
Runspace RS = RunspaceFactory.CreateRunspace(myConnection);
PowerShell PS = PowerShell.Create();
PSCommand PScmd = new PSCommand();
string cmdStr = "Enable-Mailbox -Identity " + username + " -Database DB01 -Alias " + aliasexample;
PScmd.AddScript(cmdStr);
try
{
RS.Open();
PS.Runspace = RS;
PS.Commands = PScmd;
PS.Invoke();
}
catch (Exception ex)
{
ex.ToString();
}
finally
{
RS.Dispose();
RS = null;
PS.Dispose();
PS = null;
}
with the try catch you can catch the error with debugging if something goes wrong.
If i remember correctly i had to put ACL.exe for permission to file system so i can execute the commandshell you can do a quick search on google for it.
Hope this help.
How can I get the powershell variable $test from a c# application?
I tried it like this:
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
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");
CommandParameter testParam2 = new CommandParameter("key", "value");
CommandParameter testParam3 = new CommandParameter("key", "value");
myCommand.Parameters.Add(testParam);
myCommand.Parameters.Add(testParam2);
myCommand.Parameters.Add(testParam3);
pipeline.Commands.Add(myCommand);
// Execute PowerShell script
var results = pipeline.Invoke();
var resultVariable = runspace.SessionStateProxy.PSVariable.GetValue("test");
resultVariable is null. But I filled it in powershell with an int (i.e. $test = 4).
Use $global:test=4 in script or run script in same scope. By default script run in its own scope, so any variable changed in script does not visible outside.
I am trying to use C# to disable ActiveSync mailboxes on Exchange Server 2007 (and soon to be 2013 which is probably completely different) using powershell. The first command works to set the Allowed Device IDs. The second to turn off activesync does not. Am I specifying it incorrectly?
RunspaceConfiguration runspaceConf = RunspaceConfiguration.Create();
PSSnapInException PSException = null;
PSSnapInInfo info = runspaceConf.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.Admin", out PSException);
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConf);
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
Command command = new Command("Set-CASMailbox");
command.Parameters.Add("Identity", username);
command.Parameters.Add("ActiveSyncAllowedDeviceIDs", "\"BLOCKED\"");
pipeline.Commands.Add(command);
command = new Command("Set-CASMailbox");
command.Parameters.Add("Identity", username);
command.Parameters.Add("ActiveSyncEnabled", false);
pipeline.Commands.Add(command);
Collection<PSObject> result = pipeline.Invoke();
I don't have much experience with C# and PowerShell or the Exchange PS cmdlets for that matter, so I might be wrong here.
AFAIK your sample would equal:
Set-CASMailbox -Identity 'User1' -ActiveSyncAllowedDeviceIDs "BLOCKED" | Set-CASMailbox -Identity 'User1' -ActiveSyncEnabled $false
You're not using the object (if any) that the first cmdlet returns, so they don't belong in a pipeline. You should run them separately, like:
Set-CASMailbox -Identity 'User1' -ActiveSyncAllowedDeviceIDs "BLOCKED"
Set-CASMailbox -Identity 'User1' -ActiveSyncEnabled $false
In C# I guess you need to call Invoke() twice.
Pipeline pipeline = runspace.CreatePipeline();
Command command = new Command("Set-CASMailbox");
command.Parameters.Add("Identity", username);
command.Parameters.Add("ActiveSyncAllowedDeviceIDs", "BLOCKED");
pipeline.Commands.Add(command);
//Run first cmdlet
Collection<PSObject> result = pipeline.Invoke();
//Not sure how to reset. Create new pipeline?
Pipeline pipeline2 = runspace.CreatePipeline();
Command command2 = new Command("Set-CASMailbox");
command2.Parameters.Add("Identity", username);
command2.Parameters.Add("ActiveSyncEnabled", false);
pipeline2.Commands.Add(command);
//Run second cmdlet
Collection<PSObject> result2 = pipeline2.Invoke();
I'm writing 2 apps one with c# and the other with powershell 1.0, in some point of my code I want to pass a string that indicating the server name from my c# app to a powershell script file that I wrote, how do I send it? and how do i accept it?
my code :
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
Pipeline pipeline = runspace.CreatePipeline();
String scriptfile = #"c:\test.ps1";
Command myCommand = new Command(scriptfile, false);
CommandParameter testParam = new CommandParameter("username", "serverName");
myCommand.Parameters.Add(testParam);
pipeline.Commands.Add(myCommand);
Collection<PSObject> psObjects;
psObjects = pipeline.Invoke();
runspace.Close();
and my powershell script
param([string]$Username)
write-host $username
What am I missing? I'm kinda new with powershell.
I have machines with PowerShell 2.0 and 3.0 but not 1.0, so my results may differ. When I run your code on my PowerShell 3.0 box, I get:
A command that prompts the user failed because the host program or the
command type does not support user interaction. Try a host program
that supports user interaction, such as the Windows PowerShell Console
or Windows PowerShell ISE, and remove prompt-related commands from
command types that do not support user interaction, such as Windows
PowerShell workflows.
It didn't like the Write-Host, so I changed your script to
param([string]$Username)
Get-Date
Get-ChildItem -Path $userName
Get-Date so that I could see some output without depending on the parameter and GCI to use the parameter. I modified your code to look like this:
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
using (var runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration))
{
runspace.Open();
String scriptfile = #"..\..\..\test.ps1";
String path = #"C:\Users\Public\";
var pipeline = runspace.CreatePipeline();
pipeline.Commands.Add(new Command("Set-ExecutionPolicy RemoteSigned -Scope Process", true));
pipeline.Invoke();
pipeline = runspace.CreatePipeline();
var myCommand = new Command(scriptfile, false);
var testParam = new CommandParameter("username", path);
myCommand.Parameters.Add(testParam);
pipeline.Commands.Add(myCommand);
var psObjects = pipeline.Invoke();
foreach (var obj in psObjects)
{
Console.WriteLine(obj.ToString());
}
runspace.Close();
}
Console.WriteLine("Press a key to continue...");
Console.ReadKey(true);
and it ran without error and displayed the folder contents, on both PoSh 2 and 3.
For info, if you're only setting the execution policy for the current process, you don't need to run elevated, hence I was able to do it in-code.
Import-Module command work fine with powershell windows console but same command doesn't work on c# api.
i'm using this project for execute powershell script: http://www.codeproject.com/Articles/18229/How-to-run-PowerShell-scripts-from-C
it execute many of them commands but it doesn't execute "Import-Module 'c:\vm\vm.psd1'" command. i try import microsoft modules but it doesn't work too. How can i execute "Import-Module" command with c# api?
Also add-pssnapin 'virtualmachinemanager' doesn't work too.
Try load module in this way:
PowerShell powershell = PowerShell.Create();
powerShell.Commands.AddCommand("Import-Module").AddParameter("Name", "c:\vm\vm.psd1'");
or
PowerShell powershell = PowerShell.Create();
powershell.Commands.AddCommand("Add-PsSnapIn").AddParameter("Name", "virtualmachinemanager");
With a pipeline try create an InitialSessionState
InitialSessionState iss = InitialSessionState.CreateDefault();
iss.ImportPSModule(new string[] { #"C:\vm\vm.psd1"});
Runspace runSpace = RunspaceFactory.CreateRunspace(iss);
runSpace.Open();
then use your code with pipeline to run cmdlet from module loaded
Try something like this for loading the snapin and executing your commands:
using System.Management.Automation.Runspaces;
//...
var rsConfig = RunspaceConfiguration.Create();
using (var myRunSpace = RunspaceFactory.CreateRunspace(rsConfig))
{
PSSnapInException snapInException = null;
var info = rsConfig.AddPSSnapIn("FULL.SNAPIN.NAME.HERE", out snapInException);
myRunSpace.Open();
using (var pipeLine = myRunSpace.CreatePipeline())
{
Command cmd = new Command("YOURCOMMAND");
cmd.Parameters.Add("PARAM1", param1);
cmd.Parameters.Add("PARAM2", param2);
cmd.Parameters.Add("PARAM3", param3);
pipeLine.Commands.Add(cmd);
pipeLine.Invoke();
if (pipeLine.Error != null && pipeLine.Error.Count > 0)
{
//check error
}
}
}