错误234"有更多数据可用"使用GetComputerNameEx

时间:2016-10-19 22:29:01

标签: c string winapi

More data is available函数出现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数组。

3 个答案:

答案 0 :(得分:5)

你必须两次调用该函数;一次使用空指针获取所需大小,并再次使用(至少)指定大小的缓冲区。正如文档所说:

  

要确保此缓冲区足够大,请将此参数设置为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
}

答案 1 :(得分:3)

根据GetComputerNameEx()文档:

  

lpBuffer [out]
  指向接收计算机名称或群集虚拟服务器名称的缓冲区的指针。

     

名称的长度可能大于MAX_COMPUTERNAME_LENGTH个字符,因为DNS允许更长的名称。要确保此缓冲区足够大,请将此参数设置为NULL并使用lpnSize参数中返回的所需缓冲区大小。

     

lpnSize [in,out]
  输入时,在TCHAR s中指定缓冲区的大小。在输出时,接收复制到目标缓冲区的TCHAR个数,不包括终止空字符。

     

如果缓冲区太小,则函数失败,GetLastError返回ERROR_MORE_DATA 。此参数接收所需缓冲区的大小,包括终止空字符。

     

如果lpBuffer为NULL,则此参数必须为零。

例如:

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;
}

答案 2 :(得分:1)

该错误意味着GetComputerNameEx函数需要更大的缓冲区来存储返回的字符串。

为了避免Jonathan Potter的回答中引用的竞争条件,你可以这样做:

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)