使用标准用户帐户在提升的脚本中获取登录用户名

Posted

技术标签:

【中文标题】使用标准用户帐户在提升的脚本中获取登录用户名【英文标题】:Get logon username in elevated script with standard user account 【发布时间】:2020-08-07 09:17:47 【问题描述】:

在我在 Windows 7 中运行的批处理脚本中,我有几个 IF 子句,例如:

IF "%USERNAME%"=="foo" GOTO bar

不幸的是,当我从上下文菜单中使用“以管理员身份运行”运行此批处理脚本时,%USERNAME% 始终是管理员的用户名,而不是当前活动登录用户的用户名。

这同样适用于提升的批处理脚本中的whoami

QUERY USER 为我提供了当前登录的所有用户的列表,而不仅仅是我正在寻找的那个用户。

一个标准用户帐户,不像管理员帐户可以从用户组令牌提升到管理员组令牌,同时保持相同的用户环境,实际上在“以管理员身份运行”时加载管理员帐户环境选择。

有没有办法获取当前活动的登录用户名而不是管理员用户名?

【问题讨论】:

@Compo @michael_heath 看来我没有正确解释这个问题。因此,为了澄清,问题存在于登录用户(非管理员)选择以管理员身份运行脚本的那一刻。如果有人以 user1(非管理员)身份登录,然后管理员选择使用“以管理员身份运行”(user2)运行程序,则批处理脚本%USERNAME% 显示管理员的名称(user2)。我是 Windows 7 PC 的管理员,有时普通用户已登录,我需要以管理员权限启动程序,但我想访问已登录用户的用户名。 @Compo,当一个 Windows 用户(非管理员),说“pupil123”,登录,然后我,管理员(“teacheradmin1”),右键单击一个程序并选择“在 .bat 文件上以管理员身份运行”(=我)并在 UAC 提示符中输入我的密码,然后echo %username% 显示我的用户名(“teacheradmin1”),而不是登录用户的用户名(“pupil123” )。我的问题是是否可以显示登录用户的用户名而不是 run-as-admin 用户。 【参考方案1】:

WMIC 计算机系统获取用户名

@echo off
setlocal

rem Get logon username without the leading "computername\" string.
set "user="

for /f "skip=1 tokens=1,* delims=\" %%A in (
    'wmic computersystem get username ^|findstr /r /v "^$"'
) do for %%C in (%%~B) do if not defined user set "user=%%~C"

echo "%user%"
pause

使用for /f 选项skip=1,因为第一行是不需要的UserName 标头。由\ 分隔,因为值将类似于computername\username 并在第二个令牌中获取余数。管道到findstr 以忽略空行。第二个for 循环将获得第一个没有空白字符的值。

wmic 输出传送到powershell 以清理输出测试比传送到findstr 更好,并且不需要使用第二个for 循环。

@echo off
setlocal

rem Get logon username without the leading "computername\" string.
set "user="

for /f "skip=1 tokens=1,* delims=\" %%A in ('
    wmic computersystem get username ^|
    powershell -noprofile -command "$input.trim()"
') do set "user=%%~B"

echo "%user%"
pause

使用command /? 获得更多帮助。代码中的大多数命令都会在命令提示符处显示带有 /? 参数的帮助。

查询用户别名QUser

@echo off
setlocal

rem Get logon username.
set "user="

for /f %%A in ('quser^|findstr /b /c:">"') do set "user=%%~A"

if defined user if "%user:~0,1%" == ">" set "user=%user:~1%"

echo "%user%"
pause

quser 中的前导 >query user 的别名)表示当前登录的用户名,而不是管理员的用户名。

在需要时使用%user% 而不是%username%

注意事项:

由于for /f循环从token=1的默认选项获取用户名,如果用户名包含空格或制表符,那么这将只获取空格或制表符之前的字符。

在 64 位操作系统上,quser.exe 存在于 System32 中,而不存在于 SysWOW64 中。 64 位操作系统上的 32 位 cmd.exe 可能无法识别为命令。

参考资料:

query user Query User / QUSER

【讨论】:

非常感谢@michael_heath!不幸的是,这似乎不适用于所有命令 shell。当我从 Total Commander(提升和未提升)启动 cmd.exe 或使用 MobaXTerm 的 cmd shell 时,我得到'quser' is not recognized as an internal or external command。您还建议了另一个解决方案:wmic computersystem get username,它适用于每个 cmd 窗口。有没有办法在批处理文件中使用wmic 来获取用户名? 如果这些程序是 32 位的,则可能找不到 quser.exe,因为 quser.exe 不在 SysWOW64 目录中。您可以在 64 位操作系统上使用%SystemRoot%\SysNative\quser.exe,因为SysNative 将重定向并访问System32 中的quser.exe。添加了 WMIC 代码。 漂亮!您的代码有效! @michael_heath,你是一个很棒的人。知识渊博,乐于助人和友好!而且快!非常感谢。 缩短版:for /f "tokens=2 delims=\" %%f in ('wmic computersystem get username') do set "LoggedOnUser=%%f"

以上是关于使用标准用户帐户在提升的脚本中获取登录用户名的主要内容,如果未能解决你的问题,请参考以下文章

从提升的子进程获取错误和标准输出

用户登录后路由到用户帐户

是否可以使用谷歌应用程序脚本以编程方式锁定用户帐户(g 套件)

Visual Studio 安装项目 - 使用 Windows 标准用户帐户安装当前用户

如何为具有多个帐户的用户在Google App Scripts中选择帐户?

无法在 UWP 应用中获取某些用户帐户信息 - 内部活动目录(不是 Azure AD)