Самый простой способ - создать именованный объект после запуска программы.Например CreateEvent , CreateMutex и так далее.Для проверки существования приложения вы можете просто использовать OpenEvent , OpenMutex и т. Д. Перед созданием объекта.Вы можете выбрать (при желании) имя объекта с префиксом «Global \» (см. http://msdn.microsoft.com/en-us/library/aa382954.aspx), чтобы разрешить только один процесс для всего сеанса сервера терминалов.
ОБНОВЛЕНО : Поскольку, как я вижу, существуют разные мнения по поводу моего предложения, я пытаюсь объяснить его более точно и добавить соответствующий тестовый пример.
Основная идея заключается в том, что приложение, которое запускается, создает любое именованный объект - это объект с тем же именем, которого еще нет. Это зарезервирует имя только в пространствах имен объектов ядра . Реальное использование объекта не требуется. Преимущество этого способа по сравнению с созданиемфайла на диске состоит в том, что именованные объекты временные и принадлежат приложению . Таким образом, если приложение завершено, оно будет уничтожено или завершено любым другим способом (из-занапример, исключение в произвольном порядке) именованный объект будет автоматически удален операционной системой. В следующем примере я неиспользуйте CloseHandle
на всех.То, как вы можете протестировать приложение, может успешно определить, работает ли оно как первый экземпляр или нет.
#include <windows.h>
//#include <Sddl.h>
LPCTSTR g_pszEventName = TEXT("MyTestEvent"); // TEXT("Global\\MyTestEvent")
void DisplayFirstInstanceStartedMessage()
{
TCHAR szText[1024];
wsprintf (szText,
TEXT("The first instance are started.\nThe event with the name \"%s\" is created."),
g_pszEventName);
MessageBox (NULL,
szText,
TEXT("CreateEventTest"), MB_OK);
}
void DisplayAlreadyRunningMessage ()
{
TCHAR szText[1024];
wsprintf (szText,
TEXT("The first instance of the aplication is already running.\nThe event with the name \"%s\" already exist."),
g_pszEventName);
MessageBox (NULL,
szText,
TEXT("CreateEventTest"), MB_ICONWARNING | MB_OK);
}
void DisplayErrorMessage (DWORD dwErrorCode)
{
if (dwErrorCode == ERROR_ALREADY_EXISTS)
DisplayAlreadyRunningMessage();
else {
LPTSTR pErrorString;
if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | // Always search in system message table !!!
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS |
0, NULL, // source of message definition
dwErrorCode, // message ID
// 0, // language ID
// GetUserDefaultLangID(), // language ID
// GetSystemDefaultLangID(),
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&pErrorString, // pointer for buffer to allocate
0, // min number of chars to allocate
NULL)) {
MessageBox (NULL, pErrorString, TEXT("CreateEventTest"), MB_OK);
LocalFree (pErrorString);
}
else {
TCHAR szText[1024];
wsprintf (szText, TEXT("Error %d in the CreateEvent(..., \"%s\")"), dwErrorCode, g_pszEventName);
MessageBox (NULL, szText, TEXT("CreateEventTest"), MB_OK);
}
}
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
//SECURITY_ATTRIBUTES sa;
//BOOL bSuccess;
HANDLE hEvent = OpenEvent (EVENT_MODIFY_STATE, FALSE, g_pszEventName);// EVENT_ALL_ACCESS
if (hEvent == NULL) {
DWORD dwErrorCode = GetLastError();
if (dwErrorCode != ERROR_FILE_NOT_FOUND) {
DisplayErrorMessage(dwErrorCode);
return 1;
}
}
else {
DisplayAlreadyRunningMessage();
return 0;
}
//sa.bInheritHandle = FALSE;
//sa.nLength = sizeof(SECURITY_ATTRIBUTES);
//bSuccess = ConvertStringSecurityDescriptorToSecurityDescriptor (
// TEXT("D:(A;OICI;GA;;;WD)"), // Allow full control
// SDDL_REVISION_1,
// &sa.lpSecurityDescriptor,
// NULL);
hEvent = CreateEvent (NULL, // &sa
TRUE, FALSE, g_pszEventName);
//sa.lpSecurityDescriptor = LocalFree (sa.lpSecurityDescriptor);
if (hEvent == NULL) {
DWORD dwErrorCode = GetLastError();
DisplayErrorMessage(dwErrorCode);
return 1;
}
else
DisplayFirstInstanceStartedMessage();
return 0;
UNREFERENCED_PARAMETER (hInstance);
UNREFERENCED_PARAMETER (hPrevInstance);
UNREFERENCED_PARAMETER (lpCmdLine);
UNREFERENCED_PARAMETER (nShowCmd);
}
Если требуется поддержка, чтобы разные пользователи с одного и того же рабочего стола или с разных рабочих столов могли запустить только один экземплярВ программе можно раскомментировать некоторые части закомментированного кода или заменить имя MyTestEvent
события на Global\MyTestEvent
.
Надеюсь, после примера моя позиция будет ясна.При использовании такого типа событий вызов WaitForSingleObject()
не требуется.