如何检测CMD是否以管理员身份运行/具有提升的权限?

156

我想从批处理文件内部测试是否以管理员/提升权限运行。

当选择“以管理员身份运行”时,用户名不会更改,因此这种方法不起作用。

如果存在一个普遍可用的命令,它没有任何影响,但需要管理员权限,那么我可以运行该命令并检查错误代码以测试权限。到目前为止,我还没有找到这样的命令。我发现的命令似乎只返回单个、不具体的错误代码,可能表示任何事情,并且容易因各种原因而失败。

我只关心Windows 7,尽管支持早期操作系统也很好。


一个 hack 的方法是尝试将 echo > somefile 执行到需要管理员权限的目录中。这会产生一个文件作为副作用,但你可以检查冲突并创建一个唯一的文件名作为解决方法。 - Marc B
5
可能是重复问题:批处理脚本:如何检查管理员权限 - npocmaka
1
你可以在这里找到一个自我提升的批处理文件。 - Amr Ali
可能是重复的问题:如何在批处理文件中请求管理员访问权限 - Jim Fell
1
@npocmaka,您链接的问题实际上是这个问题的重复 ;)(2013 vs. 2011) - Matthieu
15个回答

181

这个技巧只需要一个命令: 在命令提示符中键入net session

如果您不是管理员,则会收到"访问被拒绝"的消息。

System error 5 has occurred.

Access is denied.

如果你是管理员,你会收到一条不同的消息,其中最常见的是:

There are no entries in the list.

来自MS Technet

如果没有带参数使用,net session 会显示关于所有与本地计算机有关的会话信息。


这与Rushyo的答案功能上是相同的,他使用了AT命令。 - Jeff
19
在Windows 8.1中,与AT命令相比,net session 或 net.exe session 命令更受推荐,因为AT命令已经被弃用。使用Rushyo的回答,将AT替换为net session或net.exe session对我来说完美地起作用了。 - kayleeFrye_onDeck
2
这似乎是在命令提示符上执行此操作的最简单方法(尽管与批处理文件不同)。 - enderland
2
在Windows 10 Pro中,只需打印“列表中没有条目。” - gman
2
在批处理文件中使用类似以下的命令:net session >nul 2>&1 || (echo not admin&goto :eof) - anilech
1
使用%errorlevel%来检测脚本的执行权限,如果返回值为0,则表示以管理员权限执行,如果返回值为2,则表示以普通用户权限执行。 - ZEE

70

附录:在Windows 8上这个方法不起作用;请看这个优秀的答案


在这里找到了解决方案:http://www.robvanderwoude.com/clevertricks.php

AT > NUL
IF %ERRORLEVEL% EQU 0 (
    ECHO you are Administrator
) ELSE (
    ECHO you are NOT Administrator. Exiting...
    PING 127.0.0.1 > NUL 2>&1
    EXIT /B 1
)

如果那个方法不起作用,鉴于我们正在讨论的是Win7,您可以在适当情况下在Powershell中使用以下内容:

$principal = new-object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())
$principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)

如果不是(很可能不是,因为您明确提出了批处理文件),那么您可以在.NET中编写上述内容,并从exe返回退出代码,以基于批处理文件使用的结果。


4
AT命令完美无缺!你的Google搜索技巧比我高明。;-) - Jeff
2
+1 @Rushyo,我稍微扩展了一下你的解决方案,并发布在这里,因为那是我最初看到的。谢谢!https://dev59.com/Y2855IYBdhLWcg3w-JbS#8995407 - blak3r
17
“AT”在Windows 8上不起作用,但我已经找到了更好的解决方案。我已经在另一个问题的答案中发布了它,链接在这里:https://dev59.com/Y2855IYBdhLWcg3w-JbS。 - mythofechelon
4
我建议运行"whoami /groups | findstr /b BUILTIN\Admin | findstr /c:"Enabled group" && echo "I have a admin!",该命令适用于Windows 95,98,2000,XP,Vista和7、8!(摘自评论“I like Rushyo's sugesstion of using AT ...”) - barwnikk
2
命令行工具“AT”在Windows 10中已被弃用。请使用命令“net session”,参见下面的帖子。 - lison
显示剩余7条评论

33

其他人之前已经说得差不多了,但这里提供一个可以放在批处理命令开头的单行代码。(通常在@echo off之后)

net.exe session 1>NUL 2>NUL || (Echo This script requires elevated rights. & Exit /b 1)

4
这是最新版本,它能很好地隐藏net.exe的无关输出。 - andersand
2
在Windows 10上表现良好。 - James Pack
1
工作得非常好,只是将结尾微调为"Timeout /t 10 & Exit /b 1",以便在批处理文件中窗口不会立即消失。 - WhoIsRich

32

我喜欢Rushyo的建议,使用AT是一个不错的选择,但这里还有另一个选项:

whoami /groups | findstr /b BUILTIN\Administrators | findstr /c:"Enabled group" && goto :isadministrator

如果需要的话,这种方法还可以让您区分非管理员和非提升管理员。 非提升管理员仍在组列表中具有BUILTIN \ Administrators,但未启用。

但是,在某些非英语语言系统上,此方法将无法正常工作。请尝试

whoami /groups | findstr /c:" S-1-5-32-544 " | findstr /c:" Enabled group" && goto :isadministrator

(这在Windows 7上应该可以工作,但我不确定早期版本是否可以。)


1
在波兰版本中,我有:BUILTIN\Administratorzy,因此我建议使用:whoami /groups | findstr /b BUILTIN\Admin | findstr /c:"Enabled group" && goto :isadministrator。 - barwnikk
@HarryJohnston,哇,我没意识到。 "管理员" 标题是否出现在所有版本的 Windows 中? - Pacerier
@Pacerier:所有当前版本(从Vista开始)。 - Harry Johnston
whoami /groups 有一个边缘情况,可能会得到错误的信息。请参见 https://dev59.com/Y2855IYBdhLWcg3w-JbS#30921854。 - zumalifeguard
@zumalifeguard:当我测试它时,whoami /groups 给了我正确的信息:该组存在但已禁用。我的代码检查该组是否启用,因此在您的情况下不应给出错误答案。 - Harry Johnston
显示剩余4条评论

13

在Vista、Win 7及以上版本中最简单的方法是枚举令牌组并查找当前完整性级别(或管理员sid,如果只有组成员身份很重要):

检查我们是否正在以提升权限运行:

whoami /groups | find "S-1-16-12288" && Echo I am running elevated, so I must be an admin anyway ;-)

检查我们是否属于本地管理员组:

whoami /groups | find "S-1-5-32-544" && Echo I am a local admin

检查我们是否属于域管理员组:

whoami /groups | find "-512 " && Echo I am a domain admin

以下文章列出了Windows使用的完整性级别SIDs:http://msdn.microsoft.com/en-us/library/bb625963.aspx


whoami /groups 有一个边缘情况,可能会得到错误的信息。请参见 https://dev59.com/Y2855IYBdhLWcg3w-JbS#30921854。 - zumalifeguard

10
解决方案:
at >nul
if %ErrorLevel% equ 0 ( echo Administrator ) else ( echo NOT Administrator )

在Windows 10下无法正常工作。

对于所有版本的Windows,可以这样做:

openfiles >nul 2>&1
if %ErrorLevel% equ 0 ( echo Administrator ) else ( echo NOT Administrator )

8
这是哈利答案的小修改,主要关注提升状态; 我将其用于install.bat文件的开头:
set IS_ELEVATED=0
whoami /groups | findstr /b /c:"Mandatory Label\High Mandatory Level" | findstr /c:"Enabled group" > nul: && set IS_ELEVATED=1
if %IS_ELEVATED%==0 (
    echo You must run the command prompt as administrator to install.
    exit /b 1
)

这对我很有用,原理似乎是可靠的;来自MSFT的Chris Jackson:链接中提到,当你以管理员权限运行时,你的令牌包含一个名为Mandatory Label\High Mandatory Level的ACE。

whoami /groups 存在一种边缘情况,您可能会获得错误的信息。请参见 https://dev59.com/Y2855IYBdhLWcg3w-JbS#30921854。 - zumalifeguard

7

我阅读了许多(大多数?)回复,然后在Win 8.1上开发了一个对我有效的批处理文件。想和大家分享一下。

setlocal
set runState=user
whoami /groups | findstr /b /c:"Mandatory Label\High Mandatory Level" > nul && set runState=admin
whoami /groups | findstr /b /c:"Mandatory Label\System Mandatory Level" > nul && set runState=system
echo Running in state: "%runState%"
if not "%runState%"=="user" goto notUser
  echo Do user stuff...
  goto end
:notUser
if not "%runState%"=="admin" goto notAdmin
  echo Do admin stuff...
  goto end
:notAdmin
if not "%runState%"=="system" goto notSystem
  echo Do admin stuff...
  goto end
:notSystem
echo Do common stuff...
:end

希望有人会觉得这很有用 :)


whoami /groups有一个边缘案例,会导致您获取错误的信息。请参阅https://dev59.com/Y2855IYBdhLWcg3w-JbS#30921854。 - zumalifeguard
谢谢您!其他“whoami”解决方案在Windows 8.1上对我无效,而这个有效。 - Ryan

4

1

很遗憾,其他人建议的"S-1-5-32-544"并不能证明提升权限。

在Windows 10及更高版本中,一种独立于语言的方法是:

whoami /groups | find "S-1-16-12288"

这是“高强制级别”,实际上已经升级。

普通命令提示符:

C:\> whoami /groups | find "S-1-16-12288"
C:\>

管理员命令提示符:

C:\> whoami /groups | find "S-1-16-12288"
Mandatory Label\High Mandatory Level                          Label            S-1-16-12288                                                                                                                                                     


C:\>

在 .bat 文件中使用:

whoami /groups | find "S-1-16-12288" && set ELEVATED=true || set ELEVATED=false

您也可以从PowerShell使用此功能:

function is_elevated() {
  Param( [String] $ToGroup = "S-1-16-12288" )
  return [bool] ( whoami /groups | select-string $ToGroup )
}

例如:

举个例子:

PS> cd c:/temp
PS> set-content is-elevated.ps1 "return [bool] ( whoami /groups | sls S-1-16-12288 )"
PS> ./is-elevated.ps1
False
PS> start -verb runas powershell.exe
...
PS C:\Windows\system32> cd \temp
PS C:\temp> ./is-elevated.ps1
True

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