【问题标题】:How to effectively kill a process in C++ (Win32)?如何有效地杀死 C++ (Win32) 中的进程?
【发布时间】:2010-12-27 08:35:35
【问题描述】:

我目前正在编写一个非常轻量级的程序,因此我必须使用 C++,因为它没有绑定到 .NET 框架,这会大大增加程序的大小。

我需要能够终止进程,为此我需要获得一个进程句柄。不幸的是,我还没想好怎么做。

附:我知道要杀死一个进程,你必须使用 TerminateProcess

【问题讨论】:

  • 我过去使用过 pgrep 和 pkill,但那是在 Solaris 时代。
  • 你的意思是在 Win32 中。这里没有任何与 C++ 相关的内容
  • 嗯...是的,你是对的

标签: c++ winapi process


【解决方案1】:

以下代码有效:

const auto explorer = OpenProcess(PROCESS_TERMINATE, false, process_id);
TerminateProcess(explorer, 1);
CloseHandle(explorer);

【讨论】:

  • 别忘了CloseHandle(explorer)
【解决方案2】:

使用现代 C++ 的任务杀手

以下是我为终结者计划创建的代码

//_____________________________________________
//                                             |
// TheNexGen of Terminator (inclusion version) |
// ------------------------------------------- |
//                                             |
// Add your Programs in the 'if' check as I've |
// listed below, and compile using c++17 flag  |
// or higher                                   |
//_____________________________________________|



#include <process.h>
#include <windows.h>
#include <tlhelp32.h>
#include <string_view>
using namespace std;

int main()
{
    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap == INVALID_HANDLE_VALUE) return 0;

    PROCESSENTRY32W pe32{ .dwSize = sizeof(PROCESSENTRY32) };
    if (!Process32First(hProcessSnap, &pe32)) return CloseHandle(hProcessSnap), 0;

    do
    {
        wstring_view str = pe32.szExeFile;

        if
            (
                str == L"chrome.exe"
                || str == L"AAM Update Notelse ifier.exe"
                || str == L"About.exe"
                || str == L"ActionCenterDownloader.exe"
                || str == L"adb.exe"
                || str == L"AdobeARM.exe"
            )
        {
            if (HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, 0, pe32.th32ProcessID))
            {
                TerminateProcess(hProcess, 1);
                CloseHandle(hProcess);
            }
        }
    }
    while (Process32Next(hProcessSnap, &pe32));

    CloseHandle(hProcessSnap);
}

说明

我是 TheMR 一名 现代 C++ 程序员(具有编写高性能代码的经验),我已将提供的代码简化、现代化并提高了 100 倍的执行速度@DmitryBoyko

我将很快发布基于排除原则的另一个版本的终结者

【讨论】:

    【解决方案3】:

    仅限 Windows

    system("taskkill /f /im servicetokill.exe")
    

    【讨论】:

      【解决方案4】:

      与其费力地杀死一个已知名称的进程,为什么不简单地调用“系统”并要求命令行杀死它?

      例如,

      int retval = ::_tsystem( _T("taskkill /F /T /IM MyProcess.exe") );
      

      【讨论】:

      • 不确定这是否满足“轻量级”。 system 速度慢是众所周知的。
      • 根据这个问题,“轻量级”是指“尺寸轻”,因此在这种情况下,“系统”将满足“轻量级”。
      • 这是一个简单而优雅的解决方案,就像一个魅力。
      • 简洁优雅?这不是真的。
      • 是的,通常有效。但这对我来说涉及太多假设:taskkill.exe 在路径中,找到的 taskkill.exe 实际上是您想要的,命令行参数没有被更新版本的 taskkill 更改.exe,WMI 服务正在运行。
      【解决方案5】:

      这是 Visual Studio 2010 C++ 项目如何通过 EXE 文件名终止进程的完整示例。

      为了检查它只需运行 Internet Explorer,然后执行以下代码。

      #include <iostream>
      #include <string>
      #include<tchar.h>
      #include <process.h>
      #include <windows.h>
      #include <tlhelp32.h>
      
      using namespace std;
      
      //  Forward declarations:
      BOOL GetProcessList();
      BOOL TerminateMyProcess(DWORD dwProcessId, UINT uExitCode);
      
      int main( void )
      {
        GetProcessList( );
        return 0;
      }
      
      BOOL GetProcessList( )
      {
        HANDLE hProcessSnap;
        HANDLE hProcess;
        PROCESSENTRY32 pe32;
        DWORD dwPriorityClass;
      
        // Take a snapshot of all processes in the system.
        hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
        if( hProcessSnap == INVALID_HANDLE_VALUE )
        {   
          return( FALSE );
        }
      
        // Set the size of the structure before using it.
        pe32.dwSize = sizeof( PROCESSENTRY32 );
      
        // Retrieve information about the first process,
        // and exit if unsuccessful
        if( !Process32First( hProcessSnap, &pe32 ) )
        {   
          CloseHandle( hProcessSnap );  // clean the snapshot object
          return( FALSE );
        }
      
        // Now walk the snapshot of processes 
        do
        {  
          string str(pe32.szExeFile);
      
          if(str == "iexplore.exe") // put the name of your process you want to kill
          {
              TerminateMyProcess(pe32.th32ProcessID, 1);
          } 
        } while( Process32Next( hProcessSnap, &pe32 ) );
      
        CloseHandle( hProcessSnap );
        return( TRUE );
      }
      
      BOOL TerminateMyProcess(DWORD dwProcessId, UINT uExitCode)
      {
          DWORD dwDesiredAccess = PROCESS_TERMINATE;
          BOOL  bInheritHandle  = FALSE;
          HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
          if (hProcess == NULL)
              return FALSE;
      
          BOOL result = TerminateProcess(hProcess, uExitCode);
      
          CloseHandle(hProcess);
      
          return result;
      }
      

      想象一下在 C# 中它看起来像

      using System;
      using System.Collections.Generic;
      using System.Text;
      
      namespace MyProcessKiller
      {
          class Program
          {
              static void Main(string[] args)
              {
                  foreach (System.Diagnostics.Process myProc in System.Diagnostics.Process.GetProcesses())
                  {
                      if (myProc.ProcessName == "iexplore")
                      {
                          myProc.Kill();
                      }
                  }
              }
          }
      }
      

      【讨论】:

        【解决方案6】:

        这里有一些工作示例代码可以杀死一个名为“ShouldBeDead.exe”的进程:

        // you will need these headers, and you also need to link to Psapi.lib
        #include <tchar.h>
        #include <psapi.h>
        
        ...
        // first get all the process so that we can get the process id 
        DWORD processes[1024], count;
        if( !EnumProcesses( processes, sizeof(processes), &count ) )
        {
            return false;
        }
        
        count /= sizeof(DWORD);
        for(unsigned int i = 0; i < count; i++)
        {
            TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
            if(processes[i] != 0)
            {
                // remember to open with PROCESS_ALL_ACCESS, otherwise you will not be able to kill it
                HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, processes[i] );
                if(NULL != hProcess)
                {
                    HMODULE hMod;
                    DWORD cbNeeded;
                    if(EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
                    {
                        GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName)/sizeof(TCHAR));
        
                        // find the process and kill it
                        if(strcmp(szProcessName, "ShouldBeDead.exe") == 0)
                        {
                            DWORD result = WAIT_OBJECT_0;
                            while(result == WAIT_OBJECT_0)
                            {
                                // use WaitForSingleObject to make sure it's dead
                                result = WaitForSingleObject(hProcess, 100);
                                TerminateProcess(hProcess, 0);
                            }
        
                            CloseHandle(hProcess);
                        }
                    }
                }
            }
        }
        

        【讨论】:

          【解决方案7】:

          OpenProcess() 所需的 PID 通常不容易获得。如果你得到的只是一个进程名称,那么你需要迭代机器上正在运行的进程。使用 CreateToolhelp32Snapshot 执行此操作,然后使用 Process32First 并使用 Process32Next 循环。 PROCESSENTRY32.szExeFile 为您提供进程名称(不是路径!),th32ProcessID 为您提供 PID。

          下一个考虑是该过程可能会出现不止一次。并且有可能将相同的进程名称用于非常不同的程序。比如“设置”。如果您不只是想全部杀死它们,则需要尝试从它们那里获取一些运行时信息。可能是窗口标题栏文本。 GetProcessImageFileName() 可以为您提供 .exe 的路径。它使用本机内核格式,您需要 QueryDosDevice 将磁盘驱动器设备名称映射到驱动器号。

          下一个考虑因素是您在 OpenProcess() 中要求的权限。你不太可能得到PROCESS_ALL_ACCESS,你只需要PROCESS_TERMINATE。虽然这也是特权。确保您用于运行程序的帐户可以获得该权限。

          【讨论】:

            【解决方案8】:

            要获取传递给TerminateProcess 的句柄,请将OpenProcessEnumProcesses 等其他函数结合使用。

            【讨论】:

            【解决方案9】:

            CreateProcessOpenProcess 返回进程句柄。

            这里有一些sample code,通过要求系统列出所有进程然后在列表中搜索您想要的进程来查找进程。

            【讨论】:

            • 那么使用带有进程 ID 的 OpenProcess 可以让我访问该进程吗?
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-01-12
            • 2023-03-08
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多