2012-01-10 9 views
12

INFORMACIÓN ADICIONALLa prevención de varias instancias de mi solicitud

Una vez más estoy escribiendo sobre el tema anterior (Prevención de varias instancias de mi solicitud)

el código funciona porque si empiezo dos instancias de menú programe/acceso directo del escritorio . pero en mi entorno,

una instancia se ejecuta desde el Servicio de ventanas.

otro desde el acceso directo de escritorio con el mismo parámetro.

¿Alguna ayuda sobre cómo escribir el código?

+0

¿Por qué no se debería permitir? Pregunto porque si el programa es algo así como un servidor que escucha un número de puerto fijo, realmente no tienes que hacer nada especial. – hvd

+0

@hvd, hay muchos tipos de programas que no deberían permitir la ejecución de instancias múltiples. De lo contrario, no habría mutexes en las bibliotecas del sistema. – Griwes

+0

Sí, esa aplicación es un Servidor, pero se puede ejecutar para varias instancias pero no con el mismo argumento. si pasamos el mismo argumento desde el servicio de ventana e iniciamos el ABC.exe y desde el acceso directo de escritorio con el mismo argumento ABC.exe, el segundo no debería iniciarse. –

Respuesta

3

Está buscando named mutex (nombrado después del argumento, si es lo que debe impedir que la aplicación se ejecute en varias instancias).

7

Aquí es una solución simple que funciona la mayor parte del tiempo:

CreateEvent(NULL, FALSE, FALSE, "MyEvent"); 
if (GetLastError() == ERROR_ALREADY_EXISTS) 
{ 
    // Do Stuff 
    return FALSE; 
} 

Otra forma:

CreateSemaphore(NULL, TRUE, TRUE, "MySemaphore"); 
if (GetLastError() == ERROR_ALREADY_EXISTS) 
{ 
    // Do Stuff 
    return FALSE; 
} 

Y de otra manera:

CreateMutex(NULL, TRUE, "MyMutex"); 
if (GetLastError() == ERROR_ALREADY_EXISTS) 
{ 
    // Do Stuff 
    return FALSE; 
} 

Como, la otra respuesta mencionado , CreateMutex es el más común, pero no es perfecto. Si desea una solución realmente completa y por qué las formas anteriores no son buenas, consulte este link on Codeproject.

+0

Tenga en cuenta que estos objetos no pueden usar la misma cadena (para lpName) si los usa conjuntamente, de lo contrario, generarán un error diferente. – Andrew

10

El método más común es utilizar un mutex, similar a la siguiente:

int WINAPI WinMain(...) 
{ 
    const char szUniqueNamedMutex[] = "com_mycompany_apps_appname"; 
    HANDLE hHandle = CreateMutex(NULL, TRUE, szUniqueNamedMutex); 
    if(ERROR_ALREADY_EXISTS == GetLastError()) 
    { 
     // Program already running somewhere 
     return(1); // Exit program 
    } 

    // Program runs... 

    // Upon app closing: 
    ReleaseMutex(hHandle); // Explicitly release mutex 
    CloseHandle(hHandle); // close handle before terminating 
    return(1); 
} 

Usted tiene que asegurarse de que cierre correctamente - un accidente de programa que no se retire el mutex, posiblemente, podría evitar la programa se ejecute de nuevo, aunque en teoría el sistema operativo limpiará cualquier mutexes colgando una vez que el proceso termina.

Otro método utilizado comúnmente es buscar títulos de ventana para el título del programa:

HWND hWnd=::FindWindow(LPCTSTR lpClassName, // pointer to class name 
         LPCTSTR lpWindowName // pointer to window name 
         ); 

Si es nula, entonces la ventana no se ha encontrado, por lo tanto, el programa no se está ejecutando. Puede usar esto para enfocar la aplicación que se está ejecutando antes de cerrar esta nueva instancia, de modo que el usuario no se pregunte por qué la aplicación no se abrió.

if(hWnd != NULL) 
{ 
    ShowWindow(hWnd,SW_NORMAL); 
    // exit this instance 
    return(1); 
} 
+0

¿No estás olvidando 'ReleaseMutex'? –

+0

@Jesse Se libera al cerrarlo, pero si está interesado en ser explícito, una llamada a ReleaseMutex estaría bien. http://msdn.microsoft.com/en-us/library/windows/desktop/ms724211%28v=vs.85%29.aspx –

+0

No creo que sea cierto. Creo que tienes que llamar a 'ReleaseMutex'. Consulte esta [ASUNTA] (http://stackoverflow.com/questions/5034339/closehandle-on-a-mutex-before-releasemutex-what-happens) y lea también los comentarios de [CreateMutex] (http: // msdn.microsoft.com/en-us/library/aa914601.aspx). Sin embargo, me doy cuenta de que probablemente no importe en este caso. –

5

TLDR: La única manera segura y en general para evitar que varias instancias del mismo proceso es utilizar un mutex, ya que sólo está garantizada a este no le dará una condición de carrera.

Aquí tiene un buen artículo sobre el tema. Lo usé cuando tenía que hacer algo similar y la solución funciona a la perfección: AvoidingMultipleInstances.

1

También he visto esta solución, sin GetLastError():

HANDLE hMutex = CreateMutexA(NULL, FALSE, "my mutex"); 
    DWORD dwMutexWaitResult = WaitForSingleObject(hMutex, 0); 
    if (dwMutexWaitResult != WAIT_OBJECT_0) 
    { 
     MessageBox(HWND_DESKTOP, TEXT("This application is already running"), TEXT("Information"), MB_OK | MB_ICONINFORMATION); 
     CloseHandle(hMutex); 
    } 
Cuestiones relacionadas