I'm calling a PowerShell script from a console app. I need to call a script in a network share and pass a couple of arguments. I need help constructing the Arguments. I've tried precising the argument with an # symbol. here is a snipe of the code:
Process process = new Process();
// Configure the process using the StartInfo properties.
process.StartInfo.FileName = "powershell.exe";
process.StartInfo.Arguments = "powershell.exe -ExecutionPolicy Bypass -Noninteractive -File "\\Share\ConfigScript.ps1" -Config "\\Share\Config.xml" -Webservice "https://companysite.net/ConfigSite"";
process.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
process.Start();
process.WaitForExit();// Waits here for the process to exit.
I get multiple CS1002 and CS1056 errors if I jusc copy/paste arguments the way they work in PowerShell.
EDIT: NOTE: powershell.exe in the argument is used to bypass Execution Policy
You need to escape the special characters in the string.
\\ will give you \
\" will give you "
Note these special characters are escaped using the \ character. Also, check if you intentionally meant to have powershell.exe in the arguments since it is already specified as the filename?
Related
Running this from CMD produces the correct result:
powershell -command "& Get-DiskImage -imagepath C:\\file.vhdx | Get-Disk"
<Here is some stuff regarding VHD>
I want to achieve exactly the same running this from C# (there's no way to run it directly, use some PowerShell related .NET stuff, or something else).
My code is the following:
static void LaunchCommandLineApp()
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "powershell";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.RedirectStandardOutput = true;
startInfo.Arguments = "-command \" & get-diskimage -imagepath C:\\file.vhdx | Get-Disk \"";
using (Process exeProcess = Process.Start(startInfo)) {
exeProcess.WaitForExit();
var out = exeProcess.StandardOutput.ReadToEnd();
}
}
And in "out" I am getting an error:
Get-Disk : Cannot validate argument on parameter 'Number'. The argument is null. Provide a valid value for the argument, and then try running the command again.
But exactly the same code works in CMD. If I remove "| Get-Disk" from arguments, I will get correct output in "out" from the Get-DiskImage cmdlet.
Also, I have tried to play with curly braces, as other answers suggested - error haven't changed.
What shall I put in "startInfo.Arguments", so my output of "Get-DiskImage" will be correctly piped to the next cmdlet?
This is not actually a problem with the difference between running from the command line and from C#. I created a test VHDX and got the same (error) result whether run from C# or the command line, as shown by the OP.
In both cases, omitting the | Get-Disk part showed information about the disk image, which lacked a disk number, which is exactly what Get-Disk was complaining about. I suspect the image needs to be mounted for it to have a disk number.
I need to execute the following command, it works perfectly, if I execute it via command prompt, here the command line is using kodakprv.exe to send a print of a tiff file.
but when trying to execute it via c#, its not throwing any error but not sending the print either, tried to execute this command via xp_cmdshell in SQL, but it didn't work, in the xp_cmdshell documentation found that, quotes are not allowed for more then once, but kodakprv.exe print logic requires 3 pair of quotes
Please suggest can we use multiple quotes in C# while executing the command or suggest any better solution for it
String sCommand = "\"c:\\progra~1\\imagin~1\\kodakprv.Exe\" /pt \"D:\\SQLDev\\Dlls\\Testing.TIF\" \"\\\\Galactica\\C-Test1\"";
// Put your code here
System.Diagnostics.Process ExecuteCommand = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.Arguments = #" /c " + sCommand.ToString();
MessageBox.Show(startInfo.Arguments);
ExecuteCommand.StartInfo = startInfo;
ExecuteCommand.Start();
You don't need all those quotes. Only paths with spaces require quotes. None of your paths have spaces.
Shortnames, as you are using, may not exist (they can be turned off), or may not have the name you think. Windows does not preserve short names, only long names.
You are running your program via CMD. Unless your command line has redirection characters (as CMD handles redirection characters) then CMD is not required. You can start your program directly, which would be the preferred way (faster, less resources used).
Your window is set to hidden. Therefore you cannot see the message it is telling you. Unhide your window.
Your program will likely exit and close the window before you can read it. Either stick a &pause at the end of the command line sent to CMD, or read what is on both StdErr and StdOut as you specify to capture them in your code.
I'm running a runas with commands/arguments using .bat and .vbs to bypass an SRP restriction(for educational only), the .vbs file is to hide the command window, how do I write this on VB.Net or C#. I want to make it a standalone .exe file because I want to disallowed also the Command Prompt and VBScript also in the machine using SRP.
HideBat.vbs
CreateObject("Wscript.Shell").Run "run.bat", 0, True
run.bat
# ECHO OFF
runas /trustlevel:"Unrestricted" "C:\Program Files\Deluge\deluged.exe"
This is what I come up so far.
Dim myprocess As New System.Diagnostics.Process()
myprocess.StartInfo.FileName = Path.Combine(GetFolderPath(SpecialFolder.System), "runas.exe")
myprocess.StartInfo.Arguments = "/trustlevel:"Unrestricted"" & " " & "c:\program.exe"
myprocess.Start()
There is a problem on the Unrestricted, because of quotes.
Assuming C# (I don't know why you tagged this as VB.NET and C#)
Process myprocess = new Process();
myprocess.StartInfo.FileName = Path.Combine(GetFolderPath(SpecialFolder.System), "runas.exe");
myprocess.StartInfo.Arguments = "/trustlevel:\\\"Unrestricted\" \"C:\\Program Files\\Deluge\\deluged.exe\"";
myprocess.Start();
Use backslash to escape double quotes inside a string.
Updated answer-forgot to backslash the backslashes in the path.
Here my problem, I want to use gpg.exe to decrypt some data. Before this, I want to test and make an "ipconfig" through the Windows Shell. I've tried :
Process.Start("cmd","ipconfig");
without success. Did someone know a way to help me please?
Thanks.
Take a look at this function (taken from here)
public static string ExecuteCmd(string arguments)
{
// Create the Process Info object with the overloaded constructor
// This takes in two parameters, the program to start and the
// command line arguments.
// The arguments parm is prefixed with "#" to eliminate the need
// to escape special characters (i.e. backslashes) in the
// arguments string and has "/C" prior to the command to tell
// the process to execute the command quickly without feedback.
ProcessStartInfo _info =
new ProcessStartInfo("cmd", #"/C " + arguments);
// The following commands are needed to redirect the
// standard output. This means that it will be redirected
// to the Process.StandardOutput StreamReader.
_info.RedirectStandardOutput = true;
// Set UseShellExecute to false. This tells the process to run
// as a child of the invoking program, instead of on its own.
// This allows us to intercept and redirect the standard output.
_info.UseShellExecute = false;
// Set CreateNoWindow to true, to supress the creation of
// a new window
_info.CreateNoWindow = true;
// Create a process, assign its ProcessStartInfo and start it
Process _p = new Process();
_p.StartInfo = _info;
_p.Start();
// Capture the results in a string
string _processResults = _p.StandardOutput.ReadToEnd();
// Close the process to release system resources
_p.Close();
// Return the output stream to the caller
return _processResults;
}
The first parameter is the file executed, "cmd" is a shortcut for "C:\Windows\System32\cmd".
The second parameter are the arguments to give to the program. Here, you can't just write "ipconfig". You have to use /r or /c or /k to give the arguments to cmd:
/c or /r : Carries out the command specified by string and then stops.
/k : Carries out the command specified by string and continues.
Process.Start("cmd", "/r ipconfig");
Note that in the statement
ProcessStartInfo("cmd", #"/C " + arguments);
Contrary to the comment in the code, the # sign only affects the string "/C " and does not the affect the contents of the string arguments. In this case it doesn't hurt anything, but doesn't do anything either.
Contrary to the comment in the code, any \s in arguments would indeed need to be escaped.
We have a few commands(batch files/executables) on our network path which we have to call to initialize our 'development environment' for that command window. It sets some environmental variables, adds stuff to the Path etc. (Then only whatever working commands we type will be recognized & I don't know what goes inside those initializing commands)
Now my problem is, I want to call a series of those 'working commands' using a C# program, and certainly, they will work only if the initial setup is done. How can I do that? Currently, I'm creating a batch file by scratch from the program like this for example:
file.Writeline("InitializationStep1.bat")
file.Writeline("InitializeStep2.exe")
file.Writeline("InitializeStep3.exe")
Then the actual commands
file.Writeline("Dowork -arguments -flags -blah -blah")
file.Writeline("DoMoreWork -arguments -flags -blah -blah")
Then finally close the file writer, and run this batch file.
Now if I directly execute this using Process.<strike>Run</strike>Start("cmd.exe","Dowork -arguments"); it won't run.
How can I achieve this in a cleaner way, so that I have to run the initialization commands only once? (I could run cmd.exe each time with all three initializers, but they take a lot of time so I want to do it only once)
As #Hakeem has pointed out, System.Diagnostic.Process does not have a static Run method. I think you are referring to the method Start.
Once you have completed building the batch file, then simply execute it using the following code,
Process p = new Process();
p.StartInfo.FileName = batchFilePath;
p.StartInfo.Arguments = #"-a arg1 -b arg2";
p.Start();
Note that the # symbol is required to be prefixed to the argument string so that escape sequence characters like \ are treated as literals.
Alternative code
Process.Start(batchFilePath, #"-a arg1 -b arg2");
or
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = batchFilePath;
processStartInfo.Arguments = #"-a arg1 -b arg2";
Process.Start(processStartInfo);
More information
Process.Start method
Example of multi command batch file
dir /O
pause
dir
pause
Save this file as .bat and then execute using the Start method. In this case you can specify the argument with the command in the batch file itself (in the above example, the /O option is specified for the dir command.
I suppose you already have done the batch file creation part, now just append the arguments to the commands in the batch file.
Redirecting Input to a process
Since you want to send multiple commands to the same cmd process, you can redirect the standard input of the process to the take the input from your program rather than the keyboard.
Code is inspired from a similar question at: Execute multiple command lines with the same process using C#
private string ProcessRunner()
{
ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd.exe");
processStartInfo.RedirectStandardInput = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.UseShellExecute = false;
Process process = Process.Start(processStartInfo);
if (process != null)
{
process.StandardInput.WriteLine("dir");
process.StandardInput.WriteLine("mkdir testDir");
process.StandardInput.WriteLine("echo hello");
//process.StandardInput.WriteLine("yourCommand.exe arg1 arg2");
process.StandardInput.Close(); // line added to stop process from hanging on ReadToEnd()
string outputString = process.StandardOutput.ReadToEnd();
return outputString;
}
return string.Empty;
}
The method returns the output of the command execution. In a similar fashion, you could also redirect and read the StandardOuput stream of the process.
The Process.Run method that you mentioned, is that from the Process class in System.Diagnostics namespace? AFAIK, the Process type doesn't have either a static or instance method named Run. If you haven't already I'd try with the Start method on Process, either instance or static