I'm trying to troubleshoot why the following function isn't working.
public void RunCmd()
{
string strCmdText;
strCmdText = "/C [enter command stuff here]";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
}
However whenever I try to run it or throw in some breakpoints, command opens, shows an error, and then closes really quickly (so quickly that I can't read anything).
Is there a way I can halt the program or figure out what's going on? Breakpoints don't seem to be working.
When I directly type it in Command Prompt instead of running it via this c# script, it the command works fine.
try this:
strCmdText = "/K [enter command stuff here]";
/C Carries out the command specified by string and then terminates
/K Carries out the command specified by string but remains
Maybe try adding a pause command?
There are a various options. Using /K will prevent the window from closing.
You can also edit your command to add a SLEEP after the main call. For example, the following will wait 2 seconds before exiting:
public void RunCmd()
{
string strCmdText = "/C \"[enter command stuff here]\" & \"SLEEP 2\"";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
}
Process.Start has two parameters there: the process name and the arguments to pass to the process. CMD is having a problem understanding what the argument "[enter" is. If it is not an argument CMD understands, it will immediately exit.
cin.get()
That waits for a keyboard press from the user.
create temp folder under c: then append " < c:\temp\log.txt" to the end of command. this writes the output to a file
In addition to the tip about using /K vs /C to create a shell that 'lingers', you'll probably want to inject an empty "set" command to see what environmental variables (and paths) are set in the spawned shell. In all likelihood, the difference between the successful run of your script in your own shell session and the one that fails in the spawned shell, is the environment settings in which it is run.
Related
I created an c# wpf application that accepts command line parameters. If I open cmd and call the application with multiple parameters, the parameters are passed in correctly.
But if I do that same thing but from a batch file it passes the parameters as one parameter combined together rather then multiple parameters. I had the application output the parameters and it looks like all the spaces (which is what separates each command line parameter) were changed to a weird á character.
is there something special I need to do to get the parameters passed correctly?
I have tried resaving the file with ASCII encoding but that didn't change anything.
I also tried adding this line to the batch file
chcp 1253>NUL
that changed it so the á wasn't there but it still had it was one parameter.
seems like the spaces are just not getting passed as a space.
here is what my batch file line looks like, each parameter is separated by a space.
start /wait C:\MyTestApp.exe /SILENT /BOOLAGREEMENT=TRUE /BOOLGAOPTIN=TRUE
--UPDATE--Adding steps to reproduce...
this is just generic code similar to what I did just condensed
create c# wpf app.
in App.xaml.cs override OnStartup
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
this.ShutdownMode = System.Windows.ShutdownMode.OnMainWindowClose;
bool shutdownapp = false;
MessageBox.Show(string.Join(",", e.Args));
}
build exe.
now launch cmd and cd to the location of the exe.
MyTestApp.exe /param1=test1 /param2=test2
you should get a message box that says
/param1=test1,param2=test2
now create a batch file that has something like this...then run it
test.bat
#echo off
start /wait c:\MyTestApp.exe /param1=test1 /param2=test2
this time the message box should have this...
/param1=test1/param2=test2
Start sees all of that as a CMD to Start.
Is there a reason you actually need to use start? generally, there isn't and you can just call the executable directly.
eg TestMyApp.cmd
#(
SETLOCAL
ECHO OFF
)
REM Call your Command here with all arguments:
"C:\MyTestApp.exe" /SILENT /BOOLAGREEMENT=TRUE /BOOLGAOPTIN=TRUE
If you sincerely require Start.
Then you should be aware that it treats all of that command as a single string, by nature, which is what you're running into, so you should be calling a new CMD instance explicitly instead in that case:
START "" /WAIT CMD /C ""C:\MyTestApp.exe" /SILENT /BOOLAGREEMENT=TRUE /BOOLGAOPTIN=TRUE"
But that is a lot of extra work to go through if not needed.
Alternatively, you can also just run a CMD instance directly:
CMD /C ""C:\MyTestApp.exe" /SILENT /BOOLAGREEMENT=TRUE /BOOLGAOPTIN=TRUE"
Or Use CALL:
CALL "C:\MyTestApp.exe" /SILENT /BOOLAGREEMENT=TRUE /BOOLGAOPTIN=TRUE
Hi i am able to execute a remote process using Wmi and was able to get return Value and Process Id of the Process. Is there any way to get the Output of the Process which was started by Wmi. Eg. If i start an exe which prints something in console will i be able to get those values using this Api. Any help is appreciated.
You must redirect the output to a file, then read the file across the network.
Use the CMD.EXE /S /C option to do this.
Example command line to run Program.exe:
CMD.EXE /S /C " "c:\path\to\program.exe" "argument1" "argument2" > "c:\path\to\stdout.txt" 2> "c:\path\to\stderr.txt" "
Then connect to server like this \\servername\c$\path\to\stdout.txt to read the stdout results.
Note: Pay careful attention to the extra quotes around the command to run. These are necessary to ensure the command line is interpreted correctly.
You can use psexec to execute the program.exe and get the stdout by pipe
p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while p.poll() is None:
line = p.stdout.readline()
line = line.strip().decode('gbk')
if line:
print('Subprogram output: [{}]'.format(line))
if p.returncode == 0:
print('Subprogram success')
return True
else:
print('Subprogram failed')
return False
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.
I'm trying to copy a file over to a networked folder on a mapped drive. I tested out COPY in my command line which worked, so I thought I'd try automating the process within C#.
ProcessStartInfo PInfo;
Process P;
PInfo = new ProcessStartInfo("COPY \"" + "c:\\test\\test.txt" + "\" \"" + "w:\\test\\what.txt" + "\"", #"/Z");
PInfo.CreateNoWindow = false; //nowindow
PInfo.UseShellExecute = true; //use shell
P = Process.Start(PInfo);
P.WaitForExit(5000); //give it some time to finish
P.Close();
Raises an exception : System.ComponentModel.Win32Exception (0x80004005): The system cannot find the file specified
What am I missing? Would I have to add anything else to the command parameters?
I've tried File.Copy but it doesn't appear to work (File.Exists("<mappeddriveletter>:\\folder\\file.txt");) brings up false.
This SO post contains an example
Run Command Prompt Commands
how to do it right. You need to call cmd.exe with /c copy as a parameter.
Well, for the technical bit: copy in itself is not an executable, but merely a command interpreted by cmd. So basically, you'd have to start cmd.exe as a process, and pass it a flag that makes it run the copy command (which you'll also have to supply as a parameter).
Anyways, I'd side with Promit and recommend looking into File.Copy or something similar.
e: Ah, missed your comment on Promit's answer when I posted this.
Wouldn't it be a lot easier to use File.Copy ?
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