views:

411

answers:

3

I'm trying to launch another process from a service (it's a console app that collects some data and writes it to the registry) but for some reason I can't get it to launch properly.

I basics of what I'm am trying to do is as follows:

  1. Launch the process
  2. Wait for the process to finish
  3. Retrieve the return code from the process

I am currently using the following code:

STARTUPINFO info={sizeof(info)};
PROCESS_INFORMATION processInfo;
if (CreateProcess(PATH, ARGS, NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
 ::WaitForSingleObject(processInfo.hProcess, INFINITE);

 DWORD exit = 100;
 GetExitCodeProcess(processInfo.hProcess, &exit);

 CloseHandle(processInfo.hProcess);
 CloseHandle(processInfo.hThread);

 return exit;
}

Upon calling CreateProcess(), it succeeds and enters the body of the if statement. The call to WaitForSingleObject returns immediately, which it should not, as the process should take approximately 20-30 seconds to finish. And, finally, calling GetExitCodeProcess() fails and does not set the value "exit".

FYI, this is code I have actually used elsewhere with success, just not in a service.

Could it be that it's being launched from a service and there are permissions issues??

Edit: I've now realized that it will actually launch the app (I can see it in TaskMan) but it seems to be stuck. It's there, but isn't doing anything.
Based on Rob Kennedy's suggestion, I fixed the process handle issue, and it actually does wait for the process to finish. But it never does finish unless I kill it manually.

+2  A: 

WaitForSingleObject and GetExitCodeProcess expect the process handle itself, not a pointer to the process handle. Remove the ampersands.

Also, check the return values and call GetLastError when they fail. That will help you diagnose future problems. Never assume an API function will always succeed.

Once you call the functions right, and the new process starts but makes no progress, you can be reasonably certain that this code is not the culprit. The problem lies in the new process, so focus your debugging tasks there, not in the service process.

Rob Kennedy
A: 

Following the update and edit, this sounds like one of many possible gotchas when launching a process from a service. Is there any possibility - any whatsoever - that your external process is waiting for user interaction? There are three major examples I can think of, one for instance would be a command-line application which might under some circumstances require keyboard input (for example, something like "cmd /c del *.*" would require user confirmation). The other examples would apply if the application needed a window, and is displaying it but you can't see it. If that's the case, you might wish to set your service to "interact with desktop" while debugging, and then be able to see either the application window (or an unexpected Windows error message such as being unable to find a DLL or similar).

If this helps you to debug or not, usually the "a-ha!" moment comes from realizing that things such as environment variables, path, current directory, and so on aren't perhaps what you'd expect from within your service. Permissions are not the most common reason for this kind of problem. Could you provide some details about the external application you're trying to launch, perhaps that would help in thinking this out.

Chris
A: 

Since you are launching a console app, it's possible that there's hidden startup code trying to initialize a console. A service isn't attached to the desktop, and I'm sure a process launched by the service won't be either, so it won't be able to create a console. That could be the point where it is hanging.

If you can, try changing your process into a full Windows executable, but skip the part where you try to create a window.

Mark Ransom