检测Java应用程序是否作为Windows管理员运行
我有一个Java应用程序。无论如何,我可以判断进程是否在Windows 7上以管理员权限运行。Java运行时环境中没有这样的功能,但可能在依赖于平台的本机例程中。请注意,通常最好的确定方法是实际尝试,并查看是否失败。仅通过尝试需要此类访问的操作(如绑定低编号端口或打开已知受保护的文件)。或者您可以执行以下操作:检测Java应用程序是否作为Windows管理员运行,java,windows,admin,privileges,Java,Windows,Admin,Privileges,我有一个Java应用程序。无论如何,我可以判断进程是否在Windows 7上以管理员权限运行。Java运行时环境中没有这样的功能,但可能在依赖于平台的本机例程中。请注意,通常最好的确定方法是实际尝试,并查看是否失败。仅通过尝试需要此类访问的操作(如绑定低编号端口或打开已知受保护的文件)。或者您可以执行以下操作: System.getenv().get(“用户”) 并查看是哪个用户启动了该过程 当我以我的身份运行它时,我得到了“goran”,当我与sudo一起运行它时,我得到了“root”。在Li
System.getenv().get(“用户”)
并查看是哪个用户启动了该过程
当我以我的身份运行它时,我得到了“goran”,当我与sudo一起运行它时,我得到了“root”。在Linux上工作。
可能是需要的。我在网上找到了这段代码片段,我想它可以帮你完成这项工作
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
关于它是如何工作的更多细节。在我不得不在Linux机器上用Jenkins构建代码之前,答案中标记为best的方法对我来说非常有效。com.sun.security.auth.module.NTSystem()在那里不可用,使用sun软件包通常被认为是一种不好的做法:
我发现了一种与平台无关的解决方案。它尝试编写系统首选项。如果失败,用户可能不是管理员 正如所建议的,您可能希望抑制由此方法引起的错误消息。您可以通过设置
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);
}
}
}
}
这里有一个在Windows10上的解决方案,我想它也可以在其他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");
}
我在Linux中测试了我的答案。它可能不依赖操作系统,但我说不出来。嗯,这很有趣,让我试试这个,看看它在windows上做了什么。如果上面写着“管理员”,这就行了。请把结果贴出来。我真的很想知道这是否是Windows7上的独立操作系统,如果我运行这段代码,我会得到一个空值。但是,如果我运行System.getProperty(“user.name”),我会得到我的用户名。但是,这仍然不能说明我是否是管理员。尝试获取所有属性:
System.out.println(System.getenv())代码>可能还有其他原因。请尝试:System.out.println(System.getProperties())代码>好ol'S-1-5-32-544。我应该想到的。。。。由于私有类的原因,仅适用于Sun JVM。请注意,此代码段测试活动用户是否是管理员,而不是用户是否已将应用程序作为提升进程启动!如果应用程序在管理员帐户上以正常权限运行,则此操作不起作用。仍然返回true…此代码可能仅适用于Oracle JRE,并且不保证适用于JRE的任何更新:从windows计算机获取“rt.jar”。将其添加到Linux机器上的类路径。然后在你的应用程序中有代码,可以查看它是否是windows PC,执行接受的答案,如果是Linux,则运行此问题的Linux答案。想到的第一个解决方案。对我来说,我只需要在Windows上做这个,所以我没有这个问题。这是Java做得有点差劲的事情之一。只是一个旁注,你应该把它作为一个注释添加进来。谢谢你关于rt.jar的提示!我要试一试。PS:我知道,这应该是一个评论,但不幸的是,由于stackoverflow授予权限的方式有些奇怪,以我目前的声誉,我只能对我自己的答案/问题发表评论=)谢谢。这对我很管用。我试图在程序文件中创建一个测试文件,并捕获IOException(访问被拒绝)。。。新文件(System.getenv(“programfiles”)+“/test.tst”).createNewFile()很好,但我建议您将状态缓存到私有静态变量中。它不会在程序的一个实例内改变。还有一件事-该函数不断产生输出,例如Kvě072015149:14odp。java.util.prefs.WindowsPreferences警告:无法在根0x8000002处打开/创建prefs根节点Software\JavaSoft\prefs。Windows RegCreateKeyEx(…)返回了错误代码5。
有可能超出这些吗?@TomášZato我改进了我的答案注意,答案中的第二个代码块抛出了一个NullPointerException
,原因是System.setErr(null)
。要解决这个问题,请改用一个伪输出流:System.setErr(newprintstream(newoutputstream(){@Override public void write(inti)抛出IOException{}}))
如果其他线程也不同步到System.err,则行synchronized(systemErr)
无效。