【发布时间】:2011-05-20 00:27:03
【问题描述】:
我有一个 Java 应用程序。无论如何我可以判断该进程是否在 Windows 7 上以管理员权限运行。
【问题讨论】:
-
我在 Linux 中测试了我的答案。它可能不依赖于操作系统,但我不知道。
标签: java windows admin privileges
我有一个 Java 应用程序。无论如何我可以判断该进程是否在 Windows 7 上以管理员权限运行。
【问题讨论】:
标签: java windows admin privileges
Java 运行时环境中没有这样的工具,但可能在依赖于平台的本机例程中。请注意,通常最好的确定方法是实际尝试去做,看看它是否失败。
【讨论】:
仅通过尝试需要此类访问的操作(如绑定低编号端口,或打开已知受保护的文件)。
【讨论】:
或者你可以这样做:
System.getenv().get("USER")
并查看哪个用户启动了该过程。
当我以我的身份运行它时,我得到“goran”,当我使用 sudo 运行它时,我得到“root”。在 Linux 上工作。 可能需要什么。
【讨论】:
System.out.println(System.getenv()); 也许,还有别的东西。
System.out.println(System.getProperties());
我在网上找到了这个代码 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 了解其工作原理的更多详细信息。
【讨论】:
答案中标记为最佳的方法对我来说效果很好,直到我不得不在 Linux 机器上在 Jenkins 中构建代码。 com.sun.security.auth.module.NTSystem() 在那里不可用,使用 sun 包通常被认为是一种不好的做法: link
【讨论】:
我找到了一个似乎与平台无关的不同解决方案。它尝试编写系统首选项。如果失败,用户可能不是管理员。
正如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. 是否可以抑制这些?
System.setErr(null),答案中的第二个代码块会抛出NullPointerException。要解决此问题,请改用虚拟输出流:System.setErr(new PrintStream(new OutputStream() { @Override public void write(int i) throws IOException { } }));
System.err,则synchronized(systemErr) 行无效。
这是一个在 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;
}
}
【讨论】:
以下代码适合我
命令提示符命令
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");
}
【讨论】: