获取计算机名称和已登录用户名称

29

我正在开发一个应用程序。其中一个方法需要捕获计算机名称和登录到机器上的用户,然后向用户显示两者。我需要它在Windows和Linux上运行。最佳方法是什么?


1
另一个需要考虑的问题是,如果用户在Windows终端服务器上运行应用程序,他需要获取哪台计算机的名称? - Arioch 'The
6个回答

28

Windows

您可以尝试使用GetComputerNameGetUserName,这是一个示例:

#define INFO_BUFFER_SIZE 32767
TCHAR  infoBuf[INFO_BUFFER_SIZE];
DWORD  bufCharCount = INFO_BUFFER_SIZE;

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

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

参考:GetComputerNameGetUserName

Linux

使用gethostname获取计算机名(参见gethostname的文档),并使用getlogin_r获取登录用户名。您可以在getlogin_r的man页中查看更多信息。简单用法如下:

#include <unistd.h>
#include <limits.h>

char hostname[HOST_NAME_MAX];
char username[LOGIN_NAME_MAX];
gethostname(hostname, HOST_NAME_MAX);
getlogin_r(username, LOGIN_NAME_MAX);

2
关于 HOST_NAME_MAX - Antonio
2
32 KB?你只需要恰好MAX_COMPUTERNAME_LENGTH+1个字符... 考虑到前者只有15个字符,32 KB是一个巨大的浪费... - atlaste

25

如果您可以使用Boost,您可以按照以下方式轻松获取主机名:

#include <boost/asio/ip/host_name.hpp>
// ... whatever ...
const auto host_name = boost::asio::ip::host_name();

2
这是唯一真正跨平台的答案,谢谢! - oLen
1
有没有Boost函数可以获取登录名? - an4s
这只返回一个字符串而不是宽字符串。对于例如中国来说是不够的。 - Tom Henn

10

在 POSIX 系统上,可以使用 gethostnamegetlogin 函数,这两个函数在 unistd.h 中声明。

/*
   This is a C program (I've seen the C++ tag too late).  Converting
   it to a pretty C++ program is left as an exercise to the reader.
*/

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main()
{
  char hostname[HOST_NAME_MAX];
  char username[LOGIN_NAME_MAX];
  int result;
  result = gethostname(hostname, HOST_NAME_MAX);
  if (result)
    {
      perror("gethostname");
      return EXIT_FAILURE;
    }
  result = getlogin_r(username, LOGIN_NAME_MAX);
  if (result)
    {
      perror("getlogin_r");
      return EXIT_FAILURE;
    }
  result = printf("Hello %s, you are logged in to %s.\n",
                  username, hostname);
  if (result < 0)
    {
      perror("printf");
      return EXIT_FAILURE;
    }
  return EXIT_SUCCESS;
}

可能的输出:

Hello 5gon12eder, you are logged in to example.com.

相比于不总是存在的环境变量,这看起来更安全。

我撤回了上述声明,因为

  • getlogin 的手册实际上不鼓励使用它,而推荐使用getenv("LOGIN")
  • 在上面的程序中,当我从Emacs中运行程序而不是交互式终端时,getlogin_r调用失败并返回错误码ENOTTY,而getenv("USER")则可以在两种情况下都工作。

7

使用 gethostname() 函数获取计算机名称,支持 WindowsLinux


5

关于Denis的回答,需要注意的是,在Linux上,getenv("HOSTNAME")不一定总是有效的,因为环境变量可能没有被导出到程序中

获取计算机名称的跨平台C++代码示例(这是在我的Win7和CentOS机器上工作的代码):

    char *temp = 0;
    std::string computerName;

#if defined(WIN32) || defined(_WIN32) || defined(_WIN64)
    temp = getenv("COMPUTERNAME");
    if (temp != 0) {
        computerName = temp;
        temp = 0;
    }
#else
    temp = getenv("HOSTNAME");
    if (temp != 0) {
        computerName = temp;
        temp = 0;
    } else {
        temp = new char[512];
        if (gethostname(temp, 512) == 0) { // success = 0, failure = -1
            computerName = temp;
        }
        delete []temp;
        temp = 0;
    }
#endif

1
不仅它不总是对程序可用,而且还存在其他缺陷。在Linux/POSIX中,使用gethostname()无疑是更好的答案。 - villapx

0

在Linux中,您还可以使用Posix库来检索拥有进程的真实用户:getuid()返回调用进程的真实用户ID。请参见getuid man page

#include <pwd.h>
string userName = "unknownUser";
// Structure to store user info
struct passwd p;
// Get user ID of the application
uid_t uid = getuid();

// Buffer that contains password additional information
char pwdBuffer[ourPwdBufferSize];
// Temporary structure for reentrant function
struct passwd* tempPwdPtr;

if ((getpwuid_r(uid, &p, pwdBuffer, sizeof(pwdBuffer),
        &tempPwdPtr)) == 0) {
    userName = p.pw_name;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接