PDA

View Full Version : Run Process without dependance



MisterIKS
21st November 2010, 09:55
Hey everybody,

we are developing an updater for our software which is started by each of our products and updates all applications at once. We've nearly finished our updater, and it works perfectly fine if we run thge updaters exe directly, but the way we run the updater from within our products causes trouble.

We're using a QProcess within the Product which starts the updater. The updater himself finds running products and terminates them via

bool TerminateAppEnum(HWND hwnd, LPARAM lParam)
{
DWORD dwID ;
GetWindowThreadProcessId(hwnd, &dwID) ;
if(dwID == (DWORD)lParam)
{
PostMessage(hwnd, WM_CLOSE, 0, 0);
PostMessage(hwnd, WM_QUIT, 0, 0);
}
return true;
}
which was the only way we could find terminating the process safely without killing it.

Now as soon as the updater termintes the product it was started from, the updater himself stops with the common windows-message saying that the application has run into a problem and needs to be stopped.

Now we're shure that this is just because the product is listening to the updater process but we coundn't find a way, not even in WinAPI, that simply starts an exe file without any dependence to of from the product.

The only way we've imagined, anthough we're not satisfied with it, was to dynamically write an batch-file with QFile running the updater with a single command and then run it with QProcess and terminate the process some seconds later and remove the file again.

There must be a better way to do that and we really hope that you know a solution WinAPI or not, that could help us. Thanks in advance!

tbscope
21st November 2010, 10:06
As far as I understand you, you want a single program that downloads and updates all your other programs, even when they are already running.

If you start this updater from within any of your running programs, make sure you start it detached from the parent process. This prevents the updater from getting killed when you close all the other programs.

You want to close the other programs gracefully so that data does not get lost.

Instead of using the ugly windows API, why not make use of a local socket. Create a small local server that runs in the background. Start it whenever no server is available when you start one of your programs start. Then let the updater send a message to this local server to gracefully close all the running programs. You can even get feedback from running programs so all messages are displayed in the updater instead of showing multiple dialog boxes etc...

You also might do something like a "suspend to memory" trick so you do not need to ask the user to save anything. You save the current session by yourself in some temporary file/folder. Then close the program, update it, start it again and load the saved session.

Just some ideas of course.

MisterIKS
21st November 2010, 10:42
Thank you for your ideas! The local server is a good idea we also thought of, but we cuncluded that at the moments it's not necessary to have a seperate process running in the background all the time, that's why we came up with the solution of running the updater each time one of our applications starts. Therefore when starting the application there won't be any unsaved data to be stored.

At the moment we only have two applications to be updated and we've added a possibility to update the updater itself, therefore we won't switch to the local server at the moment, but maybe do that in the future.

As I found out the problem of the updater getting stuck is not the fact, that the parent process is terminated, but the termination itself. Here's the code we actually use to terminate the process, it worked fine on our developing system, but fails on two test-systems (Windows XP and 7):

HANDLE hProc;
hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE,pe32.th32ProcessID);
EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM) pe32.th32ProcessID);
if(WaitForSingleObject(hProc, 10000)!=WAIT_OBJECT_0) TerminateProcess(hProc,0);
CloseHandle(hProc);

I hate the winAPI myself, but it was as I said the only way we cound find that didn't just kill the process but, if possible, waits for it to terminate himself. If you have know a different way to do this, I would be pleased to hear! Thanks!

Timoteo
21st November 2010, 20:38
Your code assumes that the user account has full admin rights (sadly, very likely the case on the typical desktop). The way you've got your parent-child relationship setup with the processes is going to cause you trouble.

solution of running the updater each time one of our applications starts

This would require that all of your application suite have full rights, or the updater would not be able to aquire them. Instead you need the updater to be the parent process and launch the child processes with a restricted set of rights. It's simple really: Your updater just takes command line parameters that tell it which application to launch. (Using shortcuts, this is trivial to implement).

What I've done is implement an invocation proxy that would sit between my parent and child processes. The updater takes command line parameters and sets up the environment for the proxy. The proxy uses the environment to invoc the child processes. I think this more closely resembles the unix ideology of implementation than your typical windows implemenrtation but it is surprisingly effective and very flexible (even more when you make the child processes polymorphic based on input from the proxy).