Как использовать OpenProcessToken, AdjustTokenPrivileges и GetExitCodeProcess в VC ++ 2005 - PullRequest
4 голосов
/ 17 января 2012

Я прочитал пару постов о том, как проверить, завершился ли процесс из другого процесса (я понимаю, что некоторые люди зацикливаются на семантике здесь, но просто приколят меня), и я попытался реализовать это, но сталкиваюсь с код ошибки 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 ]

4 голосов
/ 17 января 2012

Дескриптор, переданный 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;
}
1 голос
/ 17 января 2012

Если вы просто хотите, чтобы P2 что-то делал при выходе из P1, есть и другой способ, который, вероятно, довольно прост: пусть P1 создает канал и позволяет P2 наследовать дескриптор этого канала. В P2 выполните чтение из канала. Когда P2 вызывает ReadFile с ошибкой ERROR_BROKEN_PIPE, P1 завершается.

1 голос
/ 17 января 2012

OpenProcesstoken требует PROCESS_QUERY_INFORMATION. Вы открываете процесс только с доступом SYNCHRONIZE. Посмотрите, если вы добавите | PROCESS_QUERY_INFORMATION, если это работает.

...