Introduction
For a project of my own, I had the task to check if the same application is already running every time the application is started by the user. If the application is already running, it must be switched to the foreground and the currently started process must be closed.
Using the code
I am using the Visual C++ 9.0 Standard Edition and the project type is MFC. We will use functions from <tlhelp32.h>. I am using WinXP.
In the string-table of your resource, you must have a string with the ID AFX_IDS_APP_TITLE
.
It must contain the application name of your executable without .exe. For example, if your executable file is named “frTKO.exe”, then the string-resource must be “frTKO”.
First, we will include the necessary header file.
#include <tlhelp32.h>
The function to do our work is as follows:
BOOL AppIsAllreadyRunning(BOOL bShow)
{
BOOL bRunning=FALSE;
CString strAppName;
strAppName.LoadString(AFX_IDS_APP_TITLE);
strAppName += _T(".exe");
DWORD dwOwnPID = GetProcessId(GetCurrentProcess());
HANDLE hSnapShot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
PROCESSENTRY32* processInfo=new PROCESSENTRY32;
processInfo->dwSize=sizeof(PROCESSENTRY32);
int index=0;
while(Process32Next(hSnapShot,processInfo)!=FALSE)
{
if (!strcmp(processInfo->szExeFile,strAppName))
{
if (processInfo->th32ProcessID != dwOwnPID)
{
if (bShow)
EnumWindows(ShowAppEnum,processInfo->th32ProcessID);
bRunning=TRUE;
break;
}
}
}
CloseHandle(hSnapShot);
delete processInfo;
return bRunning;
}
To get access to the window of the running application, we use EnumWindows()
, which needs a helper-function for enumerating processes:
BOOL CALLBACK ShowAppEnum (HWND hwnd, LPARAM lParam)
{
DWORD dwID;
CString strAppName;
strAppName.LoadString(AFX_IDS_APP_TITLE);
GetWindowThreadProcessId(hwnd, &dwID) ;
if(dwID == (DWORD)lParam)
{
char title[256];
CString strBuffer;
GetWindowText(hwnd,title,256);
strBuffer = title;
if (strBuffer.Left(strAppName.GetLength()) == strAppName)
{
if (!IsWindowVisible(hwnd))
ShowWindow(hwnd,SW_SHOW);
SetForegroundWindow(hwnd);
}
}
return TRUE;
}
Now, you place a call to your function as the first in the InitInstance()
of your app-class. You can check the return-code of the function to return FALSE
if an instance is already running.
BOOL CfrTeakoApp::InitInstance()
{
#ifndef _DEBUG
if (AppIsAllreadyRunning())
return FALSE;
#endif
Don’t forget to define the functions in the header-file:
BOOL AppIsAllreadyRunning(BOOL bShow=TRUE);
BOOL CALLBACK ShowAppEnum( HWND hwnd, LPARAM lParam );
That’s all.