C ++, ¿cómo determinar si se está ejecutando un proceso de Windows?

Esto es concerniente a los procesos de Windows XP.

Tengo un proceso en ejecución, llamémoslo Process1. Process1 crea un nuevo proceso, Process2, y guarda su id.

Ahora, en algún momento Process1 quiere que Process2 haga algo, por lo que primero debe asegurarse de que Process2 esté todavía vivo y de que el usuario no lo haya eliminado.

¿Cómo puedo verificar que este proceso todavía se esté ejecutando? Desde que lo creé, tengo el ID de proceso, creo que hay alguna función de biblioteca a lo largo de las líneas de IsProcessIDValid (id) pero no puedo encontrarla en MSDN

Puede usar GetExitCodeProcess . STILL_ACTIVE ( 259 ) si el proceso aún se está ejecutando (o si salió con ese código de salida :().

El identificador del proceso se señalará si sale.

Entonces, lo siguiente funcionará (se elimina el manejo del error por brevedad):

 BOOL IsProcessRunning(DWORD pid) { HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, pid); DWORD ret = WaitForSingleObject(process, 0); CloseHandle(process); return ret == WAIT_TIMEOUT; } 

Tenga en cuenta que los ID de proceso se pueden reciclar: es mejor guardar en caché el identificador que se devuelve desde la llamada CreateProcess.

También puede usar las API de subprocesos (SetThreadpoolWait en Vista +, RegisterWaitForSingleObject en plataformas más antiguas) para recibir una callback cuando finaliza el proceso.

EDITAR: Me perdí la parte “quiero hacer algo con el proceso” de la pregunta original. Puede utilizar esta técnica si está bien tener datos potencialmente obsoletos para una ventana pequeña o si desea suspender una operación sin siquiera intentarlo. Aún tendrá que manejar el caso donde la acción falla porque el proceso ha finalizado.

 #include  #include  #include  /*! \brief Check if a process is running \param [in] processName Name of process to check if is running \returns \c True if the process is running, or \c False if the process is not running */ bool IsProcessRunning(const wchar_t *processName) { bool exists = false; PROCESSENTRY32 entry; entry.dwSize = sizeof(PROCESSENTRY32); HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); if (Process32First(snapshot, &entry)) while (Process32Next(snapshot, &entry)) if (!wcsicmp(entry.szExeFile, processName)) exists = true; CloseHandle(snapshot); return exists; } 

Otra forma de controlar un proceso secundario es crear un hilo de trabajo que:

  1. llamar a CreateProcess ()
  2. llame a WaitForSingleObject () // el hilo de trabajo ahora esperará hasta que el proceso hijo termine la ejecución. también es posible tomar el código de retorno (desde la función main ()).

Encontré esto hoy, es de 2003. Encuentra un proceso por nombre, ni siquiera necesitas el pid.

 \#include windows.h \#include tlhelp32.h \#include iostream.h int FIND_PROC_BY_NAME(const char *); int main(int argc, char *argv[]) { // Check whether a process is currently running, or not char szName[100]="notepad.exe"; // Name of process to find int isRunning; isRunning=FIND_PROC_BY_NAME(szName); // Note: isRunning=0 means process not found, =1 means yes, it is found in memor return isRunning; } int FIND_PROC_BY_NAME(const char *szToFind) // Created: 12/29/2000 (RK) // Last modified: 6/16/2003 (RK) // Please report any problems or bugs to kochhar@physiology.wisc.edu // The latest version of this routine can be found at: // http://www.neurophys.wisc.edu/ravi/software/killproc/ // Check whether the process "szToFind" is currently running in memory // This works for Win/95/98/ME and also Win/NT/2000/XP // The process name is case-insensitive, ie "notepad.exe" and "NOTEPAD.EXE" // will both work (for szToFind) // Return codes are as follows: // 0 = Process was not found // 1 = Process was found // 605 = Unable to search for process // 606 = Unable to identify system type // 607 = Unsupported OS // 632 = Process name is invalid // Change history: // 3/10/2002 - Fixed memory leak in some cases (hSnapShot and // and hSnapShotm were not being closed sometimes) // 6/13/2003 - Removed iFound (was not being used, as pointed out // by John Emmas) { BOOL bResult,bResultm; DWORD aiPID[1000],iCb=1000,iNumProc,iV2000=0; DWORD iCbneeded,i; char szName[MAX_PATH],szToFindUpper[MAX_PATH]; HANDLE hProc,hSnapShot,hSnapShotm; OSVERSIONINFO osvi; HINSTANCE hInstLib; int iLen,iLenP,indx; HMODULE hMod; PROCESSENTRY32 procentry; MODULEENTRY32 modentry; // PSAPI Function Pointers. BOOL (WINAPI *lpfEnumProcesses)( DWORD *, DWORD cb, DWORD * ); BOOL (WINAPI *lpfEnumProcessModules)( HANDLE, HMODULE *, DWORD, LPDWORD ); DWORD (WINAPI *lpfGetModuleBaseName)( HANDLE, HMODULE, LPTSTR, DWORD ); // ToolHelp Function Pointers. HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ; BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ; BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ; BOOL (WINAPI *lpfModule32First)(HANDLE,LPMODULEENTRY32) ; BOOL (WINAPI *lpfModule32Next)(HANDLE,LPMODULEENTRY32) ; // Transfer Process name into "szToFindUpper" and // convert it to upper case iLenP=strlen(szToFind); if(iLenP<1 || iLenP>MAX_PATH) return 632; for(indx=0;indx 

Nunca puede verificar y ver si un proceso se está ejecutando; solo puede verificar si un proceso se está ejecutando en algún momento del pasado reciente. Un proceso es una entidad que no está controlada por su aplicación y puede salir en cualquier momento. No hay forma de garantizar que un proceso no saldrá entre el cheque para ver si se está ejecutando y la acción correspondiente.

El mejor enfoque es simplemente hacer la acción requerida y atrapar la excepción que se lanzaría si el proceso no se ejecutara.

llamar a EnumProcesses() y verificar si el PID está en la lista.

http://msdn.microsoft.com/en-us/library/ms682629%28VS.85%29.aspx

JaredPar tiene razón en que no se puede saber si el proceso se está ejecutando. Solo puede saber si el proceso se estaba ejecutando en el momento en que lo hizo. Podría haber muerto mientras tanto.

También debe saber que los PID pueden reciclarse rápidamente. Entonces, solo porque hay un proceso con su PID, eso no significa que sea su proceso.

Haga que los procesos compartan un GUID. (El Proceso 1 podría generar el GUID y pasarlo al Proceso 2 en la línea de comando). El Proceso 2 debería crear un mutex con nombre con ese GUID. Cuando el Proceso 1 desea verificar, puede hacer un WaitForSingleObject en el mutex con un tiempo de espera de 0. Si el proceso 2 se ha ido, el código de retorno le dirá que el mutex fue abandonado, de lo contrario obtendrá un tiempo de espera.

Mientras escribía una herramienta de monitoreo, tomé un enfoque ligeramente diferente.

Me pareció un poco derrochador generar un hilo adicional solo para usar WaitForSingleObject o incluso el RegisterWaitForSingleObject (que hace eso por ti). Como en mi caso no necesito saber el instante exacto en que se cerró el proceso, solo que efectivamente se ha cerrado.

Estoy usando GetProcessTimes () en su lugar:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms683223(v=vs.85).aspx

GetProcessTimes () devolverá una estructura FILETIME para el ExitTime del proceso solo si el proceso realmente ha salido. Entonces, solo es cuestión de verificar si la estructura ExitTime está poblada y si la hora no es 0;

Esta solución DEBERÍA dar cuenta del caso donde un proceso ha sido cancelado pero su PID fue reutilizado por otro proceso. GetProcessTimes necesita un control del proceso, no del PID. Entonces, el sistema operativo debe saber que el identificador es para un proceso que se estaba ejecutando en algún momento, pero no más, y darle el tiempo de salida.

Confiar en ExitCode se sintió sucio: /

Puede encontrar si un proceso (dado su nombre o PID) se está ejecutando o no iterando sobre los procesos en ejecución simplemente tomando una instantánea de los procesos en ejecución a través de CreateToolhelp32Snapshot , y usando las llamadas Process32First y Process32Next en esa instantánea.

Luego puede usar el campo th32ProcessID o el campo szExeFile de la estructura PROCESSENTRY32 resultante, según si desea buscar por PID o por nombre ejecutable. Una implementación simple se puede encontrar aquí .

Esta es una solución que he usado en el pasado. Aunque el ejemplo aquí está en VB.net, he usado esta técnica con c y c ++. Pasa por alto todos los problemas con identificadores de proceso y identificadores de proceso, y códigos de retorno. Windows es muy fiel al liberar el mutex sin importar cómo termine Process2. Espero que sea útil para alguien …

 **PROCESS1 :-** Randomize() mutexname = "myprocess" & Mid(Format(CDbl(Long.MaxValue) * Rnd(), "00000000000000000000"), 1, 16) hnd = CreateMutex(0, False, mutexname) ' pass this name to Process2 File.WriteAllText("mutexname.txt", mutexname)   pr = WaitForSingleObject(hnd, 0) ReleaseMutex(hnd) If pr = WAIT_OBJECT_0 Then  Else  End If ... CloseHandle(hnd) EXIT **PROCESS2 :-** mutexname = File.ReadAllText("mutexname.txt") hnd = OpenMutex(MUTEX_ALL_ACCESS Or SYNCHRONIZE, True, mutexname) ... ReleaseMutex(hnd) CloseHandle(hnd) EXIT