how to execute console application from windows form? - c#

I want to run a console application (eg app.exe) from a windows form load event.
I'v tried System.Diagnostics.Process.Start(), But after it opens app.exe, it closes it immidiately.
Is there any way that I can run app.exe and leave it open?

If you are just wanting the console window to stay open, you could run it with something like this command:
System.Diagnostics.Process.Start( #"cmd.exe", #"/k c:\path\my.exe" );

Try doing this:
string cmdexePath = #"C:\Windows\System32\cmd.exe";
//notice the quotes around the below string...
string myApplication = "\"C:\\Windows\\System32\\ftp.exe\"";
//the /K keeps the CMD window open - even if your windows app closes
string cmdArguments = String.Format("/K {0}", myApplication);
ProcessStartInfo psi = new ProcessStartInfo(cmdexePath, cmdArguments);
Process p = new Process();
p.StartInfo = psi;
p.Start();
I think this will get you the behavior you are trying for. Assuming you weren't just trying to see the output in the command window. If you just want to see the output, you have several versions of that answer already. This is just how you can run your app and keep the console open.
Hope this helps. Good luck.

If app.exe does nothing, or finishes its work quickly (i.e. simply prints "Hello World" and returns), it will behave the way you just explained. If you want app.exe to stay open after its work is done, put some sort of completion message followed by Console.ReadKey(); in the console application.

If you can change the code of app.exe, just add Console.In.Read() to make it wait for a key press.

app.exe can end with Console.ReadLine() assuming it too is a C# application where you control the source code.

You have one of two problems, given your master/slave application setup:
Your master app is opening, displaying a form, that form runs the slave app and closes immediately, even though the slave app is still running.
Your master app is opening, displaying a form, that form runs the slave app which closes immediately.
For the first problem, you need to wait/block for the process to complete (i.e. Process.WaitForExit().
For the second problem, it sounds like the slave app has done what it needs to (or thrown an exception) and is closing immediately. Try running it with the same parameters from a command prompt and check the output.

If you have control over app.exe, you should be aware of how it functions so I will assume that you do not have control over it's inner workings. In that case, you can try passing a help flag which may or may not give you more info on how to call app.exe. Try something like this:
private startApp()
{
string command = " -h"; //common help flag for console apps
System.Diagnostics.Process pRun;
pRun = new System.Diagnostics.Process();
pRun.EnableRaisingEvents = true;
pRun.Exited += new EventHandler(pRun_Exited);
pRun.StartInfo.FileName = "app.exe";
pRun.StartInfo.Arguments = command;
pRun.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal
pRun.Start();
pRun.WaitForExit();
}
private void pRun_Exited(object sender, EventArgs e)
{
//Do Something Here
}

Create a new text file, name it app.bat and put this in there:
app.exe
pause
Now have your form point to that bat file.

In your console application, type:
Console.ReadLine(); - Use this piece of code to wait until you press enter
Console.ReadKey(); - Use this code to wait until you press a key

Related

Executing cmd commands with complex output in c#

I often find myself using different commands on pc's to check stuff in the system and I wanted to basically create a small standalone exe that will execute all my common commands and give me the output of each of them without me entering them manually...
I want to note that I know this isn't the first question on google on the subject of executing a cmd command with c# but non fit my command requirements, for example many of them execute commands such as copy or move or make and non of them have a complex output, I want to execute for example the "sfc /scannow" command, which outputs a progress bar which measures the progress of course and a final output, the issue with that is I have tried many ways to attempt that but all failed, a shell execution works very well with opening another cmd windows and even requiring elevation but as soon as the progress bar ends and it displays the final output it crashes (and thus I can't see the final output), with shell execution off (executing via the main window) it either doesn't show the progress bar at all and just shows the final output, or shows nothing, or it does show the progress bar, but with each increment it's a new line which obviously doesn't look right...
this is my code:
public static void ExecuteCommand(string command) {
Process prc = new Process();
ProcessStartInfo info = new ProcessStartInfo
{
Verb = "runas",
FileName = "cmd.exe",
UseShellExecute = true,
Arguments = "/c" + command
};
prc.StartInfo = info;
prc.Start();
prc.WaitForExit();
prc.Close();
}
if anyone can think of a fix please do tell me, I have been stuck on this for about 3 days...
Turns out the culprit was "/c", if I change it to "/K" the windows stays open until I close it manually like I wanted.

My updater is failing to close my main program (C#)

I have an updater, which is called via the main program once an update is detected (from a remote XML file), first it checks whether the process is open
if (clsProcess.ProcessName.ToLower().Contains("conkinator-bot.exe"))
{
clsProcess.CloseMainWindow();
return true;
}
(this gets run for every process until it finds it (foreach loop))
the updater then downloads the file:
client.DownloadFile(url, "Conkinator-Bot-new.exe");
and then it attempts to delete the current one and rename it:
File.Delete("Conkinator-Bot.exe");
File.Move("Conkinator-Bot-new.exe", "Conkinator-Bot.exe");
but the error that I get when this occurs is the following:
Unhandled Exception: System.UnauthorizedAccessException: Access to the path 'D:\Conkinator's Skype Tool\Conkinator-Bot.exe' is denied.
however the new version of the program DOES download.
Just because the main window is closed doesn't mean the process is over. You need to wait for the process to exit after you close the main window:
clsProcess.WaitForExit();
Ideally, you'd use a timeout - there might be something preventing the window from closing, or the process might have a faulty exit mechanism.
It is a lot easier to close the main program from inside the main program itself.
string msg = "To update the application we need to close it. Do you want to continue?";
if (DialogResult.Yes == MessageBox.Show(msg, title, MessageBoxButtons.YesNo))
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "YourUpdaterFile.exe";
psi.WindowStyle = ProcessWindowStyle.Normal;
// Assuming a lot here but to just show the options available....
psi.WorkingDirectory = Path.GetDirectoryName(Application.ExecutablePath);
Process.Start(psi);
Application.Exit();
}

How to check a Window already opened when button is clicked?

I am Working in Visual Studio 2008 Winforms Application project in Windows 7 (32 bit).I am doing the project in C#.
I have placed some buttons in a tab and added actions for that once it is clicked. While clicking the button am just running a .exe file in its action part.
My problem is that, i opened a window by clicking one button(so the .exe file is running), now while am clicking the button again it is opening same window again irrespective of checking that it is open or not. I want to solve this issue,as when a window is opened it must not open again on another click on same button. How to solve this issue. ?
Please help....
Thanks in advance..
You could check if the process is already running, when re-clicking the button:
private void btnStartExecutable_Click(object sender, EventArgs e)
{
Process[] processName = Process.GetProcessesByName("InsertProcessNameHere");
if (pname.Length == 0)
{
MessageBox.Show("Application isn't running yet.");
//Start application here
Process.Start("InsertProcessNameHere");
}
else
{
MessageBox.Show("Application is already running.");
//Don't start application, since it has been started already
}
}
You can try this:
bool processExited = true;
private void button1_Click(object sender, EventArgs e)
{
if (processExited)
{
Process process = new Process();
process.EnableRaisingEvents = true;
process.Exited += MyProcessExited;
process.StartInfo = new ProcessStartInfo();
process.StartInfo.FileName = "notepad.exe";
process.Start();
processExited = false;
}
else
{
MessageBox.Show("Still running");
}
}
void MyProcessExited(object sender, EventArgs e)
{
processExited = true;
}
The right answer here IMHO is that unless the two application shares a common resource or can talk to each other through some channel, there is no safe and efficient way to achieve what you want. Since the process is external, it could already be running before your calling app starts, or even while it's already running. You won't be able to tell if the process has been started from your app or not.
By the time I'm writing this your question does not yet state if you are in liberty to modify the external app you are calling. If you are however, using a Mutex would be a quick and easy way to solve your problem.
In your external app, whenever you want to make the other app aware of whatever condition you want (be it that the process is running or that a specific window is opened), have a Mutex instance created like this:
var mutex = new Threading.Mutex(true, "mutex unique identifier");
And in your calling app, try to create a Mutex instance with the same identifier:
bool alreadyExists;
var mutex = new Threading.Mutex(false, "mutex unique identifier", out alreadyExists);
Here the alreadyExists variable will tell you whether or not the external process is running or not. This is much safer than trying to identify it via its name, as other processes could have the same or a new version could be of a different name. Of course, the mutex identifier must be as unique as possible (like a Guid), otherwise you may encounter the same problem. ;)
Whenever you feel like the mutex must be released (at external app level), release it:
mutex.ReleaseMutex();
Note that if the process ends the mutex will be automatically released by the OS.
If the external app isn't a .NET based app, you can still create a mutex with Win32 API functions.
Thanks for the support.. I got the answer like this..
1) Creating an event'Exit' for the process in function button click
2) Define a function for the exit event where you set a flag
3) Check the flag is set or not everytime while opening the process in the function button click
Event for Exit: 'P' is the name of process:
p.Exited += new EventHandler(p_Exited);
p_Exited will be the function name where we will set the flag.
Thanks all...
If you know the name of the process that gets started or the path the .exe is run from you can use the Process class to check to see if it is currently running.
http://msdn.microsoft.com/en-us/library/system.diagnostics.process(v=vs.110).aspx

Execute process/program silently

I am creating a wpf application that needs a prerequisite. If that prerequisites is not met then I ask the user if he will like to install the prerequisite that happens to be: Microsoft Visual C++ 2010 SP1 Redistributable Package.
So if the user chose to install the prerequisite I will execute vcredist_x86.exe (that is the file that get's downloaded from the first link that I provided).
Then on my application I will be able to tell when the installation is complete by doing something like:
ProcessStartInfo psi = new ProcessStartInfo(#"vcredist_x86.exe");
var p = new Process(); p.StartInfo = psi;
p.Start(); //start the process
p.WaitForExit(); // wait for the installation to finish
// installation should be done now
Ok everything works great so far. The problem is that I have a progress bar in my wpf application and I will like to show the progress in there.
I have been able to show the progress of the installation by doing the following:
There is a program called AutoIt that it is great for automating simple tasks. For example I can easily detect if a window exists with autoit by using something like:
I could then compile that script and create a very small executable. In that executable I will return 1 if the specified window exists or 0 otherwise.
When the user moves to the next window my script might return 2 because that is a different window. AutoIt can also see the progress of a progress bar of a window!!! so if that script returns 80 for example then I will update my progress to 80% for instance.
I do that by doing something like:
// start the autoitExecutable....
// wait for executable to exit usually takes 10 miliseconds it is fast
if (autoitProcess.ExitCode == 1)
{
// do somthing
}else if(autoitProcess.ExitCode == 2)
{
// do something else
} //etc....
As you can see I have to execute that script every 1 second to detect what changes have been done in order to update my progress bar in WPF. That works but every time I execute that executable with c# I get the:
cursor for about 500 milliseconds then on the next second it appears again. That becomes annoying even though no windows show up. It will be nice if I could get rid of that cursor and execute that executable silently somehow. when I execute the autoit executable there are no windows that show up nor nothing else.
P.S.
I know I could use c# to check for the existance of a window and maybe see the value of other window's handler's just like autoit is able to do it but it is so simple to create those programs with AutoIt and it will be nice if I could use AutoIt instead of C# for this kind of taks
I saw this behavior when the exe was set to "windows application" rather than "console application".
Changing the type to console no longer gives a busy cursor at launch.
You could add an event handler as well for example
System.Diagnostics.ProcessStartInfo p = new
System.Diagnostics.ProcessStartInfo(#"vcredist_x86.exe") ;
p.Arguments="-RunForever";
proc = new System.Diagnostics.Process();
proc.StartInfo = p;
proc.EnableRaisingEvents = true;
proc.Exited += new EventHandler(myProcess_Exited);
proc.Start();
inside the event if I wanted to do something like this
// Inside the form class:
private System.Diagnostics.Process proc;
private void myProcess_Exited(object sender, System.EventArgs e)
{
button3.BackColor=Color.LightGreen; //success indicator
}
if you wanted to do this in a While Loop you could also do something like this for example
but you would have to change the params to fit your case
example code you can utilize
while(!autoitProcess.WaitForExit(someTimeout))
{
if(ShouldCancel)
{
break;
}
}
does this make sense or help out...?

C#/.NET: Closing another process outside the main window

I just wanna ask your opinion/suggestion on how to 'terminate' a running application/process is C#
Right now, I do have the following codes:
Process myProcess;
private void btnOpen_Click(object sender, RoutedEventArgs e)
{
DirectoryInfo di = new DirectoryInfo(System.Environment.GetFolderPath(Environment.SpecialFolder.Programs));
myProcess = Process.Start(di + #"\Wosk\Wosk.appref-ms"); // opening a file coming for Startup Menu
}
private void btnClose_Click(object sender, RoutedEventArgs e)
{
myProcess.Kill(); // not working - Cannot process request because the process has exited
}
I also tried myProcess.Close(); but nothing's happening.
You should have a look at
Process.HasExited Property
A process can terminate independently
of your code. If you started the
process using this component, the
system updates the value of HasExited
automatically, even if the associated
process exits independently.
Based on your comment it looks like the Process instance has already exited when you hit the close button. This can happen at any time and it's something you need to guard against. The easiest way is to simply catch the exception that results from calling Kill on an already exited process.
try {
myProcess.Kill();
} catch ( InvalidOperationException ) {
// Process is already finished so nothing to do
}
You are starting a program that was installed with ClickOnce. The .appref-ms is executed by a helper program, rundll32.exe, that starts the process and quickly exits. To terminate the started process, you'll need to find the actual running .exe with Process.GetProcessesByName() and use the Kill method.
We can't tell you what the process name is, that's contained in the .appref-ms file. But it is easy for you to see with TaskMgr.exe.
Process[] islemler = Process.GetProcessesByName("osk");
foreach (Process islem in islemler)
islem.Kill();
First please replace:
di + #"\Wosk\Wosk.appref-ms"
with:
Path.Combine(di.FullName, #"Wosk\Wosk.appref-ms")
Now to the point: I don't know what Wosk.appref-ms is or how this process is started. If this is a file it will be opened with the default program associated with this file extension. The problem could be related to the fact that the process you start only starts another process and terminates immediately. That's why when you try to kill it it says that it has already exited, but the actual process it spawned is still running. In this case you will have to enumerate through the running processes with Process.GetProcesses(), find the process and stop it.

Categories

Resources