1

已解决:看看我的最后一个帖子。这可能是 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();
}
4

3 回答 3

5

首先,你是想获取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. 这是我所期望的,因为我要求完全访问权限并且我没有以管理员身份运行。所以我尝试以管理员身份运行它。然而结果不会改变。嗯……可能是什么问题?

好吧,即使您是管理员,也可能是您要求的PROCESS_ALL_ACCESS进程不允许您要求那么多访问权限。仅仅因为您是 ancyBank 的所有者并不意味着您可以走进分行并要求经理打开其他人的保险箱……那么您尝试要求LESS访问如何。换成怎么样PROCESS_QUERY_INFORMATION

现在,证据(当您转发它时)表明您的呼叫CreatToolHelp32Snapshot失败,并且从未进入循环,或者您以非管理员身份运行并询问您无权访问的进程的信息。但我不相信你准确地传达了正在发生的事情,你没有帮助我们帮助你。

于 2013-07-14T14:39:03.560 回答
2

操作系统不允许您打开系统进程。它也将毫无用处,因为它不是模块等的常用过程。

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 禁用系统上,当我只将进程名称更改为可以打开的名称时,程序运行良好。

于 2013-07-14T14:37:04.843 回答
1

真正的问题是女士们先生们:来自 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;
}
于 2013-07-14T16:16:28.110 回答