My updater is failing to close my main program (C#) - 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();
}

Related

Detect Single Windows Process Exit Event C#

Okay so ive got another one, Right now im working on a button, called installbtn in code.
Right now i have in my code.
private void installbtn_Click(object sender, EventArgs e)
{
// Access the internal exe resource pcc - the pcc is Path Copy Copy, which i am using as a
// requirement to use this software
byte[] pccFile = Properties.Resources.pcc;
// The resource pcc.exe as a binary called pcc which is then used as a byte called pccFile
string pccExe = Path.Combine(Path.GetTempPath(), "pcc.exe");
// The Executable and its filename + Extenstion
using (FileStream exeFile = new FileStream(pccExe, FileMode.Create))
exeFile.Write(pccFile, 0, pccFile.Length);
// Write the file to users temp dir
Process.Start(pccExe);
// Start the Installer
installbtn.Text = "Installing...";
StatusLabel1.Text = "Installing PCC Now...";
// Indicate on the form, the current process status.
// Here i want the application to check if pccExe has closed
// after the user has installed the component and its process "pcc.exe" exits
MessageBox.Show("Module Installed /r/nPlease Start the Application", "Application Module Installed");
installbtn.Text = "Restart Now!";
StatusLabel1.Text = "Please Restart the Application";
// and if it has then show a message box and reflect in the form
// i want it to quit and restart the application after the message box is closed
}
now when the installer finishes, i would like to be able to detect when the installer closes ("pcc.exe") after install and then reload the application once it has. Not sure if its possible but i would appreciate the help.
Thanks Shaun.
You could use Process.WaitForExit()
The WaitForExit() overload is used to make the current thread wait
until the associated process terminates. This method instructs the
Process component to wait an infinite amount of time for the process
and event handlers to exit
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
process.StartInfo = startInfo;
startInfo.FileName = exeToRun;
process.Start();
process.WaitForExit();
Start returns a Process object, on which you can wait (or start a thread that waits, etc.).

launch exe with params, but program closes instantly after opening?

I am writing a client for my gaming community and one of the functions of this client is to launch a game via the client with parameters that will enable our community mod pack on launch.
When I press the button, the game begins to launch and as soon as the program opens (the icon pops up in the task bar), it closes instantly.
Is there something I am missing that is needed to keep the launched exe running?
Here is my code:
private void btnLaunchGame_Click(object sender, EventArgs e)
{
string armaPath = gameDir+"/Expansion/beta/";
string filename = Path.Combine(armaPath, "arma2oa.exe");
string launchParams = "-noSplash -noFilePatching -showScriptErrors \"-name=Meta\" \"-mod=I:/Steam/steamapps/common/Arma 2;expansion;expansion/beta;expansion/beta/expansion;servermods/#HC_DAYZ;servermods/#HC_WEAPONS;servermods/#HC_EXTRAS;servermods/#HC_ACE\"";
System.Diagnostics.Process.Start(filename, launchParams);
}//close Game Launch
Any ideas is appreciated!
I have a .bat file that will execute the game flawlessly with the launch args listed below, this could possibly help pinpoint the cause of my problem:
http://puu.sh/5CGKk.png (couldn't get code to paste in a readable format).
Try using Process:
Process process = new Process();
process.StartInfo.FileName = "arma2oa.exe";
process.StartInfo.Arguments = "-noSplash -noFilePatching -showScriptErrors \"-name=Meta\" \"-mod=I:/Steam/steamapps/common/Arma 2;expansion;expansion/beta;expansion/beta/expansion;servermods/#HC_DAYZ;servermods/#HC_WEAPONS;servermods/#HC_EXTRAS;servermods/#HC_ACE\"";
process.StartInfo.WorkingDirectory = gameDir + "/Expansion/beta/";
process.Start();
It may be what exe require working directory to be set. Or it will crash, unable to load resources.
If that doesn't works, then perhaps you need to add
process.WaitForInputIdle();
before exiting function running process. I don't know why, but running Acrobat Reader without this wait may sometimes cause a wierd effect: Acrobat is running, but the document, passed via arguments, is not shown. Perhaps something to do with Garbage collector or Process itself.
Try following
using (Process process = new Process())
{
ProcessStartInfo startInfo = new ProcessStartInfo("C:\Program Files\Arma2oa\Arma2oa.exe");
startInfo.Arguments = "-noSplash -noFilePatching -showScriptErrors \"-name=Meta\" \"-mod=I:/Steam/steamapps/common/Arma 2;expansion;expansion/beta;expansion/beta/expansion;servermods/#HC_DAYZ;servermods/#HC_WEAPONS;servermods/#HC_EXTRAS;servermods/#HC_ACE\"";
process.StartInfo = startInfo;
process.Start();
}

Why would Process.WaitForExit throw a "no process" exception even when a process does exist?

I have a windows service containing this code:
public static void ExtractTextInner(string source, string destination)
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = EXTRACTOR_EXE_FILEPATH
startInfo.Arguments = "\"" + source + "\" \"" + destination + "\"";
startInfo.CreateNoWindow = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
int exitCode = process.ExitCode;
process.Close();
if (exitCode != 0)
{
switch (exitCode)
{
case 1:
throw new ApplicationException("IFilter Extraction Failed");
default:
throw new ApplicationException("Unknown Exit Code:" + exitCode.ToString());
}
}
}
The purpose of this code is run an IFilter extract on a document, we use a seperate process because some IFilters are notoriously flaky.
Now this code runs perfectly fine on Windows 7 and Server 2008 R2 boxes but on a Windows Server 2003 the WaitForExit immediately throws a "There is no process associated with this Process object" exception. The process does exist and completes its task without a problem.
Anyone seen this? Can anyone shed any light on why WaitForExit would thow this error?
Additional Info
If I place this code in a Console App and run it works fine on the Windws Server 2003 box as well, hence it would appear to be a specific problem running this in a Service on a Windows Server 2003 box.
When starting processes, with the System.Diagnostics.Process class, the system can either use CreateProcess or ShellExecuteEx Win32 function. When using CreateProcess only executable files can be started. When using ShellExecuteEx, any file which can be started using the "Start->Run" command from the shell.
However these are completely different ways of starting processes. ShellExecuteEx involves the shell, and can, for example, re-use an existing instance of Word or Excel to open a document, by using the information stored under the HKCR\<progid>\shell\<verb> registry key. This may involve for example using DDE to search for and then activate an existing Excel instance.
See documentation on ShellExecuteEx's SHELLEXECUTEINFO:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb759784(v=vs.85).aspx
Note that ShellExecuteEx may or may not return an hProcess depending on whether a new process was started. This is the behavior which you are seeing.
CreateProcess is a lower-level function and creates a process directly, and simply passes the equivalent arguments. It always returns a process handle.
Note: Since you seem to be starting an executable file, it is a bit surprising that no hProcess is returned by ShellExecuteEx. Nevertheless, if you want to ensure you get a process handle, using UseShellExecute = false is the correct thing to do.

Start a new process and Killing the current process

I want to start a new process B.exe from the current executing process A.exe.
And as soon as B.exe is launched I want to kill A.exe (the current executing process).
Though I can start B.exe I cannot close my current process i.e A.exe.
Code I use is:
//Start the BT Setup Process
ProcessStartInfo startInfo = new ProcessStartInfo(#"C:\TEST\B.exe");
Process.Start(startInfo);
//Terminate the FSA
Process[] myProcess = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);
foreach (Process process in myProcess)
{
process.CloseMainWindow();
//all the windows messages has to be processed in the msg queue
//hence call to Application DoEvents forces the MSG
Application.DoEvents();
}
Why do you want to close A from B while A cat start B and then close by itself?
Process.Start("A.exe");
Process.GetCurrentProcess().Kill(); // or Application.Exit(); or anything else
If you're falling into this quest of starting a process, and kill your own process after, use Environment.Exit(0), not Application.Exit().
Try Process.Kill() instead of Process.CloseMainWindow().
I know this is old but in .net 4.0 you can do
ProcessStartInfo startInfo = new ProcessStartInfo(#"C:\TEST\B.exe");
startInfo.UseShellExecute = true;//This should not block your program
Process.Start(startInfo);
Then Application.Exit or whatever
I tested with a winforms application using the close form method after launching a console app that just blocks on Console.readline();
If you just want to close the current process you should be able to just call Application.Exit rather than looping through and closing processes.

how to execute console application from windows form?

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

Categories

Resources