C++ - 以管理员身份运行进程时的 GetUserName()

Posted

技术标签:

【中文标题】C++ - 以管理员身份运行进程时的 GetUserName()【英文标题】:C++ - GetUserName() when process is run as administrator 【发布时间】:2015-04-24 16:32:33 【问题描述】:

我有一个提示用户名的简单 C++ 程序

#include <windows.h>
#include <Lmcons.h>
#include <winbase.h>

int _tmain(int argc, _TCHAR* argv[])

    wchar_t username[UNLEN + 1];
    DWORD username_len = UNLEN + 1;
    ::GetUserName(username, &username_len);

    MessageBox(NULL, username, NULL, 1);
    return 1;

GetUserName() 在管理员帐户中按预期执行,这意味着打印真实用户名。

但是,当在非管理员帐户中以管理员身份运行时,我得到的是管理员名称,而不是真正的登录用户。

我相信这种行为是意料之中的,因为它记录在 GetUserName():如果当前线程正在模拟另一个客户端,GetUserName 函数会返回该线程正在模拟的客户端的用户名。

问题

有没有办法获得真正的登录用户(非管理员用户),即使进程以管理员身份运行?

【问题讨论】:

上述“解决方案”不起作用。这样做:***.com/questions/5218778/… @UserX,该问题询问有关从服务获取当前登录用户的问题。这个问题询问如何从交互式应用程序中获取当前登录的用户。它们是不同的问题,需要不同的解决方案。 【参考方案1】:

我相信你想问 Windows 的问题是“哪个用户登录到当前会话”。

为此,请使用您自己的进程 ID 调用 ProcessIdToSessionId() 以确定当前会话 ID。

然后使用WTSUserName 选项调用WTSQuerySessionInformation() 以获取用户名。

【讨论】:

根据msdn.microsoft.com/en-us/library/aa383838%28v=vs.85%29.aspx,不是 @igalk:XP 不受支持,因此文档中对它的引用正在慢慢消失。根据可靠消息来源,WTSQuerySessionInformation() 自 Windows 2000 以来就已可用。【参考方案2】:

问题不在于冒充的线程。您正在管理员登录下运行整个应用程序。这就是为什么当您从非管理员帐户启动 Windows 时,它会要求您使用管理员帐户登录。

因此,您从GetUserName() 得到的结果是正确的。该名称是您应用的真实登录用户。

如果您想要其他名称,标准的解决方案是以普通用户身份启动,并使用“提升”按钮以提升的权限重新启动您的应用程序。看起来像任务管理器,如果您想查看所有正在运行的进程,它会执行此操作。此时,您当然可以将任何您想要的内容传递给新进程,包括该用户名。

【讨论】:

我想知道是否有一个选项可以让真正的登录用户使用提升的进程? @idanshmu:我认为这个问题没有明确定义。 什么真正的登录用户?因为就 Windows 而言,您提供了以管理员身份登录的管理员密码。那你怎么不是管理员? real 用户是激活进程的人,如果我以idan 登录并以管理员身份运行进程,real 用户是idan。无论如何,我希望能够获得idan 而不是管理员名称。例如,有人告诉我,即使您以管理员身份运行该进程,活动桌面仍位于 真实 用户控件上。一定有办法得到这个名字。 好吧,桌面只是一个由 Explorer.Exe 进程管理的大窗口。这个过程大概有“idan”作为它的所有者。但出于安全原因,UIPI(UI 进程隔离)会将您的管理员应用程序与不太安全的进程分开。为什么你甚至需要这个名字? 我不想要进程用户名。无论我的应用程序以何种方式运行,我都希望能够获得 real 用户名。对我来说,GetUserName() 应该返回最后登录的用户(当然不包括由于提升的进程所需的日志记录)。

以上是关于C++ - 以管理员身份运行进程时的 GetUserName()的主要内容,如果未能解决你的问题,请参考以下文章

从以管理员身份运行的进程以用户身份启动进程

提升进程以管理员身份运行不起作用

windows 以管理员身份运行 代码

将所发布的WinFrom程序以管理员身份运行

Linux用户和组管理及其相关命令

Linux权限管理