检测 Java 应用程序是不是以 Windows 管理员身份运行
Posted
技术标签:
【中文标题】检测 Java 应用程序是不是以 Windows 管理员身份运行【英文标题】:Detect if Java application was run as a Windows admin检测 Java 应用程序是否以 Windows 管理员身份运行 【发布时间】:2011-05-20 00:27:03 【问题描述】:我有一个 Java 应用程序。无论如何我可以判断该进程是否在 Windows 7 上以管理员权限运行。
【问题讨论】:
我在 Linux 中测试了我的答案。它可能不依赖于操作系统,但我不知道。 【参考方案1】:Java 运行时环境中没有这样的工具,但可能在依赖于平台的本机例程中。请注意,通常最好的确定方法是实际尝试去做,看看它是否失败。
【讨论】:
【参考方案2】:仅通过尝试需要此类访问的操作(如绑定低编号端口,或打开已知受保护的文件)。
【讨论】:
谢谢。这对我有用。我试图在程序文件中创建一个测试文件并捕获 IOException (Access is Denied)... new File(System.getenv("programfiles")+"/test.tst").createNewFile()【参考方案3】:或者你可以这样做:
System.getenv().get("USER")
并查看哪个用户启动了该过程。
当我以我的身份运行它时,我得到“goran”,当我使用 sudo 运行它时,我得到“root”。在 Linux 上工作。 可能需要什么。
【讨论】:
嗯,这很有趣,让我试试这个,看看它在 Windows 上的作用。如果它说“管理员”,这将起作用。 请发布您的结果。我真的很想知道这是否与操作系统无关 在 Windows 7 上,如果我运行此代码,我会得到一个空值。但是,如果我运行 System.getProperty("user.name"),我会得到我的用户名。但是,这仍然不能说明我是否是管理员。 有趣。尝试获取所有属性:System.out.println(System.getenv());
也许,还有别的东西。
也可以试试:System.out.println(System.getProperties());
【参考方案4】:
我在网上找到了这个代码 sn-p,我认为它会为你完成这项工作。
public static boolean isAdmin()
String groups[] = (new com.sun.security.auth.module.NTSystem()).getGroupIDs();
for (String group : groups)
if (group.equals("S-1-5-32-544"))
return true;
return false;
它仅适用于 Windows,并内置于核心 Java 包中。我刚刚测试了这段代码,它确实有效。这让我感到惊讶,但确实如此。
SID S-1-5-32-544 是 Windows 操作系统中管理员组的 ID。
Here is the link 了解其工作原理的更多详细信息。
【讨论】:
不错的 S-1-5-32-544。我早该想到的。 ... 由于私有类,仅适用于 Sun JVM。 请注意,此 sn-p 测试活动用户是否为管理员,而不是用户是否已将应用程序作为提升的进程启动! 如果应用程序以管理员帐户的正常权限运行,这将不起作用。仍然返回 true... 此代码可能仅适用于 Oracle JRE,不保证适用于 JRE 的任何更新:oracle.com/technetwork/java/faq-sun-packages-142232.html【参考方案5】:答案中标记为最佳的方法对我来说效果很好,直到我不得不在 Linux 机器上在 Jenkins 中构建代码。 com.sun.security.auth.module.NTSystem() 在那里不可用,使用 sun 包通常被认为是一种不好的做法: link
【讨论】:
从您的 Windows 机器中获取“rt.jar”。将它添加到 Linux 机器上的类路径中。然后在你的应用程序中有代码,可以查看它是否是 Windows PC,执行接受的答案,如果是 Linux,运行这个问题的 Linux 答案。想到的第一个解决方案。对我来说,我只需要在 Windows 上这样做,所以我没有这个问题。它是 Java 做的很糟糕的事情之一。只是一个旁注,您应该将其添加为评论。 感谢有关 rt.jar 的提示!我会试一试。 PS:我知道,这应该是一个评论,但不幸的是,由于***授予权限的方式有点奇怪,以我目前的声誉,我只能评论我自己的答案/问题=)【参考方案6】:我找到了一个似乎与平台无关的不同解决方案。它尝试编写系统首选项。如果失败,用户可能不是管理员。
正如Tomáš Zato 建议的那样,您可能希望抑制由此方法引起的错误消息。你可以通过设置System.err
来做到这一点:
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.prefs.Preferences;
import static java.lang.System.setErr;
import static java.util.prefs.Preferences.systemRoot;
public class AdministratorChecker
public static final boolean IS_RUNNING_AS_ADMINISTRATOR;
static
IS_RUNNING_AS_ADMINISTRATOR = isRunningAsAdministrator();
private static boolean isRunningAsAdministrator()
Preferences preferences = systemRoot();
synchronized (System.err)
setErr(new PrintStream(new OutputStream()
@Override
public void write(int b)
));
try
preferences.put("foo", "bar"); // SecurityException on Windows
preferences.remove("foo");
preferences.flush(); // BackingStoreException on Linux
return true;
catch (Exception exception)
return false;
finally
setErr(System.err);
【讨论】:
很好,但我建议您将状态缓存到私有静态变量中。它不会在程序的一个实例中改变。 还有一件事——函数不断产生输出,例如Kvě 07, 2015 1:49:14 ODP. java.util.prefs.WindowsPreferences <init> WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5.
是否可以抑制这些?
@TomášZato 我改进了我的答案
请注意,由于System.setErr(null)
,答案中的第二个代码块会抛出NullPointerException
。要解决此问题,请改用虚拟输出流:System.setErr(new PrintStream(new OutputStream() @Override public void write(int i) throws IOException ));
如果其他线程也没有同步到System.err
,则synchronized(systemErr)
行无效。【参考方案7】:
这是一个在 Windows 10 上的解决方案,我猜它在其他 Windows 操作系统上也能正常运行。
public static boolean isAdmin()
try
ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe");
Process process = processBuilder.start();
PrintStream printStream = new PrintStream(process.getOutputStream(), true);
Scanner scanner = new Scanner(process.getInputStream());
printStream.println("@echo off");
printStream.println(">nul 2>&1 \"%SYSTEMROOT%\\system32\\cacls.exe\" \"%SYSTEMROOT%\\system32\\config\\system\"");
printStream.println("echo %errorlevel%");
boolean printedErrorlevel = false;
while (true)
String nextLine = scanner.nextLine();
if (printedErrorlevel)
int errorlevel = Integer.parseInt(nextLine);
return errorlevel == 0;
else if (nextLine.equals("echo %errorlevel%"))
printedErrorlevel = true;
catch (IOException e)
return false;
【讨论】:
【参考方案8】:以下代码适合我
命令提示符命令
net user
Java 代码
public static boolean isAdmin()
StringBuilder outputbuilder = new StringBuilder();
try
ProcessBuilder builder = new ProcessBuilder(
"cmd.exe","/c" ,"net user");
builder.redirectErrorStream(true);
Process p = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while (true)
line = r.readLine();
if (line == null) break;
outputbuilder.append(line);
catch (IOException e)
e.printStackTrace();
return false;
System.out.println(outputbuilder.toString());
return outputbuilder.toString().contains("Administrator");
【讨论】:
以上是关于检测 Java 应用程序是不是以 Windows 管理员身份运行的主要内容,如果未能解决你的问题,请参考以下文章
C/C++/Assembly 以编程方式检测超线程在 Windows、Mac 和 Linux 上是不是处于活动状态 [重复]
如何检测 x64 Windows 上是不是安装了 32 位 Java,仅查看文件系统和注册表?
Windows 和 Mac 在密钥检测方面的 Java 差异