I have a Windows Forms Application with the app.manifest set to:
level="requireAdministrator" uiAccess="false".
Now I need to run a console application (Diskspd.exe) from my application and return the standard output. It almost works, though the part that requires runAs Admin of DiskSpd fails.
Here is the part of the code that call the process (Example of txtDatPath.Text is "C:\temp\IO.dat"):
if (File.Exists(txtDatPath.Text))
{
File.Delete(txtDatPath.Text);
}
string qPath = string.Format("\"{0}\"", txtDatPath.Text);
if (rdoOLTP.Checked)
{
DScmd = "-b8K –d180 -h -L –o32 –t3 -r –w75 -c5G " + qPath;
}
else
{
DScmd = "–b60K –d60 -h -L –o32 –t1 -s –w100 –c1G " + qPath;
}
//now set up the cmd
var p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.Verb = "runas";
p.StartInfo.Arguments = DScmd;
p.StartInfo.FileName = "diskspd.exe";
p.Start();
// To avoid deadlocks, always read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
I need the process itself to run as Admin to succeed. The command behaves the same way if I run regular command then try CMD and run as admin it completes.
StartInfo.UseShellExecute needs to be set to false for the RedirectStandardOutput to work.
Well - after all of this - in adding debugging, the issue is the p.StartInfo.Arguments = DScmd;
The Argument is being interpreted as separate entries.
The solution/problem: DISKSPD requires ASCII and the string is UNICODE.
Changed the hyphens to convert.ToChar(45)
So I am going to close this case (thx all!) and open new one.
Related
I have a console app that does a number of things. One of the steps involves calling an EXE (AzCopy). I've successfully run this type command in a prompt and it looks like this:
AzCopy /Source:https://mysite.table.core.windows.net/MYTABLE/ /SourceKey:SOURCEKEY /Dest:C:\export /Manifest:MYTABLE
I need to run this script in the middle of a console app's execution. I've seen a number of different ways to do this, but none seem to work. I've tried this:
System.Diagnostics.Process.Start("CMD.exe", command);
And this:
var procStartInfo = new ProcessStartInfo("AzCopy", command);
And this:
var p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = command;
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
None seem to actually kick off the AzCopy call. What gives?
System.Diagnostics.Process.Start("CMD.exe", command); should work.
But you need to add /C at the beginning of your command.
Something like this:
"/C AzCopy /Source:https://mysite.t........................................."
I'm trying to launch a command in a console window / I'm using a gtk form/
So I've tried to launch it this way:
Process p = new Process ();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "bash";
p.StartInfo.CreateNoWindow = false;
p.StartInfo.Arguments ="/tmp/test.sh";
p.Start ();
p.WaitForExit ();
but it won't show any thing.
for those who only use windows, it's something like:
p.StartInfo.FileName = "cmd";
p.StartInfo.Arguments =" c:\\test.bat";
I've tried to change UseShellExecute to true but the problem still exist..
Any Ideas??
Bash runs the script but if you want to see output, you need to run it in a terminal.
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "gnome-terminal"; // Replace with whichever terminal you want to use
p.StartInfo.CreateNoWindow = false;
p.StartInfo.Arguments ="-x bash /tmp/test.sh";
//p.StartInfo.Arguments ="-e \"bash -c /tmp/test.sh;bash\""; // Use this if you want the terminal window to stay open
p.Start();
p.WaitForExit();
I've been searching and experimenting all morning with this one and I'm stumped. I have an aspx page running in IIS and calling the following c# function. I'm trying to have it run a cmd file and return the output from the cmd file. I've experimented with the five different options in the code below:
protected String RunMyCmdFileAndGetResponse() {
Process proc = new Process ();
proc.StartInfo.FileName = #"c:\Windows\System32\cmd.exe";
// proc.StartInfo.Arguments = #"/c echo hello"; <== 1
// proc.StartInfo.Arguments = #"/c c:\mypath\myfile_badname.cmd"; <== 2
// proc.StartInfo.Arguments = #"/c type c:\mypath\myfile.cmd"; <== 3
proc.StartInfo.Arguments = #"/c c:\mypath\myfile.cmd"; // <== 4
// proc.StartInfo.Arguments = #"/c call c:\mypath\myfile.cmd"; <== 5
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
string response = proc.StandardOutput.ReadToEnd();
response += proc.StandardError.ReadToEnd();
proc.WaitForExit();
return response;
}
Cmd file c:\mypath\myfile.cmd contents are:
#echo test line 1 > c:\mypath\myfilelog.txt
#echo test line 2
This cmd file works as expected when run manually, producing myfilelog.txt and returning test line 2. When executed with the c# code:
Option 1 works - returns 'hello' response as expected.
Option 2 fails as expected, indicating myfile_badname.cmd is not recognized as a valid command
Option 3 works as expected - it returns the contents of myfile.cmd as the response - this confirms I am able to find and read the file.
Option 4 does not work - as near as I can figure, it should. It does not hang up, but also does not return any response at all, and does not execute the cmd file (no myfilelog.txt produced).
Option 5 - same results as option 4.
Note - I've also tried modifying myfile.cmd to remove line 1 (creating the log file) and only leave line 2 to echo a response. Just in case it's a permission issue creating the log file. Same result.
Any help would be appreciated!
Updated to add solution:
The answer from #MaxOvrdrv got me thinking a different way. There does indeed appear to be some kind of limitation when running Process.Start within an IIS context with UseShellExecute = false - if the primary argument is an executable file (cmd file, script file, etc), it will not run it. I tried passing SomeExample.cmd to cmd.exe, and SomeExample.js to cscript.exe.
However... I was able to trick it with a level of indirection, such that the executable file name is no longer the first argument, and it works just fine that way.
To run a cmd file:
string theResponse = RunMyCmdAndGetResponse(#"c:\somepath\mycmd.cmd");
protected String RunMyCmdAndGetResponse(string cmdPath) {
Process proc = new Process ();
proc.StartInfo.FileName = #"c:\Windows\System32\cmd.exe";
proc.StartInfo.Arguments = "/c cmd /c " + cmdPath;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
proc.WaitForExit();
string response = proc.StandardOutput.ReadToEnd();
response += proc.StandardError.ReadToEnd();
return response;
}
To run a script file:
string theResponse = RunMyScriptAndGetResponse(#"c:\somepath\myscript.js");
protected String RunMyScriptAndGetResponse(string scriptPath) {
Process proc = new Process ();
proc.StartInfo.FileName = #"c:\Windows\System32\cmd.exe";
proc.StartInfo.Arguments = "/c cscript //nologo " + scriptPath;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
proc.WaitForExit();
string response = proc.StandardOutput.ReadToEnd();
response += proc.StandardError.ReadToEnd();
return response;
}
Running a batch file or any process per say from an ASPX page is futile as IIS does not run under a true Windows User Context. Because of this, regardless of how many settings and rights you give to the user that the AppPool is running under or whatever type of config changes you make, it simply will never work. I ran into the same problem quite a while back and basically it's impossible.
See my previous questions (and comments), along with accepted answer for possible "conceptual" solution to your current problem, here:
Process.Start won't work
What about not using "cmd"?
Process proc = new Process ();
proc.StartInfo.FileName = #"c:\mypath\myfile.cmd";
I want to run python code from C# through command Prompt.The Code is attached below
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.WorkingDirectory = #"d:";
p.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.Start();
p.StandardInput.WriteLine(#"cd D:\python-source\mypgms");
p.StandardInput.WriteLine(#"main.py -i example-8.xml -o output-8.xml");
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine("Output:");
Console.WriteLine(output);
Output :
D:\python-source\mypgms>main.py -i example-8.xml -o output-8.xml
D:\python-source\mypgms>
But nothing happened.Actually main.py is my main program and it takes 2 arguments. one is input xml file and another one is converted output xml file.
But i dont know how to run this python script from C# through command prompt. Please Guide me to get out of this issue...
Thanks & Regards,
P.SARAVANAN
I think you are mistaken in executing cmd.exe. I'd say you should be executing python.exe, or perhaps executing main.py with UseShellExecute set to true.
At the moment, your code blocks at p.WaitForExit() because cmd.exe is waiting for your input. You would need to type exit to make cmd.exe terminate. You could add this to your code:
p.StandardInput.WriteLine(#"exit");
But I would just cut out cmd.exe altogether and call python.exe directly. So far as I can see, cmd.exe is just adding extra complexity for absolutely no benefit.
I think you need something along these lines:
var p = new Process();
p.StartInfo.FileName = #"Python.exe";
p.StartInfo.Arguments = "main.py input.xml output.xml";
p.StartInfo.WorkingDirectory = #"D:\python-source \mypgms";
p.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
p.WaitForExit();
Also the Python script appears to output to a file rather than to stdout. So when you do p.StandardOutput.ReadToEnd() there will be nothing there.
Why not host IronPython in your app and then execute the script?
http://blogs.msdn.com/b/charlie/archive/2009/10/25/hosting-ironpython-in-a-c-4-0-program.aspx
http://www.codeproject.com/Articles/53611/Embedding-IronPython-in-a-C-Application
or use py2exe to pragmatically convert your python script to exe program.
detail steps...
download and install py2exe.
put your main.py input.xml and output.xml in c:\temp\
create setup.py and put it in folder above too
setup.py should contain...
from distutils.core import setup
import py2exe
setup(console=['main.py'])
your c# code then can be...
var proc = new Process();
proc.StartInfo.FileName = #"Python.exe";
proc.StartInfo.Arguments = #"setup.py py2exe";
proc.StartInfo.WorkingDirectory = #"C:\temp\";
proc.Start();
proc.WaitForExit();
proc.StartInfo.FileName = #"C:\temp\dist\main.exe";
proc.StartInfo.Arguments = "input.xml output.xml";
proc.Start();
proc.WaitForExit();
Long story short...
This doesnt work:
Process p = new Process();
p.StartInfo.FileName = #"External\PsExec.exe";
string file = String.Concat(Path.Combine(Environment.CurrentDirectory,"temp"),#"\iisreset",DateTime.Now.ToString("ddMMyyyy-hhmmssss"),".txt");
p.StartInfo.Arguments = String.Format("-s -u {0}\\{1} -p {2} \\\\{3} iisreset > \"{4}\"", Domain,UserName, Password, machineIP, file);
p.StartInfo.CreateNoWindow = true;
p.Start();
p.WaitForExit();
I'm getting a RPC Unavailable message.
But when I access the command line in the program folder, then i run this: (with the correct parameters), exactly like I specified in the filename/arguments...
External\PsExec.exe -s -u [user] -p [password] \\[ip] iisreset > "[path]"
It works!
Do I have to specify anything else in the C# Process ? What could be possibly happening?
Thanks in advance!
EDIT: It works if I put cmd as the FileName and /c PsExec.exe before the arguments. The problem is this way it always show the window.
Instead of using p.startinfo.arguments use p.standardinput.writeline(command)
string PSPath = #"C:\PSTools\PsExec.exe";
fullcommand = PSPath + " -u " + userName + " -p " + password + " \\\\" + remoteMachine + " -h cmd.exe /c " + command + "";
Console.Clear();
//Console.WriteLine(fullcommand);
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();
process.StandardInput.WriteLine(fullcommand);
process.StandardInput.Flush();
process.StandardInput.Close();
Console.WriteLine("*****Command*****");
Console.WriteLine(fullcommand);
Console.WriteLine("*****Output*****");
Console.WriteLine(process.StandardOutput.ReadToEnd());
Console.WriteLine("*****Error*****");
Console.WriteLine(process.StandardError.ReadToEnd());
Console.WriteLine("*****Exit*****");
process.WaitForExit();
Console.WriteLine("Again ?");
You cannot redirect standard output using the arguments the way you are doing. That's not how things actually work.
At the command line, your arguments end when the command interpreter sees the >, and it begins the process of redirecting standard output to the filename.
To accomplish this in C# you need to use the RedirectStandardOutput property of the StartInfo class, then read from the Process.StandardOutput stream and write to a file.
The MSDN documentation for RedirectStandardOutput has a short example you can use to get started.
iisreset [machinename] -
you don't need psexec