【问题标题】:GetProcessMemoryInfo failed with error 6 Handle is invalidGetProcessMemoryInfo 失败,错误 6 句柄无效
【发布时间】:2018-06-25 04:47:32
【问题描述】:

我正在尝试使用 C++ 获取系统中运行的进程列表。我使用 Windows API 中可用的函数(如 OpenProcess 和 CreateToolhelp32Snapshot )来完成它。

问题是代码对于大多数进程都可以正常工作,但无法单独获取关键系统进程的内存信息,我也提供了 seDebugPrivilege 并且仅以管理员身份运行程序。

我得到像

这样的输出

File Name PID Memory Used

winlogon.exe 1248 2432 KB

fontdrvhost.exe 1308

WARNING: GetProcessMemoryInfo failed with error 6 (The handle is invalid)

dwm.exe 1384

WARNING: GetProcessMemoryInfo failed with error 6 (The handle is invalid)

svchost.exe 1448 4744 KB

我的代码是:

BOOL GetProcessList( )
{
    HANDLE hProcessSnap;
    HANDLE hProcess;
    HANDLE hToken;
    PROCESSENTRY32 pe32;
    DWORD dwPriorityClass;
    PROCESS_MEMORY_COUNTERS pmc;

  hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
  if( hProcessSnap == INVALID_HANDLE_VALUE )
  {
      char err[]="CreateToolhelp32Snapshot (of processes)";
    printError( err );
    return( FALSE );
  }

  pe32.dwSize = sizeof( PROCESSENTRY32 );

  if( !Process32First( hProcessSnap, &pe32 ) )
  {
    char err[]="Process32First";
    printError( err ); // show cause of failure
    CloseHandle( hProcessSnap );          // clean the snapshot object
    return( FALSE );
  }
  if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken))
    {
        if (GetLastError() == ERROR_NO_TOKEN)
        {
            if (!ImpersonateSelf(SecurityImpersonation))
            return FALSE;

            if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)){
                char err[]="OpenThreadToken";
                printError( err );
                return FALSE;
            }
         }
        else
            return FALSE;
     }
    SetPrivilege(hToken, SE_DEBUG_NAME, FALSE);
  do
  {
    printf( "%-25s", pe32.szExeFile );
    dwPriorityClass = 0;
    SIZE_T  dwMin, dwMax;
    hProcess = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION , FALSE, pe32.th32ProcessID );
    printf("%-10d", pe32.th32ProcessID );
    if(GetProcessMemoryInfo( hProcess, (PROCESS_MEMORY_COUNTERS *)&pmc, sizeof(pmc)))
    {

        printf( "%-10d KB", pmc.PagefileUsage/1024); 
    } else{
        char err[]="GetProcessMemoryInfo";
        printError( err );
    }
        printf("\n");
    CloseHandle(hProcess);
  }while( Process32Next( hProcessSnap, &pe32 ) );
  CloseHandle( hProcessSnap );
  return( TRUE );
}

【问题讨论】:

  • 也许这个例子可能有用:pastebin.com/KjBzMEY0。我认为你有这个问题 - stackoverflow.com/questions/28303436/…。也使用 PROCESS_QUERY_LIMITED_INFORMATION
  • 你没有检查OpenProcess的结果。在某些进程中它失败并因此在调用GetProcessMemoryInfo 中使用无效句柄返回给您错误 - 无效句柄。必须是
  • 您也没有关闭hToken 并且看起来无法分配调试权限,只有这样才能解释为什么您无法打开某些进程。还可以在枚举进程之前调整权限
  • @HelpingHand 我正在使用PROCESS_QUERY_LIMITED_INFORMATION,是的,在发布这个问题之前我确实看过那篇文章
  • 我同意 RbMm。 SetPrivilege 似乎有问题。如果线程令牌启用了调试权限,那么打开一个进程以仅查询有限的信息应该不会失败,即使对于受保护的进程也是如此。

标签: c++ windows winapi process


【解决方案1】:

要让这段代码工作,你必须改变:

SetPrivilege(hToken, SE_DEBUG_NAME, FALSE)

到:

SetPrivilege(hToken, SE_DEBUG_NAME, TRUE)

正如其他人评论的那样,要让这段代码正常工作,您必须:

  • 检查并报告所有可能的错误情况
  • 完成后释放所有资源,在这种情况下释放hToken(通过CloseHandle())并在需要时调用revertToSelf()。

除此之外,这是一项体面的努力,因此请竖起大拇指。

链接到SetPrivilege(),以防将来的访问者需要它:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa446619.aspx

黑客愉快。

【讨论】:

  • 感谢您的回答!干杯!
猜你喜欢
  • 1970-01-01
  • 2013-08-01
  • 2019-10-16
  • 2021-11-24
  • 1970-01-01
  • 1970-01-01
  • 2021-09-18
  • 1970-01-01
  • 2018-06-20
相关资源
最近更新 更多