El uso de tlhelp32 o enumerar los procesos es muy eficaz y es una forma bastante fiable de localizar si un proceso está corriendo aunque depende del nombre de dicho proceso...
El uso del mutex no es descartable en este caso. Si lo queremos usar, yo crearía el mutex en el proceso externo destruyéndolo al terminarse.
En el proceso principal colocaría algo así:
var
Mutex: THandle;
begin
Mutex:= CreateMutex(nil, FALSE, 'PROG_EXTERNO');
if GetLastError = 0 then
ShellExecute(0, 'open', Proceso_externo, Argumentos, nil, SW_HIDE);
if Mutex<>0 then CloseHandle(Mutex);
end;
Este es el método que usé en una ocasión en un sistema de Vigilancia mutua entre dos procesos. El principal comprueba el mutex creado por el secundario, ese mutex se creaba con el nombre del principal que se pasa como parámetro al secundario usándolo para crear el mutex y arrancar al principal si no está en ejecución, comprobado esta vez usando tlhelp32 . El principal comprobaba el mutex de su propio nombre y si no existía ejecutaba al secundario.
Este sistema doble lo implementé porque el programa secundario lo usaba como vigilante de uno o dos procesos principales, de este modo podía tener una o dos copias del proceso vigilante secundario sin problemas.
Saludos.