Archive for August, 2011

Checking if a process is alive using Java, JNI and C++

Many times in QA, it’s necessary to check if a process is ok from the outside. For example, we make a program open a file, and now we need to check if it’s OK. How do we do this? Well, there are several methods, but the main problem is that you can’t really tell from, the outside whether a process has hung or whether it’s working on a long processing task.

Here I’ll show a method I’ve used successfully to determine various modes of failure in a Windows desktop application. The testing harness was Java, and it hooked in to a C++ dll using JNI to determine whether the application was still running or not.

The failure modes were the following :
1. Silent crash – fairly easy to detect even without C++. Simply check if the process is running.

2. Unexpected window. This happens when an error is handled by the application, but doesn’t cause a crash.

3. A hang. Pretty hard do determine – is it a hang or is it just processing something? Should we wait a few more seconds (minutes? hours?).

Luckily, the application was programmed to respond to the Windows WM_QUERYENDSESSION message which is used to ask the application if it’s ready to shut down (eg for automatic restarts, updating, etc.).


OK, so here we go…

After running a test on the application, we use JNI to call a function in our DLL to check the status of the process (we pass in the process name as a String).

In the DLL, we do the following :

1. Enumerate the processes using the Windows EnumProcesses function.

DWORD procIDArr[1024], cbReturn;
EnumProcesses(procIDArr, sizeof(procIDArr), &cbReturn);

We now have the processes in procIDArr.

2. Iterate through the processes to find the one we want. For this, we need a HANDLE for the process.

HANDLE procHandle;

Now access each process using : 
procHandle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, procIDArr[i]);

then get the name of the process so we can check against ours :

GetModuleBaseName(procHandle, 0, (LPWSTR)exeName, sizeof(exeName));

Then get the process ID if we have found our own process. If we haven’t found our process, it means it has crashed and isn’t running anymore, or we have searched for the wrong process name :)…

DWORD procId = GetProcessId(procHandle);


3. Once the process ID is found, we need to find the windows. To do this, we use EnumWindows, along with a CALLBACK function we make.

EnumWindows(&EnumWindowsProc, NULL);

our CALLBACK signature is this :

BOOL CALLBACK EnumWindowsProc(HWND hWnd, long lParam)

we now get the window ID

DWORD id;
GetWindowThreadProcessId(hWnd, &id);

if the thread process ID is the same as the process ID we found in the previous step, the window belongs to our process.

we can now send it a message using :

SendMessageTimeout(window, WM_QUERYENDSESSION, NULL, NULL, SMTO_NORMAL,5000, NULL);

where window is the HWND hWnd passed to our CALLBACK function. If it responds, it means everything is ok, if not, we need to do one more thing.

4. If it is not responding to messages, there may be some warning/error message that the application generated, which is waiting for user input, or otherwise stopping processing. WE now check for child windows, to find any unexpected ones :

EnumChildWindows(hWnd, (WNDENUMPROC)&EnumChildWindowsProc, NULL);

where again we have a CALLBACK function

BOOL CALLBACK EnumChildWindowsProc(HWND window, LPARAM lparam) 

where we count or do whatever we need to do with the child windows to determine if there are any unexpected windows.

Be the first to comment - What do you think?  Posted by The Kernel - August 5, 2011 at 12:41 am

Categories: Uncategorized   Tags: