使用VMWare的Mac上的Windows 7中的GetComputerName()失败

时间:2014-06-05 20:11:10

标签: windows vmware

使用VMWare的Mac上的Windows 7。 GetComputerName返回ERROR_BUFFER_OVERFLOW(111)但有效长度为16且为空名称。任何想法为什么会失败?它可以与其他Windows模拟一起正常工作。

以下是演示失败的控制台应用程序的代码:

// GetComputerName.cpp : Defines the entry point for the console application.  
//  

#include "stdafx.h"  

#ifdef _DEBUG  
#define new DEBUG_NEW  
#endif  

#include <string>   // for string  
#include <vector>   // for vector  

using std::vector;  
using std::string;   

#ifdef _UNICODE  
using std::wstring;   
#define string wstring    
using std::wostringstream;  
#define ostringstream wostringstream  
#else  
#endif  

typedef vector<TCHAR> VTChar; // vtc  

CWinApp theApp;  // The one and only application object  
using namespace std;  

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])  
{  
  TCHAR tcLocalComputerName[MAX_COMPUTERNAME_LENGTH + 1]= {_T('\0')};  
  DWORD dwComputerNameLength(MAX_COMPUTERNAME_LENGTH);  
  if(!::GetComputerName(tcLocalComputerName, &dwComputerNameLength))  
  {  
    string strErrorFormat(_T("GetComputerName failed with %d; returned length was %d."));  
    VTChar vtcError(strErrorFormat.size() + 20, 0);  
    _stprintf_s(&vtcError[0], vtcError.size(), strErrorFormat.c_str(), ::GetLastError(), dwComputerNameLength);  
    AfxMessageBox(&vtcError[0], MB_ICONEXCLAMATION);  
  }    
  else  
  {  
    string strFormat(_T("GetComputerName returned \"%s\""));  
    VTChar vtcError(strFormat.size() + 30, 0);  
    _stprintf_s(&vtcError[0], vtcError.size(), strFormat.c_str(), tcLocalComputerName);  
    AfxMessageBox(&vtcError[0], MB_ICONEXCLAMATION);  
  }  

  return 0;  
}  

一位同事用了一段时间,发现如果我们再打一次电话就可以了。正在工作的应用程序实际上以迂回的方式做到了。

以下是实际运行的控制台应用程序的代码:

// GetComputerName.cpp : Defines the entry point for the console application.  
//  

#include "stdafx.h"  

#ifdef _DEBUG  
#define new DEBUG_NEW  
#endif  

#include <string>   // for string  
#include <vector>   // for vector  

using std::vector;  
using std::string;   

#ifdef _UNICODE  
using std::wstring;   
#define string wstring    
using std::wostringstream;  
#define ostringstream wostringstream  
#else  
#endif  

typedef vector<TCHAR> VTChar; // vtc  

CWinApp theApp;  // The one and only application object  
using namespace std;  

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])  
{  
  bool gotName(false);  
  TCHAR tcLocalComputerName[MAX_COMPUTERNAME_LENGTH + 1]= {_T('\0')};  
  DWORD dwComputerNameLength(MAX_COMPUTERNAME_LENGTH);  
  if(!::GetComputerName(tcLocalComputerName, &dwComputerNameLength))  
  {  
    AfxMessageBox(_T("First GetComputerName failed."));  
    if(!::GetComputerName(tcLocalComputerName, &dwComputerNameLength))  
    {  
      string strErrorFormat(_T("GetComputerName failed with %d; returned length was %d."));  
      VTChar vtcError(strErrorFormat.size() + 20, 0);  
      _stprintf_s(&vtcError[0], vtcError.size(), strErrorFormat.c_str(), ::GetLastError(), dwComputerNameLength);  
      AfxMessageBox(&vtcError[0], MB_ICONEXCLAMATION);  
    }  
    else  
      gotName= true;
  }    
  else
    gotName= true;  

  if(gotName)    
  {  
    string strFormat(_T("GetComputerName returned \"%s\""));  
    VTChar vtcError(strFormat.size() + 30, 0);  
    _stprintf_s(&vtcError[0], vtcError.size(), strFormat.c_str(), tcLocalComputerName);  
    AfxMessageBox(&vtcError[0], MB_ICONEXCLAMATION);  
  }  

  return 0;  
}  

3 个答案:

答案 0 :(得分:3)

调试Windows API调用时,您必须在通话失败后立即致电::GetLastError()

不是这个:

if(!::GetComputerName(tcLocalComputerName, &dwComputerNameLength))  
{  
    string strErrorFormat(_T("GetComputerName failed with %d; returned length was %d."));  
    VTChar vtcError(strErrorFormat.size() + 20, 0);  
    _stprintf_s(&vtcError[0], vtcError.size(), strErrorFormat.c_str(), ::GetLastError(), dwComputerNameLength);  
    AfxMessageBox(&vtcError[0], MB_ICONEXCLAMATION);  
}

但是这个:

if(!::GetComputerName(tcLocalComputerName, &dwComputerNameLength))  
{
    DWORD apiError = ::GetLastError();
    string strErrorFormat(_T("GetComputerName failed with %d; returned length was %d."));  
    VTChar vtcError(strErrorFormat.size() + 20, 0);  
    _stprintf_s(&vtcError[0], vtcError.size(), strErrorFormat.c_str(), apiError, dwComputerNameLength);  
    AfxMessageBox(&vtcError[0], MB_ICONEXCLAMATION);  
}   

像声明一样简单的字符串变量,可以覆盖线程的最后错误值。怎么样?好吧,std::string动态分配一个缓冲区来保存内容。动态分配需要调用分配器,分配器可能在其内部堆中有足够的空间,或者可能需要增加堆。如果需要增加堆,则会使用OS调用来执行此操作,现在您正在查看::VirtualAlloc而不是::GetComputerName的最后一个错误值。

答案 1 :(得分:1)

解决方案是第二次拨打电话。

以下是实际运行的控制台应用程序的代码:

// GetComputerName.cpp : Defines the entry point for the console application.  
//  

#include "stdafx.h"  

#ifdef _DEBUG  
#define new DEBUG_NEW  
#endif  

#include <string>   // for string  
#include <vector>   // for vector  

using std::vector;  
using std::string;   

#ifdef _UNICODE  
using std::wstring;   
#define string wstring    
using std::wostringstream;  
#define ostringstream wostringstream  
#else  
#endif  

typedef vector<TCHAR> VTChar; // vtc  

CWinApp theApp;  // The one and only application object  
using namespace std;  

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])  
{  
  bool gotName(false);  
  TCHAR tcLocalComputerName[MAX_COMPUTERNAME_LENGTH + 1]= {_T('\0')};  
  DWORD dwComputerNameLength(_countof(tcLocalComputerName));  
  if(!::GetComputerName(tcLocalComputerName, &dwComputerNameLength))  
  {  
    dwComputerNameLength= _countof(tcLocalComputerName);  
    AfxMessageBox(_T("First GetComputerName failed."));  
    if(!::GetComputerName(tcLocalComputerName, &dwComputerNameLength))  
    {  
      DWORD dwLastError(::GetLastError());  
      string strErrorFormat(_T("GetComputerName failed with %d; returned length was %d."));  
      VTChar vtcError(strErrorFormat.size() + 20, 0);  
      _stprintf_s(&vtcError[0], vtcError.size(), strErrorFormat.c_str(), dwLastError, dwComputerNameLength);  
      AfxMessageBox(&vtcError[0], MB_ICONEXCLAMATION);  
    }  
    else  
      gotName= true;
  }    
  else
    gotName= true;  

  if(gotName)    
  {  
    string strFormat(_T("GetComputerName returned \"%s\""));  
    VTChar vtcError(strFormat.size() + 30, 0);  
    _stprintf_s(&vtcError[0], vtcError.size(), strFormat.c_str(), tcLocalComputerName);  
    AfxMessageBox(&vtcError[0], MB_ICONEXCLAMATION);  
  }  

  return 0;  
}  

答案 2 :(得分:0)

这是错误的:

TCHAR tcLocalComputerName[MAX_COMPUTERNAME_LENGTH + 1]= {_T('\0')};  
DWORD dwComputerNameLength(MAX_COMPUTERNAME_LENGTH);  

documentation for GetComputerName很清楚:

  

lpnSize [in,out]

     

在输入时,在TCHAR中指定缓冲区的大小。

所以正确的代码是

TCHAR tcLocalComputerName[MAX_COMPUTERNAME_LENGTH + 1]= {_T('\0')};  
DWORD dwComputerNameLength(MAX_COMPUTERNAME_LENGTH + 1);  

甚至更好,

TCHAR tcLocalComputerName[MAX_COMPUTERNAME_LENGTH + 1]= {_T('\0')};  
DWORD dwComputerNameLength(_countof(tcLocalComputerName));