Invoke-MyFunction is a commandlet I wrote that takes an input file, changes it, and creates a new output file at a specified location. If I open a PowerShell on my desktop, import MyCommandlet.ps1, and run
Invoke-MyFunction -InputPath path\to\input -OutputPath path\to\output
everything works as expected. But when I try to import and invoke the command from a C# program with the code below, the commandlet doesn't run, doesn't log output, and doesn't produce the output file. It doesn't throw a CommandNotFoundException, so I assume the PowerShell object recognizes my commandlet. But I can't figure out why it doesn't execute it.
//set up the PowerShell object
InitialSessionState initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] { #"C:\path\to\MyCommandlet.ps1" });
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
//have MyFunction take input and create output
ps.AddCommand("Invoke-MyFunction");
ps.AddParameter("OutputPath", #"C:\path\to\output");
ps.AddParameter("InputPath", #"C:\path\to\input");
Collection<PSObject> output = ps.Invoke();
Further, after invoking MyFunction, the PowerShell object ps fails to execute any other commands. Even known ones.
This works for me:
//set up the PowerShell object
var initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] { #"C:\Users\Keith\MyModule.ps1" });
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
//have MyFunction take input and create output
ps.AddCommand("Invoke-MyFunction");
ps.AddParameter("OutputPath", #"C:\path\to\output");
ps.AddParameter("InputPath", #"C:\path\to\input");
var output = ps.Invoke();
foreach (var item in output)
{
Console.WriteLine(item);
}
With a MyModule.ps1 of:
function Invoke-MyFunction($InputPath, $OutputPath) {
"InputPath is '$InputPath', OutputPath is '$OutputPath'"
}
One thing that did cause me a failure is that on Visual Studio 2013 (maybe 2012 as well) AnyCPU apps will actually run 32-bit on a 64-bit OS. You have to have set the execution policy for PowerShell x86 to allow script execution. Try opening up a PowerShell x86 shell in admin mode and run Get-ExecutionPolicy. If it is set to Restricted, use Set-ExecutionPolicy RemoteSigned to allows scripts to execute.
Related
Below is the code that I currently have to run my Powershell script in my C# program.
using (PowerShell PowerShellInstance = PowerShell.Create())
{
string script = "Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted; Get-ExecutionPolicy"; // the second command to know the ExecutionPolicy level
PowerShellInstance.AddScript(script);
var someResult = PowerShellInstance.Invoke();
someResult.ToList().ForEach(c => Console.WriteLine(c.ToString()));
//Console.ReadLine();
}
{
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
Command myCommand = new Command ("C:\\automate\\dandf\\onboarding\\Yardi_Automation\\Yardi_Automation\\Onboarding_Master\\O365_Add_User.ps1");
pipeline.Commands.Add(myCommand);
pipeline.Invoke();
runspace.Close();
Console.WriteLine("Powershell script executed..");
}
}
The script once ran will add an O365 license to any user that is put through the system. Every time I run the code it will stop at "pipeline.Invoke();) for 1 second and will move on without running the script. Any help is greatly appreciated.
Runspace Error
I'm able to run puppet bolt command in powershell. In powershell, I got output as below
Started on winrm://remotemachine
Finished on winrm://remotemachine
STDOUT:
RemoteMachineHostName
Successful on 1 target Run on 1 tartget in 3.2 sec
My C# is as below
PowerShell ps = PowerShell.Create();
ps.AddScript("C:\\User1\\GetRemoteAzureVMHostName.ps1");
Collection<PSObject> results = ps.Invoke(); // in results, I'm getting value as 0.
foreach (PSObject result in results)
{
//Do something
}
I tried changing build platform target to x64 in Visual Studio 2019 but it didn't worked.
How to fix above issue
Update 1:
I have used below command in powershell script.
bolt command run hostname --targets winrm://158.28.0.546 --no-ssl-verify --user testuser123 --password test#84p
It seems you cannot input the path of the PowerShell to the method AddScript(). Here is an example that runs the PowerShell script through C#:
private static string script =File.ReadAllText(#"Path\Sum.ps1");
private static void CallPS1()
{
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.AddScript(script);
ps.Invoke();
foreach (PSObject result in ps.Invoke())
{
Console.WriteLine("CallPS1()");
Console.WriteLine(result);
}
}
}
So you can try to read the script out and then input them in the method AddScript().
I figured it out that, Visual Studio is calling 32 bit powershell and unable to run bolt commands as bolt module installed on 64 bit powershell.
I have changed project build platform to x64 and build it.
It worked.
I have tried executing RemoteDesktop commandlets in powershell using C#.
The following is my program :
static void Main(string[] args)
{
using (var powershell = PowerShell.Create())
{
powershell.Commands.AddCommand("Import-Module").AddArgument("remotedesktop");
powershell.Invoke();
powershell.Commands.Clear();
powershell.AddCommand(#"Get-RDRemoteApp");
powershell.AddCommand(#"out-string");
foreach (var result in powershell.Invoke())
{
Console.WriteLine(result);
}
}
}
When I invoke command it gives the error System.Management.Automation.CommandNotFoundException: The term 'Get-RDRemoteApp' is not recognized as the name of a cmdlet, function, script file, or operable program.
How can I achieve calling RemoteDesktop commandlets ?
I solved this. I change run mode to x64 from Any CPU.
You need to set a persistent runspace for all of your commands. The way your code is now, each command is being executed in it's own isolated runspace. Adding the following code:
var runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
powershell.Runspace = runspace;
to the beginning of the using block should fix your problem.
I faced the same issue and found your post.
Default InitialSessionState only loads Core commandlets and ExecutionPolicy is set to the most restrictive: Microsoft.PowerShell.ExecutionPolicy.Default.
To work around this, I had to set the ExecutionPolicy as shown below :
InitialSessionState iss = InitialSessionState.CreateDefault();
iss.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Bypass;
iss.ImportPSModule("RemoteDesktop");
PowerShell powershell = PowerShell.Create(iss);
...
I am trying to use MDT from c# like I can already do with powershell when importing MicrosoftDeploymentToolkit.psd1. For example I can run the command Get-MDTPersistentDrive directly from powershell without problem.
But I can't find a way to do the same thing from c#, I tried to include directly the Microsoft.BDD.PSSnapIn.dll (which was basically what was doing "MicrosoftDeploymentToolkit.psd1") then I could access to the GetPersistent class but an error message informed me that I cannot directly invoke a PSCMDlet.
I then tried to use the PowerShell class
var ps = PowerShell.Create();
ps.AddScript(#"import-module C:\...\MicrosoftDeploymentToolkit.psd1");
ps.Invoke();
ps.AddCommand("Get-MDTPersistentDrive");
var result = ps.Invoke();
But I receive this exception
The term 'Get-MDTPersistentDrive' is not recognized as the name of a
cmdlet, function, script file, or operable program
I then tried to do this
InitialSessionState initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] { #"C:\...\MicrosoftDeploymentToolkit.psd1" });
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.Commands.AddCommand("Get-MDTPersistentDrive");
var result= ps.Invoke();
and I receive the error
Object reference not set to an instance of an object
I'm really lost, I don't get what they mean with this error, If you could show me where I'm wrong, or a way to execute PSCmdlet from c# or even better directly how to control MDT that would be awesome.
Hello a have a file with 21 lines of code in power shell. I need a way to run this file with a button in c#. I use c# in Visual Studio 2010. Please let me know if there is a way to achieve.
// Powershell
$Proc = Get-Process | Sort-Object CPU -Descending
$cores = Get-WmiObject Win32_processor
$memory = Get-WmiObject Win32_OperatingSystem
$Total = 10
$num = 1
Clear-Content c:\scripts\prueba.txt
foreach ($objItm in $Proc) {
If ($num -gt $Total) {
break #break the loop
}
[string] $strID=[System.Convert]::ToString($objItm.ID)
[string] $strProcessName=[System.Convert]::ToString($objItm.ProcessName)
[string] $strCPU=[System.Convert]::ToString($objItm.CPU)
[string] $strNUM=[System.Convert]::ToString($num)
$info=$strNUM+"-"+$strID+"-"+$strProcessName+"-"+$strCPU
$num += 1
$info|Add-Content c://scripts/prueba.txt
}
//Code c#
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open(); RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.Add(scriptFile)
Execute PowerShell script results = pipeline.Invoke();
I need for example press a button and make the script happens
You can use PS2EXE by Ingo Karstein
This creates a c# executable with it's own powershell host and with your script embedded.
I have a c# project which takes the c# code in PS2EXE, adds ability to read the contents of an encrypted powershell script, decrypt it and run it.
some tips that works for me . My application is already working
Run Visual Studio with permissions of Administrator this to avoid get a error with the Hkey_Local...
In power shell run this get-executionpolicy to view the policy and set unregistered with set-executionpolicy unregistered. This avoid any restriction by the OS.
And with the code write above the app work. Get ready and test !!!