Как использовать OpenProcessToken, AdjustTokenPrivileges и GetExitCodeProcess в VC++ 2005
Я прочитал пару постов о том, как проверить, завершился ли процесс из другого процесса (я понимаю, что некоторые люди зацикливаются на семантике здесь, но просто приколят меня), и я попытался реализовать это, но столкнулся с кодом ошибки 5 ("ERROR_ACCESS_DENIED") повсюду.
Вот что я делаю.
1) Процесс 1 (P1) запускает процесс 2 и записывает в общую память свой собственный PID.
2) Процесс 2 (P2) считывает PID из общей памяти
3) P2 вызывает OpenProcess(...) с PID P1, чтобы сохранить дескриптор, который он может проверить позже.
4) P2 неоднократно вызывает GetExitCodeProcess(...) с PID P1 и проверяет код STILL_ACTIVE.
В вышеупомянутом методе я продолжаю получать ошибку ACCESS_DENIED на GetExitCodeProcess. Я попытался изменить привилегии P2 с помощью приведенного ниже кода из документов MSDN:
HANDLE proc_h = OpenProcess(SYNCHRONIZE, FALSE, GetCurrentProcessId());
HANDLE hToken;
OpenProcessToken(proc_h, TOKEN_ADJUST_PRIVILEGES, &hToken);
LookupPrivilegeValue(NULL, lpszPrivilege, &luid );
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Enable the privilege
AdjustTokenPrivileges(hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL);
Но я продолжаю получать ошибку ACCESS_DENIED при вызове метода OpenProcessToken(...). Так значит ли это что-то вроде системного барьера? У меня есть права администратора на моей машине, и я использую XP.
Заранее благодарю за любую помощь.
3 ответа
Дескриптор, переданный в GetExitCodeProcess, требует PROCESS_QUERY_INFORMATION
право доступа. Следующее работает отлично:
int main(int a_argc, char** a_argv)
{
int pid = atoi(*(a_argv + 1));
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
if (NULL != h)
{
Sleep(2000);
DWORD exit_code;
if (FALSE == GetExitCodeProcess(h, &exit_code))
{
std::cerr << "GetExitCodeProcess() failure: " <<
GetLastError() << "\n";
}
else if (STILL_ACTIVE == exit_code)
{
std::cout << "Still running\n";
}
else
{
std::cout << "exit code=" << exit_code << "\n";
}
}
else
{
std::cerr << "OpenProcess() failure: " << GetLastError() << "\n";
}
return 0;
}
Вместо того, чтобы опрашивать GetExitCodeProcess
откройте ручку с SYNCHRONIZE
и ждать его выхода:
int main(int a_argc, char** a_argv)
{
int pid = atoi(*(a_argv + 1));
HANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid);
if (NULL != h)
{
WaitForSingleObject(h, 5000); // Change to 'INFINITE' wait if req'd
DWORD exit_code;
if (FALSE == GetExitCodeProcess(h, &exit_code))
{
std::cerr << "GetExitCodeProcess() failure: " <<
GetLastError() << "\n";
}
else if (STILL_ACTIVE == exit_code)
{
std::cout << "Still running\n";
}
else
{
std::cout << "exit code=" << exit_code << "\n";
}
}
else
{
std::cerr << "OpenProcess() failure: " << GetLastError() << "\n";
}
return 0;
}
OpenProcesstoken требует PROCESS_QUERY_INFORMATION, вы открываете процесс только с доступом SYNCHRONIZE. Смотрите, если вы добавите | PROCESS_QUERY_INFORMATION
если он работает.
Если вы просто хотите, чтобы P2 что-то делал при выходе из P1, есть другой способ, который, вероятно, довольно прост: пусть P1 создает канал и позволяет P2 наследовать дескриптор этого канала. В P2 выполните чтение из канала. Когда P2 вызов ReadFile
возвращается с ошибкой ERROR_BROKEN_PIPE
, P1 вышел.