【问题标题】:stricmp doesn't work in my codestricmp 在我的代码中不起作用
【发布时间】:2023-03-14 07:30:01
【问题描述】:

我正在循环浏览 TlHelp32 的进程快照,然后将名称与 stricmp 进行比较以获取进程句柄。问题是即使两个值似乎相同,但它们显然不是,因为它不返回 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;
}

我对其进行了调试以查看这些值是否合适:

【问题讨论】:

  • 你为什么在_stricmp的第一个参数中转换为char *?如果是因为类型不匹配错误而关闭编译器,请停止这样做并为函数提供正确的字符串类型。永远不要转换字符串类型——转换是不是转换。
  • 你欺骗了编译器,得到了你应得的甜点
  • 让您的应用程序使用 Unicode,而不是 hack。并使用std::wstring 代替std::stringwchar_t 代替char 等。
  • 你需要明白你必须停止对编译器撒谎的事实。这是第 1 步。
  • 问题是你有一个大杂烩的字符串类型,你没有一个连贯的设计来确定你的应用程序使用的实际字符串类型。这里是字符,那里是 wchar,这里是 Unicode 函数调用,那里是 ANSI 函数调用,等等。专注于使用一种且仅一种字符串类型,并调用处理这些字符串类型的正确函数。最好坚持使用 Unicode,因为目前在 Windows 时代创建的 MBCS 应用程序非常少。

标签: c++ winapi comparison data-conversion


【解决方案1】:

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

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

由于您将 Ansi std::string 作为输入传递给您的 GetProcessValues() 函数,因此最简单的解决方案是使用 Process32First()/ 的 Ansi 版本而是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 API。 Windows 是一个基于 Unicode 的操作系统,并且已经存在了很长时间。改用 Unicode API:

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 进行比较。

【讨论】:

    【解决方案2】:

    在处理 wchar* 数据类型时,使用 _wcsicmp 进行比较,并且 - 如有必要 - 将任何涉及的 char* 数据类型转换为 wchar* 等效项,例如使用 CStringW 类。授予microsoft _wcsicmp,并注意使用正确的语言环境。 stack overflow

    描述了一个类似的问题,但使用 wchar* 常量

    【讨论】:

    • wchar* 不是 C++ 中的整数数据类型。您将此与 C++ 的 wchar_t* 或 Windows SDK 的 WCHAR* 混淆了。除此之外,CStringW(大概)是一个 MFC/ATL 类模板。除非您正在编写 MFC 或 ATL 代码,否则这不适用(通常不适用于 Windows API 编程)。 Windows API 中的转换函数是MultiByteToWideChar。 C++ 替代方案是std::mbstowcs
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-25
    • 2019-02-13
    • 2021-10-02
    • 2020-09-19
    • 2015-02-04
    相关资源
    最近更新 更多