I am trying to automate the running of a powershell script along with the running of other programs.
To run the powershell script manually, I would normally do this in a command prompt:
powershell "IEX (New-Object Net.WebClient).DownloadString('http://serverurl/Script.ps1'); Invoke-Method"
I can't seem to replicate this in c# to save my life using built in "PowerShell" commands. I"d rather NOT have to use things like "Process", so any advice would be helpful.
Since System.Net.WebClient is a .NET class, you don't need PowerShell to use it:
string script = (new System.Net.WebClient()).DownloadString('http://serverurl/Script.ps1');
To execute the script, use the System.Management.Automation.PowerShell class:
using System.Management.Automation;
// ...
using(PowerShell ps = PowerShell.Create())
{
ps.AddScript(script).AddScript("Invoke-Method");
ps.Invoke();
}
Related
I would like to run the following powershell commands from my C# application:
Enter-PSSession –ComputerName fedsrv01.domain.local
Start-ADSyncSyncCycle -PolicyType Delta
I found some information on the Powershell Class but struggling to achieve what I want due to my lack of experience.
https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.powershell?redirectedfrom=MSDN&view=pscore-6.2.0
This is what I have so far:
I have added the assembly and referenced system.management.automation
using (var powershell = PowerShell.Create())
{
//powershell.AddCommand("get-process");
powershell.AddCommand("Enter-PSSession -ComputerName fedsrv01.domain.local");
powershell.Invoke();
}
I get an error saying, 'The term 'Enter-PSSession -ComputerName fedsrv01.domain.local' is not recognized as the name of a cmdlet, function, script file, or operable program.
if I use: powershell.AddCommand("get-process") it executes fine.
If I launch Powershell on the same PC and enter, Enter-PSSession -ComputerName fedsrv01.domain.local it works fine.
Any assistance would be much appreciated.
Cheers,
Jono
Try compiling your application as x64. If it is compiled as x86 platform then it will be using the virtualized System32 dir so the function you require may not exist.
Powershell commands from C# 'the term is not recognizes as cmdlet'
Ok, after more research into the PowerShell class I now realise that you have to add the parameters separately using the .addparameter method.
.addcommand is just for the PowerShell commands. It now makes sense why I got the error saying the command could not be found. It was assuming the entire string was a command.
Problem solved!
Jono
I've been trying for a month now to host powershell core remoting scripts, that use SSH protocol for remoting, in a dot net core application and so far nothing worked. One of my main issues is that AddScript method of system management automation seems to be doing absolutely nothing when you have Powershell remoting scripts in the block.
I was wondering if anyone has actually tried to host remoting scripts in dot net core C# application successfully?
I actually have an issue raised in the PowerShell github page, but no one is interested in it, hence the zero comments.
https://github.com/PowerShell/PowerShell/issues/7984
Thank you for your help.
I might have found a simple workaround that I've tested and it works.
Basically instead of asking the don net application to call the remoting script via .AddScript method you ask the dot net app to call a local powershell process that executes the remoting script. The script file should be somewhere on the server you're executing the application from. To show this as a code I'm using the following.
string script = "start-process pwsh-preview" -argument "path to script file"
using (Runspace runspace = RunspaceFactory.CreateRunspace())
using (Powershell powershell = Powershell.Create())
{
runspace.Open();
PSCommand command = new PSCommand();
command.AddScript(script);
powershell.Commands = command;
powerhell.Runspace = runspace;
Collection<PSObject> results = new Collection<PSObject>();
results = powershell.Invoke();
I'm yet to test calling the script with parameters (not sure how to do it yet maybe someone here can help). As well as hosting in docker container the entire thing. Most likely PowerShell core will need to be installed as well as dot net core in the docker image for it to work.
Hope this help.
I'm still waiting for the GitHub PowerShell guys to look at the issue.
I will post more information here once I test hosting this in docker.
I struggled getting PS scripts to work through my app as well and made it work just a like a week ago.
Here I launch a script on a remote computer to make a Windows Toast Notification to pop up. You might have to download and install the Powershell.SDK NuGet package for the PowerShell scripts to work.
Here you can see I also get the output generated from the script.
For some reason Verbose output was not captured even though verbose preference was set in the script. I had to capture the output by putting the statements in quotation marks like this:
"OS Version: $OsVersion"
using System;
using System.Diagnostics;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Collections.ObjectModel;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace WindowsToasts
{
public class WindowsToast
{
public void Send_WindwsUpdateToast(string computerName)
{
InitialSessionState initialSessionState = InitialSessionState.CreateDefault();
initialSessionState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;
using Runspace runspace = RunspaceFactory.CreateRunspace(initialSessionState);
runspace.Open();
using PowerShell powerShell = PowerShell.Create(runspace);
string PSPath = #"C:\temp\ToastText.ps1";
powerShell.AddCommand("Invoke-Command");
powerShell.AddParameter("ComputerName", computerName);
powerShell.AddParameter("File", PSPath);
Collection<PSObject> PSOutput = powerShell.Invoke();
foreach (PSObject outputItem in PSOutput)
{
// if null object was dumped to the pipeline during the script then a null object may be present here
if (outputItem != null)
{
Debug.WriteLine($"Output line: [{outputItem}]");
}
}
}
}
}
I'm trying to develop a .Net form application to manage azure VMs in C# using Powershell cmdlets. I'll have to use the Azure module to get this working.
One of the cmdlet will be Add-AzureAccount
My question is how can I include this module (Azure) in C# project ?
In the comment section, #Prageeth Saravanan gave a useful link on how integrate PowerShell in C#.
https://blogs.msdn.microsoft.com/kebab/2014/04/28/executing-powershell-scripts-from-c/
Quick example :
First I had to include these refs :
System.Management.Automation
System.Collections.ObjectModel
Note : You need to add a NuGet package for "Management.Automation". Just type "System.Management.Automation" you'll find it.
C# code:
//The first step is to create a new instance of the PowerShell class
using (PowerShell powerShellInstance = PowerShell.Create()) //PowerShell.Create() creates an empty PowerShell pipeline for us to use for execution.
{
// use "AddScript" to add the contents of a script file to the end of the execution pipeline.
// use "AddCommand" to add individual commands/cmdlets to the end of the execution pipeline.
powerShellInstance.AddScript("param($param1) $d = get-date; $s = 'test string value'; $d; $s; $param1; get-service");
// use "AddParameter" to add a single parameter to the last command/script on the pipeline.
powerShellInstance.AddParameter("param1", "parameter 1 value!");
//Result of the script with Invoke()
Collection<PSObject> result = powerShellInstance.Invoke();
//output example : #{yourProperty=value; yourProperty1=value1; yourProperty2=StoppedDeallocated; PowerState=Stopped; OperationStatus=OK}}
foreach (PSObject r in result)
{
//access to values
string r1 = r.Properties["yourProperty"].Value.ToString();
}
}
Hope this helps!
We could use PowerShell cmdlets Import-module to add corresponding modules to the current session. We could use force parameter to re-import a module into the same session.
Import-module -name azure -force
The import thing is that the imported module need to be installed on the local computer or a remote computer. So if we want to execute Azure PowerShell cmdlets from C# project that we need to make sure that Azure PowerShell are installed. We can use install-module AzureRM or Azure more details please refer to the Get Started Azure PowerShell cmdlets. In the Azure VM, Azure PowerShell is installed by default.
About how to call PowerShell command or PS1 file using C# please refer to Prageeth Saravanan mentioned link or another SO Thread.
I'm using System.Management.Automation.PowerShell to programmatically execute a PowerShell script from C# application. The PowerShell script loads a .Net dll which it uses to perform its activities.
var script = "Add-Type -Path 'MyLibrary.dll'; ....";
using (var powershell = PowerShell.Create()) {
powershell.AddScript(script);
powershell.Invoke();
}
Is it possible to somehow connect Visual Studio's debugger to the PowerShell object instance so that the debugger can seamlessly step from the C# application into the PowerShell script and from that script into MyLibrary.dll (assuming I have symbols for the dll)?
Edit: Based on the below, it appears that there may not be a way to seamlessly flow debugging in Visual Studio from C# to PowerShell. However, it is possible to use VS to debug the C# code that launches and that is launched by PowerShell.
You could debug the dll file by calling the following in your helper class:
System.Diagnostics.Debugger.Launch();
I'm trying to install new features on a Windows Server 2012 system through PowerShell and C#. I am getting this error back when trying to call the Install-WindowsFeature cmdlet:
The term 'Install-WindowsFeature' is not recognized as the name of a
cmdlet, function, script file, or operable program...
I can call other cmdlets though C# and even some of the other new ones. I did a Get-Command and Install-WindowsFeature, Remove-WindowsFeature, and Get-WindowsFeatures are not listed...but about 980 others are.
Why wouldn't I be able to call this cmdlet from my C# program, but when I go to PowerShell it calls it just fine?
runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript("Install-WindowsFeature");
Collection<PSObject> output = pipeline.Invoke();
Try this command instead of Install-WindowsFeature in your code:
Invoke-Expression "Powershell -Command {Import-Module ServerManager ; Install-WindowsFeature XXXX}"
Try compiling in x64. In Visual Studio go to menu Project → Properties → Build - Platform Target = x64.