Remote PowerShell Script not working with c# - c#

My Powershell Script that invoke some commands to remote machine (on same domain) works very well.
Invoke-Command -script { get-host } -ComputerName 'AD' -Credential (New-Object System.Management.Automation.PSCredential ('admin', (ConvertTo-SecureString 'passwd' -AsPlainText -Force)))
but My C# Rest API program that uses above code is not working.
using (PowerShell ps = PowerShell.Create())
{
ps.AddScript(ps_script_above);
Collection<PSObject> psOutput = ps.Invoke();
logger.Debug("Result Count is : " + psOutput.Count);
}
Result Count is always zero.
But when except 'invoke-command' phrase, it works well.
My Powershell version is 7.x and dotnet version is 5.
Anyone with experience creating C# programs using remote powershell commands,
plz help me.

Related

Execute PowerShell script without 'PowerShell.SDK'

I want to execute the PowerShell script without SDK. In my project, I have to execute the PowerShell script and also want to create an EXE file for the same. But the problem is:
When I remove Microsoft.PowerShell.SDK then the script is not executed and gives an error but creates an exe file. Error is "Cannot load PowerShell snap-in Microsoft.PowerShell.Diagnostics because of the following error: Could not load file or assembly".
When the above package is not removed from the project then the script is working fine but it gives an error while creating an exe file.
Please share your suggestion.
Here is my code:
string readLocationFile = File.ReadAllText(#"gravity_location.ps1");
using (PowerShell powerShell = PowerShell.Create())
{
powerShell.AddScript(readLocationFile);
powerShell.AddParameter("name", _locationName.Text);
powerShell.AddParameter("targetPath", filePath);
powerShell.Invoke();
}
You can use System.Management.Automation which is the core of the PowerShell SDK like this
using System.Management.Automation;
using System.Management.Automation.Runspaces;
//...
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
//Here's how you add a new script with arguments
Command myCommand = new Command("your/script/file/path.ps1");
CommandParameter testParam = new CommandParameter("key","value"); //e.g. "-Path" "value"
myCommand.Parameters.Add(testParam);
pipeline.Commands.Add(myCommand);
// Execute PowerShell script
results = pipeline.Invoke();
Detailed information about the packages.
https://learn.microsoft.com/en-us/powershell/scripting/dev-cross-plat/choosing-the-right-nuget-package?view=powershell-7.2
Another post about the topic:
Execute PowerShell Script from C# with Commandline Arguments

Export X509Certificate with Powershell and C#

I have a Powershell script that exports an X509Certificate of user abc and it works fine when running in terminal.
$user = "abc"
$pfx_file = "pfxFilePath.pfx"
$pass = ConvertTo-SecureString -String "123" -Force -AsPlainText
(Get-ChildItem -Path cert:\currentuser\my\) | where-object { $_.subject -like "*$user*"} | Export-PfxCertificate -FilePath $pfx_file -Password $pass -Verbose
However, it doesn't export anything when I invoke it with my C# test(with PowerShell SDK) in Visual Studio, there is no message - no message, no error message, no verbose message. And I really don't know how to troubleshoot the problem. Here is my code
var ps = PowerShell.Create();
await ps.AddCommand("Set-ExecutionPolicy").AddParameter("ExecutionPolicy", "Unrestricted").InvokeAsync();
ps.AddScript("".\\test.ps1");
var results = await ps.InvokeAsync();
I think this is related to user permissions, but I used the same user for both Visual Studio and terminal, how can I check which user is running the test in Visual Studio? Is there anything can help me troubleshoot this problem?
Thanks!
Edit: After some digging, I realized the problem is with PowerShell SDK. It doesn't use regular Windows PowerShell instance, it has a different PSModulePath and it is missing a lot of default modules.

How to make a batch script to run commands on a remote machine using credentials

I have wrote some batch scripts to perform docker commands on a machine and made it run using c# program. I can successfully run those batch scripts in my local machine, but I want it to run on a remote machine. How can I do that by giving remote machine access credentials? I am looking for batch commands that will first connect to the remote machine and then execute its body in remote machine.
A sample batch script is as below.
::Start an exited container
::Iam expecting some code here to connect to a remote machine
#echo off
docker start %1
Or, Is there any option to do it through c# program?
I failed to find a method to run batch scripts on a remote machine, but I used powershell scripting instead of batch scripts. If you can use powershell scripts instead of batch scripts, you can use this method.
set-item wsman:localhost\client\trustedhosts -value <Remote_computer_name> -Force
$pword = ConvertTo-SecureString -String <Remote_machine_password> -AsPlainText -Force
$user = <Remote_userName>
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user, $pword
Set-ExecutionPolicy -ExecutionPolicy Bypass
Invoke-Command -ComputerName <Remote_computer_name> -filepath <ps1_file_path> -Credential $Credential
Running the above commands in a powershell administrator window will run the scripts in <ps1_file_path> in a remote machine.
You have to take into consider that, the command
set-item wsman:localhost\client\trustedhosts -value <Remote_computer_name> -Force
will add the remote machine into trusted hosts list.
Also, the command Set-ExecutionPolicy -ExecutionPolicy Bypass will allow all powershell scripts to run on our machine and I'm not sure it is safe to use.
Hope it help somebody in some way, but you must do research to make sure this method is safe.
Refer:
Execution Policies
Try using PsExec
https://learn.microsoft.com/en-us/sysinternals/downloads/psexec
This is a light weight replacement for telnet
Please try connecting using WinRM. Some sample info-
remote command execution
and
winrm-command referance
Or ssh server on Windows server - example
WinSCP
Hope it helps.

Similar to connecting to remote computer using WSManagement, how to do it through powershell terminal

I am connecting to the remote windows machine to execute powershell scripts using WSManagement method.I am creating a runspace using WSManagement ConnectionInfo object.Then using the runspace for the powershell object.Then using the powershell object I am invoking scripts with
Powershell.Invoke() command.
How to do this through the powershell terminal?
I must be misunderstanding this, because it looks like you're asking for the Invoke-Command cmdlet, which is the first result you'd get in a "powershell remote" google search.
Invoke-Command -ComputerName server1 -ScriptBlock { get-disk }
Invoke-Command -ComputerName server1 -FilePath .\test.ps1

Office 365: Connecting to Office Online 365 service using Power Shell Script issue

I have Windows Server 2008 R2 machine and it has Power Shell v1.0. I wanted to connect to MS 365 online service using Power Shell with C#. I have installed Office 365 cmdlets and Microsoft Online Services Sign-In Assistant. ( Ref: http://onlinehelp.microsoft.com/en-us/office365-enterprises/hh124998.aspx#BKMK_install )
My script is:
$password = ConvertTo-SecureString "xxxxx" -AsPlainText –Force
$credential = New-Object System.Management.Automation.PsCredential("xxxx#xxxx.onmicrosoft.com",$password)
$cred = Get-Credential -cred $credential
Import-Module MSOnline
Connect-Msolservice -cred $cred
I can successfully run this script in the Power Shell Command window. But I have problem running this script in c# application.
Here is my c# code:
public void RunScript()
{
StringBuilder ss = new StringBuilder();
ss.AppendLine("$password = ConvertTo-SecureString \"" + pwd + "\" -AsPlainText –Force");
ss.AppendLine("$credential = New-Object System.Management.Automation.PsCredential(\"" + userName + "\",$password)");
ss.AppendLine("$cred = Get-Credential -cred $credential");
ss.AppendLine("Import-Module MSOnline");
ss.AppendLine("Connect-Msolservice -cred $cred");
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
Collection<PSObject> results = null;
try
{
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(ss.toString());
results = pipeline.Invoke();
}
finally
{
runspace.Close();
}
}
}
I get the following exception:
The term 'Connect-Msolservice' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Is there anything missing?
Thanks
InitialSessionState iss = InitialSessionState.CreateDefault();
iss.ImportPSModule(new string[] { "MSOnline" });
using (Runspace runspace = RunspaceFactory.CreateRunspace(iss))
{
// blah
}
Please make sure you have installed following things:
1. SharePoint Online Management Shell
2. Microsoft Online Services Sign-In Assistant version 7.0 or greater version
3. Windows Azure Active Directory Module

Categories