You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言宽字符命令行参数问题:传入进程名无法获取PID

问题描述

我编写了一个程序,功能是获取首个命令行参数(应为进程名)并查找对应进程的PID。核心代码如下:

在main函数中调用:

DWORD PID = FindProcessId(argv[1]);

PID查找函数定义:

DWORD FindProcessId(PWCHAR processname)
{
    NTSTATUS status;
    PVOID buffer;
    PSYSTEM_PROCESS_INFORMATION spi;
    DWORD pid = 0;

    buffer = VirtualAlloc(NULL, 1024 * 1024, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    spi = (PSYSTEM_PROCESS_INFORMATION)buffer;

    status = NtQuerySystemInformation(SystemProcessInformation, spi, 1024 * 1024, NULL);

    while (spi->NextEntryOffset) // 遍历进程列表直到找到目标PID或到末尾
    {
        if (wcsncmp(spi->ImageName.Buffer, processname, spi->ImageName.Length) == 0)
        {
            pid = spi->UniqueProcessId;
            break;
        }
        spi = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)spi + spi->NextEntryOffset); // 计算下一个进程条目地址

    }

    return pid;
}

直接在代码中传入L"notepad.exe"时,程序可正常获取PID;但通过命令行运行find_pid.exe notepad.exe时,FindProcessId返回0,明明notepad.exe正在运行却无法找到。我想用main而非wmain来让程序接收宽字符参数,为什么命令行传入时会失效?

原因分析
  1. 字符编码不匹配:main函数的argv参数是char*类型的窄字符数组,而FindProcessId接收的是PWCHAR(宽字符指针)。直接把char*强转为PWCHAR会导致编码混乱——命令行传入的ASCII字符串被当成UTF-16宽字符解析,内容完全错误,自然匹配不到进程名。
  2. wcsncmp长度参数错误:spi->ImageName.Length是宽字符的字节数(比如notepad.exe是12个字符,字节数为24),而你传入的"伪宽字符"实际长度只有12字节,wcsncmp用24作为比较长度时会读取内存垃圾数据,导致匹配失败。
解决方案

有两种可靠的修复方式:

方式一:改用wmain接收宽字符参数

这是Windows平台处理宽字符命令行参数的标准做法,系统会自动将命令行参数转换为UTF-16宽字符:

int wmain(int argc, wchar_t* argv[])
{
    if (argc < 2) return 1;
    DWORD PID = FindProcessId(argv[1]);
    // 后续逻辑
    return 0;
}

方式二:在main中手动转码窄字符为宽字符

如果坚持使用main,需要将argv[1]的窄字符转换为宽字符后再传入FindProcessId,同时修正wcsncmp的长度参数:

#include <stdlib.h> // 包含mbstowcs_s

int main(int argc, char* argv[])
{
    if (argc < 2) return 1;

    wchar_t wideName[256];
    size_t convertedChars = 0;
    mbstowcs_s(&convertedChars, wideName, sizeof(wideName)/sizeof(wchar_t), argv[1], _TRUNCATE);

    DWORD PID = FindProcessId(wideName);
    // 后续逻辑
    return 0;
}

修正FindProcessId中的比较逻辑:

// 原长度参数是字节数,替换为宽字符个数
if (wcsncmp(spi->ImageName.Buffer, processname, spi->ImageName.Length / sizeof(wchar_t)) == 0)

内容的提问来源于stack exchange,提问作者nortain32

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 01:38:28