【问题标题】:C++ Process32Next only returns the same processC++ Process32Next 只返回相同的进程
【发布时间】:2016-06-27 00:32:04
【问题描述】:

我一直在尝试开发一个 C++ 库,目的是仅通过名称来杀死进程。如某处所述,我必须进行系统快照,然后列出每个进程(通过它的 ID),打开进程并检查它的文件名是否与传递给函数的文件名相同,如果是,则将其杀死。

这是我的代码: ma​​in.cpp

#include <iostream>
#include "proman.hpp"
using namespace std;

int main(int argc, char* argv[])
{
    cout << "INIT PRUBA" << endl;
    cout << "Trying to kill cmd.exe" << endl;
    const TCHAR* proc = L"cmd.exe";
    killPBN(proc);
    getchar(); getchar();
    return 0;
}

proman.hpp

#ifndef INC_PROMAN_H
#define INC_PROMAN_H


#include <TCHAR.h> //http://www.codeproject.com/Articles/76252/What-are-TCHAR-WCHAR-LPSTR-LPWSTR-LPCTSTR-etc
#include <windows.h>
#include <tlhelp32.h>
#include <iostream>
#include "proman.cpp"
//Function prototypes

bool killPBN(const TCHAR *procname); 



#endif

proman.cpp

bool killPBN(const TCHAR *procname)//
{
    //Compiles, but doesnt work, probablemente el fallo este en el compare dentro del for(;;) ==
    //Init some stuff
    TCHAR processPath[MAX_PATH];
    DWORD processId;
    HANDLE tmpHandle = NULL;
    BOOL b;
    
    //Handle to store the snapshot
    HANDLE systemSnap;
    //Initialize to every process dump (no heap nor modules)
    systemSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    if (systemSnap==INVALID_HANDLE_VALUE)
    {
        std::cout << "Can't snap system" << std::endl;
        throw(NULL);
    }
    
    //We have our snapshot, we need to enumerate every process (get its ID)
    //A custom handle to store process data
    PROCESSENTRY32 procHandler;
    //Initialize dwSize so Process32First won't fail
    procHandler.dwSize = sizeof(PROCESSENTRY32);
    //We are ready to call Process32First
    Process32First(systemSnap, &procHandler);
    //Got our first process, now, dump it's ID and ExeFile
    //processPath = procHandler.szExeFile; //Exe Path
    //processId   = procHandler.th32ProcessID; //PID
    
    std::cout << "First Proc: " << procHandler.szExeFile << std::endl;
    
    if (procHandler.szExeFile == procname) //parameter here, use strncompare o como sea
    {
        //Try to open process
        tmpHandle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, procHandler.th32ProcessID);
        //If opened, kill process
        if (NULL != tmpHandle)
        {   
            std::cout << "Killing: " << procHandler.szExeFile << std::endl;
            TerminateProcess(tmpHandle, 0);
            return 0; 
        }
        //If not opened, throw expection of no admin rights
        else
        {
            //no admin rights?
            //throw(std::out_of_range); 
            std::cout << "Can't Kill Proc: " << procHandler.szExeFile << std::endl;
        }
    }
    else
    {
        while(1==1)
        {
            //The process wasn't the one we were looking for, look next
            b = Process32Next(systemSnap, &procHandler);
            if (b==FALSE)
            {/*throw(proc_not_found);*/
                std::cout << "No more processes" << std::endl;
                break;
            } //no deberia hacer throw, eso solo si hay un error, aqui usar un return!!! si no hay mas procesos
            else
            {
                if (procHandler.szExeFile == procname)
                {
                    tmpHandle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, procHandler.th32ProcessID);
                    if (NULL != tmpHandle)
                    {   
                        TerminateProcess(tmpHandle, 0);
                    }
                }
                else
                {
                    std::cout << "Can't kill " << procHandler.szExeFile <<std::endl;
                    //throw(std::out_of_range); //no admin rights?
                }   
            }
        }   
                
    }
    std::cout << " Exit Success";
    

    //Deletes snapshot and tmpHandle
    CloseHandle(systemSnap);
    CloseHandle(tmpHandle);
    return 0;
    
}

我知道代码有点大。这个想法是看第一个过程,如果不是想要的,看下一个过程。但是,这是输出:

INIT PRUBA
Trying to  kill cmd.exe
First Proc: 00C1F510
Can't kill 00C1F510
Can't kill 00C1F510
Can't kill 00C1F510
Can't kill 00C1F510
Can't kill 00C1F510
Can't kill 00C1F510
Can't kill 00C1F510
Can't kill 00C1F510
Can't kill 00C1F510
Can't kill 00C1F510
Can't kill 00C1F510
...
No more processes
 Exit Success

如您所见,该程序似乎没有读取比第一个进程更多的内容。

感谢您的宝贵时间,

编辑:如您所见,szExeFile 应该类似于 cmd.exe(exe 名称),但它可能是某种地址?

EDIT2:另外,请注意 TCHAR,它应该被 ANSI/UNICODE char/wchart 替换,具体取决于编译器设置。

【问题讨论】:

  • if (procHandler.szExeFile == procname) 没有达到您的预期——尝试使用调试器并单步执行代码
  • 你的代码有很多错误。我不能让自己看这个,因为太多了。
  • 实在太多了。我无法面对。特别是当他们被指出时你不注意。
  • 我不注意吗?来自 msdn:szExeFile 进程的可执行文件的名称,因此对于它返回的内容没有明显的解释。我应该再说一遍,只是说“有这么多”绝对没有帮助,最好不要发表评论。
  • 第一条评论指出 == 是错误的。它甚至写在你自己代码的注释中。

标签: c++ winapi process kill


【解决方案1】:

正如@BarmakShemirani 所指定,我将使用 Unicode 函数作为 wcout 或 wcscmp。 谢谢。

【讨论】:

  • 如果您要使用 TCHAR,那就错了。你不应该使用 TCHAR。使用 Unicode。
  • 澄清一下,您应该将TCHAR 替换为WCHARwchar_t
  • @HarryJohnston 所以,对于支持 unicode 的程序,我将使用 WCHAR / wchar_t 和 unicode 函数,而对于标准的非 unicode,只使用 char 和普通函数?谢谢。
  • @PedroJavierFernández:事情并没有那么简单。您应该始终在 Unicode 模式下构建,并且几乎始终将 wchar_t 用于 Win32 API 函数。您的程序是否支持 Unicode,例如,它使用的任何数据文件,如果支持,您应该如何在内部对其进行编码,是一个完全独立的问题。您可以随时根据需要在内部编码和 UTF-16 之间进行转换。 (一个警告:如果您需要稳健地处理文件名,例如,如果您正在编写文件系统实用程序,则需要将文件名保留为 UTF-16,因为转换它们可能会丢失信息。)
猜你喜欢
  • 2013-12-15
  • 1970-01-01
  • 1970-01-01
  • 2020-09-17
  • 1970-01-01
  • 2014-01-30
  • 1970-01-01
  • 2011-09-09
相关资源
最近更新 更多