在Windows上以管理员身份运行Java应用程序

5

我正在使用Java编写一个安装程序,需要获取提升的权限才能访问“Program Files”目录。基于我在网上找到的信息,我编写了以下实现:

public static void main(String args[]) {
    if (!checkPrivileges()) { // spawn a copy w/ elevated privileges
        Runtime runtime = Runtime.getRuntime();
        try {
            Process p = runtime.exec(
                "runas /profile /user:Administrator \"java -cp . main.Main\"");
        } catch (IOException e) { ... }
    } else {
        // Run with elevated privileges
    }
}

我用来检查权限的测试略有改动,源自这里,代码如下:

private static boolean checkPrivileges() {
    File testPriv = new File("C:\\Program Files\\");
    if (!testPriv.canWrite()) return false;
    File fileTest = null;
    try {
        fileTest = File.createTempFile("test", ".dll", testPriv);
    } catch (IOException e) {
        return false;
    } finally {
        if (fileTest != null)
            fileTest.delete();
    }
    return true;
}

当我运行这个程序时,它未通过权限测试,这是预料中的结果,并且执行了调用。查看 p.isAlive() 的返回值表明该进程确实仍在运行;但是,我没有看到任何新进程的证据,Windows 也没有提示我授予权限。
我不熟悉在 Java 中使用 exec(),所以很可能我对其使用方式有误解。此外,我在尝试做什么方面可能是不可行的?如果不行,是否有一种简单直接的替代方法可以让我获得所需的结果?

1
在Windows 8(可能也适用于其他版本),使用“runas”实际上不会弹出UAC弹窗,而是通过标准输入提示输入密码。尝试在命令提示符窗口中运行“runas /profile /user:Administrator notepad”,这可能可以解释您的问题。 - Pokechu22
1
这似乎确实是在这里的情况。我想这只会引出一个后续问题:我如何在Java中弹出UAC弹窗?或者,我的目标平台是Windows 7(尽管我正在Windows 8平台上开发)。这段代码在那个平台上会做我想要的事情吗? - bionicOnion
1
一个解决方案是编写一个简单的C应用程序来重新启动你的Java程序。你可以给这个应用程序一个应用程序清单,告诉Windows需要提升权限。然而,可能有一种直接在Java中实现的方法,这是一个有趣的问题。+1。 - Harry Johnston
2个回答

1

好的,我终于设法找到了一个解决这个问题的方案,我很满意;虽然有点丑陋,但对我当前的工作来说是可行的。

我借鉴了this答案中的代码来进行实际特权提升;从那里开始,问题就是如何将该解决方案与Java一起使用。最终得到的代码如下:

    if (!checkPrivileges()) {
        try {
            String jarPath = DownloaderMain.class.getProtectionDomain().getCodeSource().getLocation().getPath();
            String decodedPath = URLDecoder.decode(jarPath, "UTF-8");
            decodedPath = decodedPath.substring(1, decodedPath.length());
            Elevator.executeAsAdministrator(System.getProperty("java.home") + "\\bin\\java", "-jar " + "\"" + decodedPath + "\"");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    } else {
        // Run with elevated privileges
    }

checkPrivileges方法与上述内容相同,Elevator类与链接的解决方案中的类基本相同(只是删除了不需要的main方法)。此解决方案假定要提升的进程是一个jar包;更改以适应个人需求不应该太困难。


0

我认为实现这个目的的最佳方法是使用微软为开发人员构建的工具,因为你无法在简单的Java中完成。在这种情况下,请使用清单文件http://msdn.microsoft.com/en-us/library/aa375632(v=vs.85).aspx 。只需构建一个包装器.exe文件,要求此权限,然后启动您的java程序。


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