获取进程标识符始终返回0

时间:2019-11-17 02:25:49

标签: c++ windows winapi

因此,此代码始终为我的进程标识符返回0。

::std::uint32_t GetPID(const char* windowName)
{
    ::std::uint32_t pID; // when this is initialized to 0, my function returns 0 otherwise it returns rand

    HWND hWindow = FindWindow(NULL, (LPCWSTR)windowName);

    GetWindowThreadProcessId(hWindow, &pID);

    return pID;
}

我尝试使用其他函数,该函数也可以获取进程标识符,该函数之前对我来说是完美的,但它也返回0。我也尝试过使用其他进程名,但没有任何作用。

我尝试调试它,发现将pID初始化为0时,该函数返回0。我认为这是因为FindWindow()的HWND在某种程度上是无效的,因此GetWindowThreadProcessId()不会将我的pID变量设置为进程ID,因此它保持为0。此外,当我只定义pID时,我的函数将返回不是pid的随机数(垃圾内存,因为未初始化) ,好像来自FindWindow()的句柄无效,因此没有为pID的变量GetWindowThreadProcessId()分配任何进程标识符。)

我认为它与FindWindow()函数有关,但是我尝试放入其他进程名称,并且没有变化。我可以使用PROCESSENTRY32,但我想知道这是怎么回事。

我觉得答案就在我眼前,由于某种原因我无法弄清楚。

1 个答案:

答案 0 :(得分:1)

采用字符串参数的较旧的Windows API函数具有三种变体,一种采用窄字符串(char),一种采用宽字符串(wchar_t),而另一种则根据{ {1}}宏设置(UNICODE)。

始终使用窄字符串的函数可以在函数名称的末尾用tchar_t标识,而始终使用宽字符串的函数用A标识。

较新的API函数可能根本不提供窄版(ANSI)版本,在这种情况下,以上内容不适用。 W不是其中一种情况。

您正在使用具有变量类型的变量,并且显然FindWindow设置已为您更改,因为您说代码以前可以工作。但是,我确定您稍后添加了UNICODE强制转换,因为在任何情况下该强制转换都是错误的。

(LPCWSTR)(LPCWSTR)windowName指针强制转换为const char*指针(const wchar_t*LPCWSTR),但实际上并没有转换指针的窄字符指向宽阔的。例如,在Windows上,宽字符为2个字节宽,因此当函数取消引用指针时,const wchar_t*指向的数组的每2个字节将被解释为一个字符。但这显然没有意义。特别是,空终止符在windowName中只有一个字节,但是在char中则需要是两个字节。因此,wchar_t指向的char数组极不可能包含windowName的正确对齐的空终止符,从而在函数迭代{{1}时导致不确定的行为}越界。

因此,在最佳情况下,您将wchar_t*用作窗口名称是乱码,但很可能会出现不确定的行为。

如果要传递一个窄字符串,请使用适当的函数:

wchar_t*

通常,切勿使用C样式强制转换,因为它们可以执行许多意外的操作。而是使用FindWindowHWND hWindow = FindWindowA(NULL, windowName); 或其他合适的强制转换。单个static_cast通常是没有问题的,但是一旦您需要使用reinterpret_cast,您应该对它的实际操作非常谨慎。 C样式强制转换可以执行任何这些强制转换,因此请格外注意这一要求。


您还应该始终检查API调用的结果是否有错误,并正确处理它们。那很可能表明您static_cast调用有问题(即使调用中已经存在未定义的行为)。这也是必要的,因为您可能无法保证实际上在所有对reinterpret_cast的调用中都可以找到一个窗口,然后返回的FindWindow将不是有效的窗口句柄:

GetPID
相关问题