错误234“;更多数据可供参考;使用GetComputerNameEx
我通过错误234“;更多数据可供参考;使用GetComputerNameEx,c,string,winapi,C,String,Winapi,我通过GetComputerNameEx函数获得了更多可用数据,但不知道如何修复它 这是我的代码: int wmain() { COMPUTER_NAME_FORMAT nameType = ComputerNameDnsFullyQualified; WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1]; DWORD size = ARRAYSIZE(computerName); BOOL pcName = GetCo
GetComputerNameEx
函数获得了更多可用数据,但不知道如何修复它
这是我的代码:
int wmain()
{
COMPUTER_NAME_FORMAT nameType = ComputerNameDnsFullyQualified;
WCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD size = ARRAYSIZE(computerName);
BOOL pcName = GetComputerNameEx(nameType, computerName, &size);
DWORD error = GetLastError();
if (pcName != 0)
{
wprintf("Computer name: %s\n", computerName);
}
else
{
wprintf(L"Error getting the name. Code: %li\n", error);
}
return 0;
}
不知道如何将
size
变量设置为输出,以便我可以正确声明computerName
数组。您必须调用函数两次;一次使用空指针获取所需大小,另一次使用(至少)指定大小的缓冲区。正如文件所说:
要确保此缓冲区足够大,请将此参数设置为NULL
并使用lpnSize参数中返回的所需缓冲区大小
这是Win32函数的常见模式。是的,它确实会导致可能的比赛状态,但这就是它的工作原理
示例
DWORD dwSize = 0;
if (GetComputerNameEx(nameType, nullptr, &dwSize))
{
WCHAR* computerName;
computerName = (WCHAR*)malloc(dwSize * sizeof(WCHAR));
if (GetComputerNameEx(nameType, computerName, &dwSize))
{
// use the name
}
free(computerName); // don't forget to free
}
该错误意味着
GetComputerNameEx
函数需要更大的缓冲区来存储返回的字符串
为了避免乔纳森·波特回答中提到的种族条件,你可以这样做:
LONG error = ERROR_MORE_DATA;
WCHAR* buffer = NULL;
DWORD bufferLength = /* Some initial reasonable length for the string buffer */;
while (error == ERROR_MORE_DATA) {
// Create a buffer with bufferLength size (measured in WCHARs)
buffer = realloc(buffer, bufferLength * sizeof(WCHAR));
if (GetComputerNameEx(nameType, buffer, &bufferLength)) {
error = ERROR_SUCCESS;
} else {
error = GetLastError();
}
}
if (error != ERROR_SUCCESS) {
// Some error occurred
...
}
// Use buffer containing computer name
// Don't forget to free(buffer)
根据
GetComputerNameEx()
文档:
lpBuffer[out]指向接收计算机名或群集虚拟服务器名的缓冲区的指针 名称的长度可能大于
MAX\u COMPUTERNAME\u length
字符,因为DNS允许更长的名称。要确保此缓冲区足够大,请将此参数设置为NULL
,并使用lpnSize
参数中返回的所需缓冲区大小
lpnSize[输入,输出]在输入时,指定缓冲区的大小,单位为
TCHAR
s。输出时,接收复制到目标缓冲区的TCHAR
s数,不包括终止的空字符
如果缓冲区太小,函数将失败,GetLastError
返回ERROR\u MORE\u数据
。此参数接收所需缓冲区的大小,包括终止空字符
如果lpBuffer
为空,则此参数必须为零
例如:
int wmain()
{
COMPUTER_NAME_FORMAT nameType = ComputerNameDnsFullyQualified;
WCHAR *computerName = NULL, *computerNameNew;
DWORD size = 0;
BOOL pcName;
DWORD error;
do
{
pcName = GetComputerNameExW(nameType, computerName, &size);
if (pcName) break;
error = GetLastError();
if (error != ERROR_MORE_DATA) break;
computerNameNew = (WCHAR*) realloc(computerName, sizeof(WCHAR) * size);
if (!computerNameNew) {
error = ERROR_OUTOFMEMORY;
break;
}
computerName = computerNameNew;
}
while (1);
if (pcName)
{
wprintf("Computer name: %s\n", computerName);
}
else
{
wprintf(L"Error getting the name. Code: %ul\n", error);
}
free(computerName);
return 0;
}
--lpBuffer太小。lpnSize参数包含接收名称所需的字节数。请注意,
MAX\u COMPUTERNAME\u LENGTH
不起作用的原因是,这是非限定名称的最大长度,OP的代码要求限定名称。我不确定DNS全名的长度是否有任何固定限制。但我无法在第一次调用GetComputerNameEx
后设置computerName[size]
,因为Visual Studio说表达式必须有一个常量值。我能做什么?我没有使用您的实际代码,因为我使用的是C。请使用malloc/free
而不是new/delete
。我已经更新了示例。我发布了一个答案,其中的代码我认为不会受到竞争条件的影响。仅供参考,当GetComputerNameEx()
因ERROR\u MORE\u DATA
而失败时,dwSize
的值已经包含空终止符的空间,因此您不需要++dwSize
。这是有文档记录的行为:“如果缓冲区太小,函数将失败,GetLastError
返回ERROR\u MORE\u DATA
。此参数接收所需缓冲区的大小,包括终止空字符。”如果要使用malloc()
,至少可以使用realloc()
而不是循环时的free()
。否则,请考虑使用<代码> LoalalLoCo()/代码> /<代码> LoalRealCube()/<代码>。另外,您需要使用GetLastError()
来获取错误
值,它不是由GetComputerNameEx()
本身返回的。谢谢您的评论。我已经更新了代码。无论如何,我使用free
+malloc
而不是realloc
的原因之一是在重新分配之间不需要保留以前的内存内容。True。另一方面,根据内存管理器的实现,realloc()
可以简单地扩展现有内存块,而不必在内存中的其他位置搜索和保留一个全新的块。