MCPcopy Create free account
hub / github.com/AutoHotkey/AutoHotkey / ProcessExist

Function ProcessExist

source/script_autoit.cpp:1941–2003  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1939////////////////////
1940
1941DWORD ProcessExist(LPTSTR aProcess)
1942{
1943 // Determine the PID if aProcess is a pure, non-negative integer (any negative number
1944 // is more likely to be the name of a process [with a leading dash], rather than the PID).
1945 DWORD specified_pid = IsNumeric(aProcess) ? ATOU(aProcess) : 0;
1946 if (specified_pid)
1947 {
1948 // Most of the time while a PID is being used, the process still exists. So try opening
1949 // the process directly, since doing so is much faster than enumerating all processes:
1950 if (HANDLE hproc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE, FALSE, specified_pid))
1951 {
1952 DWORD wait_result = WAIT_FAILED;
1953 // OpenProcess can succeed for erroneous PID values; e.g. values of 1501 to 1503 can
1954 // open the process with ID 1500. This is likely due to the undocumented fact that
1955 // PIDs are a multiple of four: https://devblogs.microsoft.com/oldnewthing/20080228-00/?p=23283
1956 DWORD actual_pid = GetProcessId(hproc); // Requires PROCESS_QUERY_LIMITED_INFORMATION access.
1957 if (actual_pid == specified_pid)
1958 {
1959 // OpenProcess can succeed for a process which has already exited if another process
1960 // still has an open handle to it. So check whether it's still running:
1961 wait_result = WaitForSingleObject(hproc, 0); // Requires SYNCHRONIZE access.
1962 }
1963 CloseHandle(hproc);
1964 if (wait_result == WAIT_OBJECT_0)
1965 return 0; // Process has exited.
1966 if (wait_result == WAIT_TIMEOUT)
1967 return specified_pid; // Process still running.
1968 // Otherwise, fall back to the slow but more reliable method to get a more conclusive result.
1969 }
1970 // If OpenProcess failed, some likely causes are ERROR_ACCESS_DENIED and ERROR_INVALID_PARAMETER.
1971 // The latter probably indicates the PID is invalid, but we continue anyway, for the unlikely
1972 // case of a process with a name composed of digits and no extension (verified possible).
1973 // If ERROR_ACCESS_DENIED was returned, we can't rule out the false-positive cases described
1974 // above without doing a thorough enumeration of processes, so continue in that case as well.
1975 }
1976
1977 PROCESSENTRY32 proc;
1978 proc.dwSize = sizeof(proc);
1979 HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1980 Process32First(snapshot, &proc);
1981
1982 while (Process32Next(snapshot, &proc))
1983 {
1984 if (specified_pid && specified_pid == proc.th32ProcessID)
1985 {
1986 CloseHandle(snapshot);
1987 return specified_pid;
1988 }
1989 // Otherwise, check for matching name even if aProcess is purely numeric (i.e. a number might
1990 // also be a valid name?):
1991 // It seems that proc.szExeFile never contains a path, just the executable name.
1992 // But in case it ever does, ensure consistency by removing the path:
1993 LPCTSTR proc_name = _tcsrchr(proc.szExeFile, '\\');
1994 proc_name = proc_name ? proc_name + 1 : proc.szExeFile;
1995 if (!_tcsicmp(proc_name, aProcess)) // lstrcmpi() is not used: 1) avoids breaking existing scripts; 2) provides consistent behavior across multiple locales; 3) performance.
1996 {
1997 CloseHandle(snapshot);
1998 return proc.th32ProcessID;

Callers 1

BIF_DECLFunction · 0.85

Calls 1

IsNumericFunction · 0.85

Tested by

no test coverage detected