Можно ли использовать OpenProcess с кодом ошибки ERROR_ACCESS_DENIED, чтобы узнать, существует ли процесс?

Я запускаю следующий код на платформе Windows. Цель состоит в том, чтобы узнать, относится ли конкретный идентификатор процесса к существующему процессу.

BOOL bProcessExists = FALSE;
HANDLE hProcHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcID);
if(hProcHandle)
{
    bProcessExists = TRUE;
    ::CloseHandle(hProcHandle);
}
else
{
    if(::GetLastError() == ERROR_ACCESS_DENIED)
    {
        bProcessExists = TRUE;
    }
}

Процесс, который запускает приведенный выше код, не работает с повышенными привилегиями, и я обнаружил, что OpenProcess может возвращать отказ в доступе для некоторых идентификаторов процессов.

Будет ли приведенный выше код действительным?


person ahmd0    schedule 01.07.2012    source источник
comment
В вашем коде есть состояние гонки: идентификаторы процессов могут быть переработаны. Если вы получили идентификатор процесса foo.exe, ваш код может сообщить, что процесс существует, потому что теперь bar.exe имеет этот идентификатор (учитывая, что foo.exe умер). Таким образом, он сообщит вам, есть ли какой-либо процесс с этим идентификатором, но без дополнительной проверки, для чего это нужно?   -  person eran    schedule 01.07.2012
comment
Хорошая точка зрения. Спасибо, что указали на это.   -  person ahmd0    schedule 02.07.2012


Ответы (1)


Меня больше беспокоит ваше предположение, что возможность открыть процесс означает, что процесс существует (за исключением чрезвычайно расплывчатых определений «существует»).

Запись для процесса будет сохраняться до тех пор, пока открыт хотя бы один дескриптор этого процесса. Если (например) родитель порождает процесс, а затем сохраняет дескриптор дочернего процесса, для дочернего процесса все равно будет запись, даже после того, как этот процесс завершится. В этой ситуации, если у вас есть соответствующие права, вы сможете открыть дескриптор процесса, даже если процесс уже завершился.

Чтобы правильно обработать этот случай, вы, вероятно, захотите вызвать GetExitCodeProcess и сказать, что процесс существует, только если он возвращает STILL_ALIVE в качестве статуса процесса.

Что касается другой части, я не могу с уверенностью сказать, что это сработает, но я бы сказал, что есть хороший шанс. Я использовал аналогичный метод для проверки паролей пользователей — попросите их ввести предложенное имя пользователя и пароль. Затем используйте NetUserChangePasswordout правом на смену пароля). Затем вы смотрите на полученную ошибку: ERROR_ACCESS_DENIED означает, что введенная ими комбинация имени пользователя и пароля была допустимой, а ERROR_INVALID_PASSWORD означает, что она недействительна.

person Jerry Coffin    schedule 01.07.2012
comment
В ПОРЯДКЕ. Я понимаю. Это не так просто, как кажется :) Спасибо за информацию. - person ahmd0; 02.07.2012