[英]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.