因此,此代码始终为我的进程标识符返回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
,但我想知道这是怎么回事。
我觉得答案就在我眼前,由于某种原因我无法弄清楚。
答案 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样式强制转换,因为它们可以执行许多意外的操作。而是使用FindWindow
或HWND hWindow = FindWindowA(NULL, windowName);
或其他合适的强制转换。单个static_cast
通常是没有问题的,但是一旦您需要使用reinterpret_cast
,您应该对它的实际操作非常谨慎。 C样式强制转换可以执行任何这些强制转换,因此请格外注意这一要求。
您还应该始终检查API调用的结果是否有错误,并正确处理它们。那很可能表明您static_cast
调用有问题(即使调用中已经存在未定义的行为)。这也是必要的,因为您可能无法保证实际上在所有对reinterpret_cast
的调用中都可以找到一个窗口,然后返回的FindWindow
将不是有效的窗口句柄:
GetPID