【问题标题】:C++ Microsoft example to get and display the user name doesn't compile获取和显示用户名的 C++ Microsoft 示例无法编译
【发布时间】:2020-07-31 04:12:03
【问题描述】:

我想以最简单的方式在 C++ 中获取用户名。我的程序仅适用于 Windows。

我想使用Microsoft example。我将代码示例复制粘贴到新的 Visual Studio 2019 中,但 TEXT 指令出现错误:

“const wchar_t *”类型的值不能用于初始化“TCHAR *”类型的实体

TCHAR* envVarStrings[] =
{
  TEXT("OS         = %OS%"),
  TEXT("PATH       = %PATH%"),
  TEXT("HOMEPATH   = %HOMEPATH%"),
  TEXT("TEMP       = %TEMP%")
};
...
printError(TEXT("GetUserName"));
...

这是完整的代码:

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

TCHAR* envVarStrings[] =
{
  TEXT("OS         = %OS%"),
  TEXT("PATH       = %PATH%"),
  TEXT("HOMEPATH   = %HOMEPATH%"),
  TEXT("TEMP       = %TEMP%")
};
#define  ENV_VAR_STRING_COUNT  (sizeof(envVarStrings)/sizeof(TCHAR*))
#define INFO_BUFFER_SIZE 32767
void printError( TCHAR* msg );

void main( )
{
  DWORD i;
  TCHAR  infoBuf[INFO_BUFFER_SIZE];
  DWORD  bufCharCount = INFO_BUFFER_SIZE;

  // Get and display the name of the computer. 
  bufCharCount = INFO_BUFFER_SIZE;
  if( !GetComputerName( infoBuf, &bufCharCount ) )
    printError( TEXT("GetComputerName") ); 
  _tprintf( TEXT("\nComputer name:      %s"), infoBuf ); 

  // Get and display the user name. 
  bufCharCount = INFO_BUFFER_SIZE;
  if( !GetUserName( infoBuf, &bufCharCount ) )
    printError( TEXT("GetUserName") ); 
  _tprintf( TEXT("\nUser name:          %s"), infoBuf ); 

  // Get and display the system directory. 
  if( !GetSystemDirectory( infoBuf, INFO_BUFFER_SIZE ) )
    printError( TEXT("GetSystemDirectory") ); 
  _tprintf( TEXT("\nSystem Directory:   %s"), infoBuf ); 

  // Get and display the Windows directory. 
  if( !GetWindowsDirectory( infoBuf, INFO_BUFFER_SIZE ) )
    printError( TEXT("GetWindowsDirectory") ); 
  _tprintf( TEXT("\nWindows Directory:  %s"), infoBuf ); 

  // Expand and display a few environment variables. 
  _tprintf( TEXT("\n\nSmall selection of Environment Variables:") ); 
  for( i = 0; i < ENV_VAR_STRING_COUNT; ++i )
  {
    bufCharCount = ExpandEnvironmentStrings(envVarStrings[i], infoBuf,
        INFO_BUFFER_SIZE ); 
    if( bufCharCount > INFO_BUFFER_SIZE )
      _tprintf( TEXT("\n\t(Buffer too small to expand: \"%s\")"), 
              envVarStrings[i] );
    else if( !bufCharCount )
      printError( TEXT("ExpandEnvironmentStrings") );
    else
      _tprintf( TEXT("\n   %s"), infoBuf );
  }
  _tprintf( TEXT("\n\n"));
}

void printError( TCHAR* msg )
{
  DWORD eNum;
  TCHAR sysMsg[256];
  TCHAR* p;

  eNum = GetLastError( );
  FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | 
         FORMAT_MESSAGE_IGNORE_INSERTS,
         NULL, eNum,
         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
         sysMsg, 256, NULL );

  // Trim the end of the line and terminate it with a null
  p = sysMsg;
  while( ( *p > 31 ) || ( *p == 9 ) )
    ++p;
  do { *p-- = 0; } while( ( p >= sysMsg ) &&
                          ( ( *p == '.' ) || ( *p < 33 ) ) );

  // Display the message
  _tprintf( TEXT("\n\t%s failed with error %d (%s)"), msg, eNum, sysMsg );
}

我怎样才能创建一个函数,我应该包含哪些头文件?

std::wstring getUsername() {
   //...
}

【问题讨论】:

    标签: c++ windows winapi wchar-t tchar


    【解决方案1】:

    代码假定为 C 编译器。要将此编译为 C++,您必须将envVarStrings 声明为TCHAR const* envVarStrings[],并将void printError( TCHAR* msg ) 的签名更改为void printError( TCHAR const* msg )。与 C 不同,您不能将字符串文字分配给 C++ 中指向非 const 的指针。

    如果您只需要用户名,您可以调用GetUserName 而不是读取环境变量。 API 调用返回与调用线程关联的用户名。

    【讨论】:

    • @ben:确实。尽管如此,我仍不清楚 OP 试图完成什么。他们也是在读取环境变量,毕竟有%USERNAME%,所以我加了一个注释,不需要读取环境变量。
    • 仅供参考,Win32 API 有一个 LPCTSTR 别名 const TCHAR *: LPCTSTR envVarStrings[] = ...; void printError( LPCTSTR msg )
    • @rem:这些别名的主要目的是通过添加间接级别来为 ABI 建模。有问题的代码不会跨越 ABI,因此它不会从使用这些别名中受益。在这种情况下,它们只是增加了使用语言级别类型语法的复杂性。通过语法突出显示,您可以获得*const 限定符的视觉提示。与使用 LPCTSTR 之类的别名相比,这减少了读者的心理负担,将所有内容组合成一个令牌。该令牌需要由当时不需要分心的人分解为其组成部分。
    【解决方案2】:

    Win32 API 提供您所需要的。函数GetUserNameWGetComputerNameW 正是你所需要的,用法也很简单。这是一个有效的例子:

    #include <iostream>
    #include <string>
    #include <windows.h>
    #include <Lmcons.h>
    
    std::wstring getUsername() {
        wchar_t username[UNLEN + 1];
        DWORD username_len = UNLEN + 1;
        GetUserNameW(username, &username_len);
        return username;
    }
    
    std::wstring getComputerName() {
        wchar_t computerName[UNLEN + 1];
        DWORD computerName_len = UNLEN + 1;
        GetComputerNameW(computerName, &computerName_len);
        return computerName;
    }
    
    int main()
    {
        std::wcout << L"Username is : " << getUsername() << std::endl;
        std::wcout << L"Computer name is : " << getComputerName() << std::endl;
        return 0;
    }
    

    【讨论】:

    • L"Username is : " 当您使用宽流时。
    • 不过,这并不能回答问题。
    • @IInspectable,粗体字的问题是:How can I made a function and which headers should I include ?。我给填充的函数提供了相同的签名。
    • 这是问题的标题:“获取和显示用户名的 C++ Microsoft 示例无法编译”。此外,您传递的数组大小错误以检索计算机名称(请参阅documentation)。然后,零错误处理。
    • 附带说明,由于GetUserNameW()GetComputerNameW() 都输出最终的字符串长度,我建议在构造std::wstring 值时使用这些长度,例如return std::wstring(username, username_len-1); ... @ 987654332@ 这样std::wstring 就不用重新计算事先已经知道的长度了。
    猜你喜欢
    • 2019-05-10
    • 2012-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多