stricmp 在我的代码中不起作用

stricmp doesn't work in my code

我正在循环浏览 TlHelp32 的进程快照,然后将名称与 stricmp 进行比较以获取进程句柄。问题是即使两个值看起来相同,但它们显然不是,因为它不是 return 0 。虽然我不知道为什么,我也尝试将进程名称写入函数。

HANDLE GetProcessValues(std::string ProcName)
{
   const char* ProcNameChar = ProcName.c_str();
   HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   PROCESSENTRY32 process;
   ZeroMemory(&process, sizeof(process));
   process.dwSize = sizeof(process);
   if (Process32First(snapshot, &process))
   {
       do
       {
           if (_stricmp((char*)process.szExeFile,ProcNameChar)==0)
           {
               HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID);
               return hProc;
           }
       }while (Process32Next(snapshot,&process));
   }
   return 0;
}

我调试它以查看这些值是否合适:

在处理 wchar* 数据类型时,使用 _wcsicmp 进行比较,并且 - 如有必要 - 将任何涉及的 char* 数据类型转换为 wchar* 等价的数据类型,例如使用 CStringW class。授予 microsoft _wcsicmp, and be also aware of using a correct locale. A similar problem, yet with wchar* constants, has been described at stack overflow

问题是您正在使用 TCHAR 版本的 Process32First()/Process32Next(),并且您的调试器屏幕截图清楚地显示您正在为 Unicode 编译项目,所以 TCHAR 映射到 WCHAR,因此 process.szExeFile 是一个 WCHAR[] 数组。您将该数组错误地类型转换为 char* 指针。您不能直接将 Unicode 字符串与 Ansi 字符串进行比较。在比较它们之前,您需要将一个字符串转换为另一个字符串的编码。

您还泄露了 CreateToolhelp32Snapshot() 返回的 HANDLE

由于您将 Ansi std::string 作为输入传递给 GetProcessValues() 函数,最简单的 解决方案是使用 Ansi 版本的 Process32First()/Process32Next() 相反,因此 process.szExeFile 现在是一个 CHAR[] 数组,因此不需要转换:

HANDLE GetProcessValues(std::string ProcName)
{
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (snapshot == INVALID_HANDLE_VALUE)
        return NULL;

    PROCESSENTRY32A process;
    ZeroMemory(&process, sizeof(process));
    process.dwSize = sizeof(process);

    const char* ProcNameChar = ProcName.c_str();
    HANDLE hProc = NULL;

    if (Process32FirstA(snapshot, &process))
    {
        do
        {
            if (_stricmp(process.szExeFile, ProcNameChar) == 0)
            {
                hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID);
                break;
            }
        }
        while (Process32NextA(snapshot, &process));
    }

    CloseHandle(snapshot);
    return hProc;
}

但是,您真的应该远离使用 Ansi APIs。 Windows 是基于 Unicode 的 OS,并且已经存在了很长时间。使用 Unicode APIs 代替:

HANDLE GetProcessValues(std::wstring ProcName)
{
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (snapshot == INVALID_HANDLE_VALUE)
        return NULL;

    PROCESSENTRY32W process;
    ZeroMemory(&process, sizeof(process));
    process.dwSize = sizeof(process);

    const wchar_t* ProcNameChar = ProcName.c_str();
    HANDLE hProc = NULL;

    if (Process32FirstW(snapshot, &process))
    {
        do
        {
            if (_wcsicmp(process.szExeFile, ProcNameChar) == 0)
            {
                hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID);
                break;
            }
        }
        while (Process32NextW(snapshot, &process));
    }

    CloseHandle(snapshot);
    return hProc;
}

如果您的 ProcName 参数绝对必须是 std::string,那么您可以:

  1. 使用 MultiByteToWideChar()std::wstring_convert 等将 ProcName 转换为 Unicode,然后将该结果与 Unicode API 返回的字符串进行比较.

  2. 使用 WideCharToMultiByte()std::wstring_convert 等将字符串从 Unicode API 转换为 Ansi,然后将这些结果与 ProcName 进行比较。 =36=]