At the moment I'm developing a small wrapper around CMD using ProcessStartInfo, trying to emulate the command window and adding some extra functionality that I desperately need.
This WINFORM application is a multitab app so that you can start multiple 'sessions'. Furthermore, since the content is stored in a richtextbox, I can easily copy it and more importantly search the console log.
Up till now everything seems to work fine, but when I ask for the current directory, I see the location of this app, which is fine. But when I go one directory up, it does not seem to work.
I'm pretty sure I'm doing something wrong. Could somepoint point me out what it is, what I'm doing wrong? Here is the code excerpt that deals with the execution of the code.
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd");
procStartInfo.RedirectStandardOutput = true;
procStartInfo.RedirectStandardError = true;
procStartInfo.RedirectStandardInput = true;
procStartInfo.UseShellExecute = false;
// Do not create window.
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(onOutputDataReceived);
proc.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(onErrorDataReceived);
proc.Start();
proc.StandardInput.WriteLine("/c " + cmd);
proc.StandardInput.Close();
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
proc.WaitForExit();
You seem to be starting a new process each time you want to execute a command. If you want the environment (like current path) to stay the same between commands, you will need to either save the environment and load it into your new process, or keep a single process open.
Related
using this Code
Process process = new Process();
// p.EnableRaisingEvents = true;
process.EnableRaisingEvents = true;
process.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.LoadUserProfile = false;
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = #"C:\putty.exe"; ; // Gets or sets the application or document to start.
process.StartInfo.Arguments = "-serial com31 -sercfg 9600,8,n,1,N";//Gets or sets the set of command-line arguments to use when starting the application
Thread.Sleep(1000);
process.Start();//Starts (or reuses) the process resource that is specified by the StartInfo property of this Process component and associates it with the component.
process.BeginOutputReadLine();
process.WaitForExit(); // wait forever with ping
I'm trying to open putty in console application , but any timr I use it it opens in New windows and I cant get to output of the process using process.OutputDataReceived event
I'm using code very similar to this to open Iperf and it works fine
What am I missing here ?
Putty is not a console application and therefore does not provide output on it's stdout and stderr streams.
And since it is a windowed application it does not care whether you start it with the CreateNoWindow flag. Try and start notepad.exe with that flag, you will see it appearing obviously.
There is however a programm by the creators of Putty that provides the functionality you need.
It's called Plink.exe and you can download it on their homepage
I have a complete command line application in c# which has different modules and depends on multiple dlls etc.
Now, i want to call that CLI app with an another UI app. But the issue is that the Thread part of the CLI applicaiton is not working and the control just jumps to the end. So, is there any way I can handle this scenario?
For example: I have app CLI.exe which i want to call so i have written following code:
Process proc = new Process();
proc.StartInfo.FileName = CLI.exe;
proc.StartInfo.Arguments = args;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardInput = true;
proc.Start();
proc.WaitForExit();
Now this calls the app i want to call. The following code is there in my app CLI.exe
System.Console.WriteLine("Start app {0}", args);
do
{
System.Threading.Thread.Sleep(1000);
} while (model.Exited == false);
System.Console.WriteLine("Finish app");
Now, in between the do while loop, I do a lot pf processing while the model.exit don't get false.
But it starts the app, writes the Start app message and just after that it writes the Finish app and the processing in between never happened.
model.Exit also went true without processing.
Also, if I run the CLI.exe with the batch command or run the CLI.exe on cmd it runs perfectly.
So, any idea as how to manage this?
proc.WaitForExit(); freezes your process until child process is finished. Remove that and handle process exit in another way, for example, using events:
proc.EnableRaisingEvents = true;
proc.Exited += OnExit;
I'm trying to run a command via command prompt from an ASP.Net web application. I can see the process start in task manager on the web server, however the process just sits there and never exits nor does it run the commands I specified.
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C " +command;
startInfo.UserName = "myuser";
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.Domain = "mydomain";
startInfo.CreateNoWindow = true;
String pass = "mypass";
System.Security.SecureString secPass = new System.Security.SecureString();
foreach (char c in pass.ToCharArray())
{
secPass.AppendChar(c);
}
secPass.MakeReadOnly();
startInfo.Password = secPass;
process.StartInfo = startInfo;
process.Start();
//output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
process.Close();
I've tried both with and without reading the standard output.
The application will hang on process.WaitForExit(); until I kill the process via task manager.
I think we need to understand what commands you are actually trying to process in order to determine what's going on. Also we need to know what OS the server is running.
For example, I did see in your comments where you tried "echo test > C:\test.txt" Under Windows Server 2008 (and Windows 7) the root directory requires administrator permissions in order to create files. If this is executing under IIS, my guess is that your IIS user isn't an administrator and you are getting security exceptions.
Also, a number of commands may require elevated priviledges due to UAC. I don't remember exactly, but I'm guessing that if those commands are being caught by UAC then the process is waiting for UAC confirmation... Which I believe you cannot supply via a command line.
This type of problem won't be seen if you log into the machine and execute it directly... unless you are logging in with the worker process user account.
So, the very first thing you need to do is figure out what it is you are trying to run and see if the user the worker process is executing under can even perform those actions. Security is there to protect you, so be careful about granting additional permissions to the user.
The reason why it might work on one machine versus another again depends on the OS's those machines are running and the configuration of the user the commands are executing under.
If this is truly a security issue, as I suspect, then you should post a question on serverfault.com to ask what permission sets you need to execute various commands under your worker process user.
You might look at the machines event logs to see if there were any warnings or errors thrown about the command. Sometimes things like this can show up there to give you a bit more information as to what happened.
Once passed to CMD, the control has passed to the shell. It's better to add a close it like this:
private void closeSubProcess()
{
Process[] currentProcesses = Process.GetProcesses();
foreach (Process p in currentProcesses)
{
string s = p.ProcessName;
s = s.ToLower();
if (s.CompareTo("YOURPROGRAMNAMEHERE") == 0)
{
p.CloseMainWindow();
p.Close();
}
}
}
I am calling cmd.exe to start a node module in Windows. npm obviously must be installed first, along with the node module I need, and then I can call the module with args in C#. Problem was, the cmd.exe would not shut off, I'd have to use Task Mgr (just like this question!).
//This requires npm, and the module installed by npm...
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.UseShellExecute = true; //closes command window
psi.Arguments = "/c <nodemodulename>" + file1 + ".txt " + file2 + ".log";
Process p = Process.Start(psi);
p.Close();
The /c argument was key to closing down cmd.exe. When I started out, I had put in the /K argument, which keeps the darned thing running. Solved. Hope this helps. (This is like ancient, but we always forget)
I want to use shell executable in order to respect user preferences of application to be started, but I also need to know when that particular application is closed.
Process editProcess = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = filename;
startInfo.Verb = "edit";
startInfo.UseShellExecute = true;
editProcess.StartInfo = startInfo;
// start the default editor
editProcess.Start();
editProcess.WaitForExit();
WaitForExit seems to return when the shell process exits and not when the real process exits.
Is there a better way of knowing when started application is exited than manually parsing registry, finding correct application to start and explicitly start that app without shell execute?
Handle the process exited event:
editProcess.Exited += process_Exited;
I have some fairly straightforward code to open up files using a Process object:
var proc = new Process();
proc.StartInfo.FileName = attachmentPath;
proc.StartInfo.UseShellExecute = true;
proc.Start();
Every once in a while, the window that opens from this process starting open behind all my currently open windows. I don't see any pattern or consistency to why this happens. Does anybody have an idea why this happens, or how I can work around it? Thanks!
Windows has discouraged applications from stealing focus for a while; the rules around it aren't really documented, presumably to prevent applications from working around them.
However, you could give this a try:
var proc = new Process();
proc.StartInfo.FileName = attachmentPath;
proc.StartInfo.UseShellExecute = true;
proc.Start();
//Wait for window to spin up
proc.WaitForInputIdle();
BringWindowToTop(proc.MainWindowHandle);
Define BringWindowToTop with p/invoke.