C ++, como determinar se um processo do Windows está sendo executado?

Isso é sobre processos do Windows XP.

Eu tenho um processo em execução, vamos chamá-lo de Process1. Process1 cria um novo processo, Process2 e salva seu id.

Agora, em algum ponto, o Process1 quer que o Process2 faça alguma coisa, por isso, primeiro precisa ter certeza de que o Process2 ainda está ativo e que o usuário não o matou.

Como posso verificar se esse processo ainda está em execução? Desde que eu criei, eu tenho o ID do processo, eu acho que há alguma function de biblioteca ao longo das linhas de IsProcessIDValid (id), mas não consigo encontrá-lo no MSDN

Você pode usar GetExitCodeProcess . Ele retornará STILL_ACTIVE ( 259 ) se o processo ainda estiver em execução (ou se tiver STILL_ACTIVE com esse código de saída :().

O identificador do processo será sinalizado se sair.

Então, o seguinte irá funcionar (tratamento de erros removido por brevidade):

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

Observe que as identificações de processo podem ser recicladas – é melhor armazenar em cache o identificador retornado da chamada CreateProcess.

Você também pode usar as APIs do conjunto de encadeamentos (SetThreadpoolWait no Vista +, RegisterWaitForSingleObject em plataformas mais antigas) para receber um retorno de chamada quando o processo terminar.

EDIT: eu perdi o “quero fazer algo para o processo” parte da pergunta original. Você pode usar essa técnica se estiver ok para ter dados potencialmente obsoletos para uma pequena janela ou se você quiser falhar em uma operação sem sequer tentar. Você ainda terá que lidar com o caso em que a ação falha porque o processo foi encerrado.

 #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; } 

Outra maneira de monitorar um processo filho é criar um thread de trabalho que:

  1. chamar CreateProcess ()
  2. chame WaitForSingleObject () // o segmento de trabalho agora aguardará até que o processo filho termine a execução. é possível pegar o código de retorno (da function main ()) também.

Achei isso hoje, é de 2003. Ele encontra um processo pelo nome, você nem precisa do 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 

Você nunca pode verificar e ver se um processo está em execução, você só pode verificar se um processo estava sendo executado em algum momento no passado recente. Um processo é uma entidade que não é controlada pelo seu aplicativo e pode sair a qualquer momento. Não há como garantir que um processo não saia entre a verificação para ver se ela está em execução e a ação correspondente.

A melhor abordagem é apenas fazer a ação necessária e capturar a exceção que seria lançada se o processo não estivesse em execução.

chame EnumProcesses() e verifique se o PID está na lista.

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

JaredPar está certo em que você não pode saber se o processo está sendo executado. Você só pode saber se o processo estava sendo executado no momento em que você verificou. Pode ter morrido nesse meio tempo.

Você também precisa estar ciente de que os PIDs podem ser reciclados rapidamente. Então, só porque há um processo lá fora com o seu PID, isso não significa que é o seu processo.

Os processos compartilham um GUID. (O processo 1 pode gerar o GUID e passá-lo para o Processo 2 na linha de comando). O processo 2 deve criar um mutex nomeado com esse GUID. Quando o Processo 1 deseja verificar, ele pode fazer um WaitForSingleObject no mutex com um tempo limite 0. Se o Processo 2 desaparecer, o código de retorno informará que o mutex foi abandonado, caso contrário, você obterá um tempo limite.

Ao escrever uma ferramenta de monitoramento, eu tomei uma abordagem ligeiramente diferente.

Foi um desperdício criar um thread extra apenas para usar WaitForSingleObject ou até mesmo o RegisterWaitForSingleObject (que faz isso para você). Já que no meu caso eu não preciso saber o instante exato em que um processo foi fechado, apenas que ele realmente fechou.

Eu estou usando o GetProcessTimes () em vez disso:

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

GetProcessTimes () retornará uma estrutura FILETIME para o ExitTime do processo somente se o processo tiver realmente saído. Portanto, é apenas uma questão de verificar se a estrutura ExitTime está preenchida e se a hora não é 0;

Esta solução deve considerar o caso em que um processo foi eliminado, mas o PID foi reutilizado por outro processo. GetProcessTimes precisa de um identificador para o processo, não o PID. Portanto, o sistema operacional deve saber que o identificador é para um processo que estava sendo executado em algum momento, mas não mais, e fornecer o horário de saída.

Confiando no ExitCode senti sujo: /

Você pode descobrir se um processo (com seu nome ou PID) está sendo executado ou não, iterando os processos em execução simplesmente tirando um instantâneo dos processos em execução via CreateToolhelp32Snapshot e usando as chamadas Process32First e Process32Next nesse instantâneo.

Em seguida, você pode usar o campo th32ProcessID ou o campo szExeFile da estrutura PROCESSENTRY32 resultante dependendo se você deseja pesquisar por PID ou nome do executável. Uma implementação simples pode ser encontrada aqui .

Esta é uma solução que usei no passado. Embora o exemplo aqui esteja em VB.net – usei essa técnica com c e c ++. Ele ignora todos os problemas com identificações de processo e identificadores de processo e códigos de retorno. O Windows é muito fiel ao liberar o mutex, não importa como o Process2 seja finalizado. Espero que seja útil para alguém …

 **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