Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > CreateToolhelp32Snapshot и Win64


Автор: Cheloveck 4.10.2009, 13:15
Руководствуясь http://www.rsdn.ru/article/qna/baseserv/enumproc.xml статьёй и http://msdn.microsoft.com/en-us/library/ms725506(VS.85).aspx предостережением в MSDN склонился к использованию CreateToolhelp32Snapshot для получения различной информации о процессах. Но меня очень смущает цифра 32 в названии функции, как впрочем и в типах для работы с процессами. Собственно вопрос, корректно ли это будет работать в 64-разрядной Windows? Я поставил себе на виртуалку 64-разрядную винду, немного потестил, вроде бы работает, но у меня нет достоверной информации, будет ли работать с 64-битными процессами...

Автор: Cheloveck 5.10.2009, 08:11
Нашёл оговорку в MSDN
Цитата

If the specified process is a 64-bit process and the caller is a 32-bit process, this call will fail.

Автор: Cheloveck 5.10.2009, 15:28
Для тех, кто озадачен получением списка процессов в ОС Windows поделюсь своими изысканиями. 
Как было сказано в двух постах выше: 
  • функция ZwQuerySystemInformation не рекомендуема к использованию Microsoft'ом
  • CreateToolhelp32Snapshot не работает с 64-разрядными процессами
Остальные способы, приведённые в указанной статье показались мне несколько невзрачными. Приведу код, с помощью которого можно решить поставленную задачу (а именно, получение списка процессов с PID, а значит и со всей сопутствующей информацией)
Код

    // Оказалось, что для некоторых процессов в Windows Vista (н/р csrss.exe)
    // необходимо получить привелегии SE_DEBUG_NAME.
    HANDLE htoken;
    if(OpenProcessToken(GetCurrentProcess(),
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &htoken)) 
    {
        TOKEN_PRIVILEGES tkp;
        LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid);
        tkp.PrivilegeCount = 1;
        tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        AdjustTokenPrivileges(htoken, FALSE, &tkp, 0, NULL, 0);
        CloseHandle(htoken);
    }

    std::wofstream output(L"processes.log");
    if(!output.is_open())
    {
        std::cerr << "Can't open log file\n";
        system("pause");
        return 1;
    }
    WTS_PROCESS_INFO *ppinfo;
    DWORD count;
    WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1, &ppinfo, &count);

    const DWORD len = 256;
    wchar_t username[len];
    wchar_t domainname[len];
    DWORD dname_len = len;
    DWORD uname_len = len;
    SID_NAME_USE snu;
    for(DWORD i = 0; i < count; i++)
    {
        output << "[" << ppinfo[i].pProcessName << "]\n" <<
            "PID = " << ppinfo[i].ProcessId << "\nUser = ";
        
        if(LookupAccountSid(NULL, ppinfo[i].pUserSid, 
                username, &uname_len, domainname, &dname_len, &snu))
            output << username << "\nDomain = " << domainname;
        else
            output << "<Unknown>\nDomain = <Unknown>";
        output << std::endl << std::endl;
        dname_len = len;
        uname_len = len;
    }

    WTSFreeMemory(ppinfo);
    output.close();

Данный код запишет все процессы в файл в виде
Код

[имя_программы.exe]
PID = 500
User = имя_пользователя
Domain = доменное имя


P.S. пример не оптимизирован, но наглядно демонстрирует работу.

Автор: dumb 5.10.2009, 22:53
одна оговорка: для успешного выполнения данного кода должна быть запущена служба "Terminal Services"("Службы терминалов").

Автор: Cheloveck 5.10.2009, 23:19
dumb, спасибо, не знал, буду проверять перед выполнением.

Автор: Cheloveck 6.10.2009, 08:49
dumb, я отключил "службы терминалов" и запустил программу, всё работает!

Добавлено через 1 минуту и 2 секунды
возможно, что не будет доступа на удалённую машину с отключённой службой, но на локальной проблем нет.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)