Powershell Error when Running process - c#

I am working in C# working on a program to clean up the windows 10 start menu and assign a custom layout. To do so I need to run a single command from powershell and am getting an error when running it.
How I am trying to accomplish the task.
I am starting C:\.\.\powershell.exe and passing the -command arguments of: Import-StartLayout -LayoutPath C:\StartMenu.xml -MountPath C:\
Process process = new Process();
process.StartInfo.FileName = #"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe";
process.StartInfo.Arguments = #" -command Import-StartLayout -LayoutPath C:\StartMenu.xml -MountPath C:\";
process.Start();
Here is the error I am receiving:
Import-StartLayout : The term 'Import-StartLayout' 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.
At line:1 char:1
+ Import-StartLayout -LayoutPath C:\StartMenu.xml -MountPath C:\; Start ...
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Import-StartLayout:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Any ideas why cmd or powershell will not take the external cmdlet of Import-StartLayout??

Import-StartLayout does not exist on windows 7 and earlier if you know that, continue.
You could try using System.Diagnostics.Process like the following:
Process powerShell = new Process()
{
StartInfo =
{
Arguments = "Import-StartLayout -LayoutPath C:\\StartMenu.xml -MountPath C:\\",
FileName = "powershell"
}
};
powerShell.Start();
Another way would be to use System.Management.Automation which is not an official supported package by Microsoft.
using (Runspace runSpace = RunspaceFactory.CreateRunspace())
{
runSpace.Open();
using (Pipeline pipeline = runSpace.CreatePipeline())
{
Command importStartLayout = new Command("Import-StartLayout");
importStartLayout.Parameters.Add("LayoutPath", "C:\\StartMenu.xml");
importStartLayout.Parameters.Add("MountPath", "C:\\");
pipeline.Commands.Add(importStartLayout);
Collection<PSObject> resultsObjects = pipeline.Invoke();
StringBuilder resultString = new StringBuilder();
foreach (PSObject obj in resultsObjects)
{
resultString.AppendLine(obj.ToString());
}
}
}

Related

Psexec works on command line but not in ASP

I am using PsExec to remotely fire a program. I can fire the actual program (not displayed here) or cmd.exe remotely with no problems whatsoever from the command line. When I try to fire it from ASP and C#, it will not trigger the command prompt, even though I am using the same exact string. Here is the string I am using that works every time, and the code that doesn't. Help please!
Working String: C:\psexec \\10.0.0.25 -u Administrator -p password -d -i cmd.exe
Non-working code:
ProcessStartInfo psi = new ProcessStartInfo(#"C:\PsExec.exe")
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true,
Arguments = #"\\10.0.0.25 -u Administrator -p password -d -i cmd.exe"
};
process.StartInfo = psi;
var success = process.Start();
One option, assuming you have control over the machine, is to setup the psexec command as a Task Scheduler job, then execute the task scheduler job from your ASP app. You can configure the task scheduler to run as an administrator, and when you fire off the job it will run under that credentials. You won't get any output that way though, so if that's an issue there may not be a good choice.
See How to run existing windows 7 task using command prompt for an example of running the task..
It's been a while since I was a system administrator, but if I recall correctly psexec has to be run from an administrative command prompt. Maybe the account your app is running under doesn't have rights to reach across the network and do stuff to a remote machine?
Put this in your Page_Load temporarily:
Response.Write(Environment.UserName);
and run it again, it should show you the name you're looking for at the top of your app.
Well, I am right now doing some automation and have figured out a few things. Please see below code maybe it will help you out
public static void PSExec_Method()
{
try
{
string userName = #"ABC";
string password = "ABC";
string remoteMachine = "ABC";
//How to restart AppPool
//string operation = "stop";
//string apppoolname = "APPPOOL";
//string command = #"%SYSTEMROOT%\System32\inetsrv\appcmd " + operation + " apppool /apppool.name:\"" + apppoolname + "\"";
string command = #"powershell -noninteractive Get-Content C:\tmp\tmp.csv -Head 5";
//string command = #"ipconfig";
string PSPath = #"C:\PSTools\PsExec.exe";
string fullcommand = PSPath + " -u " + userName + " -p " + password + " \\\\" + remoteMachine + " -h cmd.exe /c " + command;
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = fullcommand;
process.Start();
Console.WriteLine(process.StandardOutput.ReadToEnd());
Console.WriteLine(process.StandardError.ReadToEnd());
process.WaitForExit();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}

Executing Powershell Script fails in c#

My powershell script fails to run with the following error:
On this line: -
"Import-AzureRmContext -Path C:\profile.json;"
If I right click the file and "Run with powershell" then the script runs fine.
If I run using PowerShellInstance, get the same error:
Found this code from another StackOverflow Post. Which you can use to execute powershell scripts using command prompt. This worked for me using the below function and call:
ExecuteCommand("powershell -command \" & C:\\PowershellFileName.ps1\"");
public void ExecuteCommand(string Command)
{
ProcessStartInfo ProcessInfo;
Process Process;
ProcessInfo = new ProcessStartInfo("cmd.exe", "/K " + Command);
ProcessInfo.CreateNoWindow = true;
ProcessInfo.UseShellExecute = true;
Process = Process.Start(ProcessInfo);
}

How to pass a path as an argument to Process.Start

the following code speaks for itself. When I try to xcopy a local folder to a networkshare, the paths get all messed up and CMD can't interpet correctly the backslashes. Any suggestions are welcome, already tried everything I found on the web (been stuck almost for 2 hours on this):
string command = "xcopy /s " + #"C:\Users\Me\Desktop\TempExtract\MyApp\*.* " + #"\\TestShare\SharedFolder\Applications\ /Y /I";
Process Processo = new Process();
ProcessStartInfo Xcopy = new ProcessStartInfo("cmd.exe");
Xcopy.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
Xcopy.Arguments = command;
Processo = Process.Start(Xcopy);
Processo.WaitForExit();
The problem here is that "Arguments" can't decode "\\" to "\" so my paths are like:
C:\\Users\\Me\\Desktop\\TempExtract\\MyApp\\*.*
And CMD can't interpert double backslashes :( help!
I think the problem lies in the way you setup ProcessStartInfo. So command should be:
string command = #"C:\Users\Me\Desktop\TempExtract\MyApp\*.* " + #"\\TestShare\SharedFolder\Applications\ /Y /I";
and add
Xcopy.FileName = "xcopy";
this is what worked for me:
using System.Diagnostics;
class Program
{
static void Main(string[] args)
{
var command = #"C:\Users\Me\Desktop\TempExtract\MyApp\*.* " + #"\\TestShare\SharedFolder\Applications\ /Y /I";
var Processo = new Process();
var Xcopy = new ProcessStartInfo("cmd.exe")
{
Arguments = command,
FileName = "xcopy",
UseShellExecute = false
};
Processo = Process.Start(Xcopy);
Processo.WaitForExit();
}
}
try adding /c in the beginning or the command string (as the cmd.exe launches the following command through the /c parameter, check the help of cmd.exe).
If that doesn't do the trick, add \" around your paths.

Executing 3rd Party Powershell SDK commands with C#

This is an incredibly frustrating problem that nobody else seems to have the answer to so I'm trying to break my question down into the simplest thing possible. Surely there are other 3rd party Powershell SDK's out there that people have tried to access and use via C#. Does anybody know why this would get an error saying the following?
The term 'add-PSSnapin Citrix*.Admin.V* is not recognized as the name of a cmdlet, function, script file, or operable program.
The same goes for other commands that this PSSnapin provides at the command prompt.
I can type this command in manually at a powershell command prompt and it works. So do the other commands. What's the deal?
public void testPS()
{
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.AddCommand("add-PSSnapin Citrix.*.Admin.V*");
ps.Invoke();
//Commented sections below don't work either, same error.
//ps.AddCommand("Get-BrokerSession");
//ps.AddParameter("AdminAddress");
//ps.AddParameter("SERVERNAME");
//ps.Invoke();
//Collection<PSObject> psr = ps.Invoke();
//foreach (PSObject x in psr)
//{
// MessageBox.Show(x.ToString());
//}
}
}
UPDATE:
This new code as suggested in the answer below gets a new error: 'System.Management.Automation.ParameterBindingException' occurred in System.Management.Automation.dll
public void testPS()
{
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
PSSnapInException psex;
runspace.RunspaceConfiguration.AddPSSnapIn("Citrix.Broker.Admin.V2", out psex);
Pipeline pipeline = runspace.CreatePipeline();
Command getSession = new Command("Get-BrokerSession");
getSession.Parameters.Add("AdminAddress");
getSession.Parameters.Add("MYSERVERNAME");
//also tried the above with this code
//getSession.Parameters.Add("-AdminAddress MYSERVERNAME");
// and
//getSession.Parameters.Add("AdminAddress MYSERVERNAME");
// and other methods as well
pipeline.Commands.Add(getSession);
//This line below is where the exception occurs.
Collection<PSObject> output = pipeline.Invoke();
foreach (PSObject x in output)
{
MessageBox.Show(x.ToString());
}
}
}
UPDATE 2:
I also get this same error above trying to set the execution policy.
UPDATE 3:
Fixed, see comments in answer below. The syntax of the parameters line was incorrect.
Use RunspaceConfiguration.AddPSSnapIn to add PSSnapin and then add a command:
Runspace runSpace = RunspaceFactory.CreateRunspace();
runSpace.Open();
PSSnapInException psex;
runSpace.RunspaceConfiguration.AddPSSnapIn("Citrix.Broker.Admin.V2", out psex);
Pipeline pipeline = runSpace.CreatePipeline();
Command getSession = new Command("Get-BrokerSession");
getSession.Parameters.Add("AdminAddress", "SERVERNAME");
pipeline.Commands.Add(getSession);
Collection<PSObject> output = pipeline.Invoke();
You need to make sure that you split the command from its argument. In your case, it would be something like:
ps.AddCommand("add-PSSnapin");
Then you can always just post-append Citrix.*.Admin.V* as an argument for the command above.
For those still stuck with this like me, even as of the latest Microsoft.Powershell.Sdk 6.2.0 nuget package I was running into this issue. A colleague of mine ended up getting it to work by doing the following:
public string RunPowershell(string param1)
{
var outputString = "";
var startInfo = new ProcessStartInfo
{
FileName = #"powershell.exe",
Arguments = "C:\\path\\to\\script.ps1" + " -param1 " + param1,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
using (var process = new Process())
{
process.StartInfo = startInfo;
process.Start();
var output = process.StandardOutput.ReadToEnd();
var errors = process.StandardError.ReadToEnd();
if (!string.IsNullOrEmpty(output))
{
outputString = output;
}
if (!string.IsNullOrEmpty(errors))
{
Console.WriteLine($"Error: {errors}");
}
}
return outputString;
}
"C:\path\to\script.ps1" can have Add-PSSnapin commands in it and still run just fine.
I couldn't find a bug filed for Microsoft.Powershell.Sdk to handle this, but if someone creates one and links it here, thanks!
Hope this helps

Enabling execution policy for PowerShell from C#

I have an ASP.NET MVC 4 page that calls a piece of PowerShell. However, I am running into a problem as a module I am using is not signed, so I have to enable the Unrestricted policy. How can I force the PowerShell child to use Unrestricted policy?
I have enabled this in my script, but it is ignored. Also when I try to set the policy in code, an exception is thrown.
using (Runspace myRunSpace = RunspaceFactory.CreateRunspace())
{
myRunSpace.Open();
using (PowerShell powerShell = PowerShell.Create())
{
powerShell.Runspace = myRunSpace;
powerShell.AddCommand("Set-ExecutionPolicy").AddArgument("Unrestricted");
powerShell.AddScript(script);
objectRetVal = powerShell.Invoke();
}
}
If you only need to run the one script with no interactions you can set the execution policy via the command prompt like so:
string command = "/c powershell -executionpolicy unrestricted C:\script1.ps1";
System.Diagnostics.Process.Start("cmd.exe",command);
For PowerShell 5.1 and PowerShell 7 Core, you can use an ExecutionPolicy Enum to set the Execution policy, like so:
using Microsoft.PowerShell;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
...
public class MyClass
{
public void MyMethod()
{
// Create a default initial session state and set the execution policy.
InitialSessionState initialSessionState = InitialSessionState.CreateDefault();
initialSessionState.ExecutionPolicy = ExecutionPolicy.Unrestricted;
// Create a runspace and open it. This example uses C#8 simplified using statements
using Runspace runspace = RunspaceFactory.CreateRunspace(initialSessionState);
runspace.Open();
// Create a PowerShell object
using PowerShell powerShell = PowerShell.Create(runspace);
// Add commands, parameters, etc., etc.
powerShell.AddCommand(<command>).AddParameter(<parameter>);
// Invoke the PowerShell object.
powerShell.Invoke()
}
}
You have to use parameter -Scope = CurrentUser:
powershell.AddCommand("Set-ExecutionPolicy").AddArgument("Unrestricted")
.AddParameter("Scope","CurrentUser");
This is the same as #kravits88 answer but without displaying the cmd:
static void runPowerShellScript(string path, string args) {
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.Arguments = #"/c powershell -executionpolicy unrestricted " + path + " " + args;
startInfo.UseShellExecute = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.CreateNoWindow = true;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
}
My solution was to self sign the modules and script I was running from IIS Express. I'm still developing and have found that IIS Express does not see all modules that you may have installed in the \System32\WindowsPowerShell...\Modules Path. I moved the modules I was using to another drive and used that location to import the module into my script.
Thanks for the replies :-)

Categories