簡體   English   中英

無法處理程序

[英]Cannot get handle of process

求助:看看我的最后一篇帖子。 這可能是Windows XP和以前版本的問題,具有GetProcessId函數所需的權限。

沒有構建錯誤。 GetProcessId仍然返回0。我無法解決此問題。

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h> //For EnumProcessModules.
#include <tlhelp32.h>

#include <iostream>
using namespace std;

HANDLE GetHandleByName( string str )
{
    HANDLE hProcess = NULL;
    PROCESSENTRY32 entry;
    entry.dwSize = sizeof( PROCESSENTRY32 );

    HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, NULL );

    if( Process32First( snapshot, &entry ) == TRUE )
    {
        while( Process32Next( snapshot, &entry ) == TRUE )
        {
            WCHAR* wchrstr = ( WCHAR * )malloc( 128 );
            mbstowcs ( wchrstr, str.c_str(), 128 );
            if( wcscmp( reinterpret_cast< const wchar_t * >( entry.szExeFile ), wchrstr ) == 0 )
            {
                hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID );
            }
            free( wchrstr );
         }
    }

    CloseHandle( snapshot );
    return hProcess;
}



void main()
{
    HANDLE hProcess = GetHandleByName( "System" );

    cout << GetProcessId( hProcess );
    cin.get();
}

首先,您是要獲取System進程還是[System Process]虛擬進程? 無論哪種方式,您的代碼都有一些必須解決的問題。

如果您僅嘗試使用System則您的代碼僅需進行少量調整即可使用。 如果您真正想要的是[System Process]那么您不走運。

首先,您不執行任何錯誤檢查。 可能CreateToohelp32Snapshot失敗,並且您在Process32First調用中使用了無效的句柄。 其次,您調用Process32First ,然后立即調用Process32Next而無需查看Process32First返回的進程。 換句話說,您始終會跳過返回的第一個過程。 巧合的是,您猜第一個過程是返回哪個過程的? 這是虛擬的[System Process]

因此,讓我們嘗試一個枚舉所有進程並正確執行的函數:

void EnumAllProcesses(BOOL bTryToOpen = FALSE,
                      DWORD dwAccess = PROCESS_QUERY_INFORMATION)
{
    PROCESSENTRY32 entry;
    entry.dwSize = sizeof( PROCESSENTRY32 );

    HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, NULL );

    if( snapshot == INVALID_HANDLE_VALUE )
    {
        _tprintf(_T("Unable to create a ToolHelp32 snapshot (%08X)\n"), GetLastError());
        return;
    }

    if( Process32First( snapshot, &entry ) == TRUE )
    {
        do
        {
            _tprintf(_T("Process: %s (%u)\n"), entry.szExeFile, entry.th32ProcessID);

            if(bTryToOpen)
            {
                HANDLE hProcess = OpenProcess( dwAccess,
                                               FALSE, 
                                               entry.th32ProcessID );

                _tprintf(_T("    hProcess = %p (%08X)\n"), hProcess, GetLastError());

                if(hProcess != NULL)
                    CloseHandle(hProcess);
            }
        } while( Process32Next( snapshot, &entry ) == TRUE );        
    }

    CloseHandle( snapshot );
}

但是即使使用此新代碼,如果您想打開[System Process]也會遇到問題。 原因是當您指定此進程的進程ID(總是為零)時, OpenProcess將失敗並顯示ERROR_INVALID_PARAMETER 這是記錄的行為。 查看CreateProcess上的MSDN頁面,尤其是dwProcessId參數說明:

如果指定的進程是系統進程(0x00000000),則該函數將失敗,並且最后一個錯誤代碼是ERROR_INVALID_PARAMETER 如果指定的進程是Idle進程或CSRSS進程之一,則此函數將失敗,並且最后一個錯誤代碼為ERROR_ACCESS_DENIED因為它們的訪問限制會阻止用戶級代碼打開它們。

這是我的系統上以非管理員身份運行的此代碼輸出的快照:

Process: [System Process] (0)
    hProcess = 00000000 (00000057) 
Process: System (4)
    hProcess = 00000000 (00000005)
Process: smss.exe (324)
    hProcess = 00000000 (00000005)
Process: csrss.exe (492)
    hProcess = 00000000 (00000005)
Process: wininit.exe (568)
    hProcess = 00000000 (00000005) 

請注意,嘗試打開[System Process] (PID為0)時,該錯誤正確地是“無效參數”。 嘗試打開System (使用PID 4)時,錯誤為5-轉換為ERROR_ACCESS_DENIED 這是我期望的,因為我要求完全訪問並且我沒有以admin身份運行。 所以我嘗試以管理員身份運行它。 但是結果不會改變。 嗯...可能是什么問題?

好吧,可能是您正在要求PROCESS_ALL_ACCESS處理那些即使您是管理員也不允許您要求這么多訪問權限的進程。 僅僅因為您是ancyBank的所有者,並不意味着您可以走進分支機構並要求經理只打開其他人的保險箱...那么,您如何嘗試要求LESS訪問權限。 改為PROCESS_QUERY_INFORMATION呢?

現在,證據(在您中繼時)表明您對CreatToolHelp32Snapshot的調用失敗,並且永不進入循環,或者您以非管理員身份運行並要求獲得您無權訪問的進程的信息。 但是我不相信您會准確地傳達正在發生的事情,並且您沒有在幫助我們為您提供幫助。

操作系統不允許您打開系統進程。 這也將是無用的,因為這不是模塊等的常規過程。

dwProcessId [in]
The identifier of the local process to be opened.

If the specified process is the System Process (0x00000000), the function fails and the last error code is ERROR_INVALID_PARAMETER. If the specified process is the Idle process or one of the CSRSS processes, this function fails and the last error code is ERROR_ACCESS_DENIED because their access restrictions prevent user-level code from opening them.

另外,您需要更高的特權才能打開另一個進程。 您可以通過以管理員身份執行程序, 從UAC清單中要求管理員或禁用UAC來測試此類應用程序來執行此操作。

To open a handle to another local process and obtain full access rights, you must enable the SeDebugPrivilege privilege. For more information, see Changing Privileges in a Token.

在我禁用了UAC的系統上,當我僅將進程名稱更改為可以打開的名稱時,程序運行良好。

真正的問題是女士們和先生們:windows.h中的GetProcessId(HANDLE process)仍然返回0作為結果。 我已將功能替換為:

編輯:還有第二種方法來解決此問題,使用AdjustTokenPrivileges,感謝我們可以使用PROCESS_ALL_ACCESS,這樣原始的GetProcessId將可以工作,而無需使用下面的函數,該函數僅創建遠程線程。

DWORD WINAPI GetProcessIDbyProcessHandle(HANDLE hProcess)
{
    if (hProcess == NULL)    return 0xffffffff;
    PTHREAD_START_ROUTINE lpStartAddress = (PTHREAD_START_ROUTINE)
        GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "GetCurrentProcessId");
    if (lpStartAddress == NULL) return 0xffffffff;
    // We do not know, whether process handle already has required access rights;

    // thus we have to duplicate it
    HANDLE hProcessAccAdj;
    BOOL bRes = DuplicateHandle(GetCurrentProcess(), 
                                hProcess, GetCurrentProcess(), &hProcessAccAdj, 
                                PROCESS_QUERY_INFORMATION|PROCESS_CREATE_THREAD|
                                PROCESS_VM_OPERATION|PROCESS_VM_WRITE, 
                                FALSE, 0);
    if (!bRes || hProcessAccAdj == NULL)
    {
        UINT unError = GetLastError();
        return 0xffffffff;
    }
    // Create a remote thread; as its starting address 

    // we specify GetCurrentProcessId() address,
    // which is the same for all processes. Note that GetCurrentProcessId() has no input
    // parameters, and we don't care about our thread stack cleanup,
    // as it will be destroyed right after this call

    DWORD dwThreadID;
    HANDLE hRemoteThread = CreateRemoteThread(hProcessAccAdj, NULL, 
        0, lpStartAddress, 0, 0, &dwThreadID);
    CloseHandle(hProcessAccAdj);
    if (hRemoteThread == NULL) return 0xffffffff;
    // Wait until process ID is obtained

    // (replace INFINITE value below to a smaller value to avoid deadlocks);
    // then get the thread exit code, which is a value returned by GetCurrentProcessId()
    // in the context of the remote process
    WaitForSingleObject(hRemoteThread, INFINITE);
    DWORD dwExitCode;
    if (GetExitCodeThread(hRemoteThread, &dwExitCode) == 0)    dwExitCode = 0xffffffff;
    CloseHandle(hRemoteThread);
    return dwExitCode;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM