Run Java application as administrator on Windows

2020-03-03 06:55发布

问题:

I am writing an installer in Java that will accordingly require elevated privileges to access the Program Files directory. Based on information that I've found online, I've written an implementation as follows:

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
    }
}

The test that I'm using to check for privileges is modified slightly from an answer found here and looks like this:

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;
}

When I run this, it fails the privileges test--as expected--and makes the call to exec. Checking if the call worked by looking at p.isAlive() shows that the process is, in fact, alive; however, I'm not seeing any evidence of the new process and Windows isn't prompting me to grant permissions.

I'm not familiar with using exec() in Java, so it's quite possible that I've misunderstood its usage somehow. For that matter, is what I'm attempting to do here even possible? If not, is there a straightforward alternative that will actually get me the results that I'm looking for?

回答1:

Okay, I've finally managed to get a solution for this problem that I'm happy with; it's a bit on the ugly side, but it works for what I'm doing.

I borrowed the code from this answer to do the actual privilege elevation; from there, the question was one of actually getting that solution to work with Java. The code for that ends up looking like this:

    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
    }

The checkPrivileges method is unchanged from above and the Elevator class is virtually identical to the one that appears in the linked solution (I just took out the unneeded main method). This solution assumes that the process to be elevated is a jar; it shouldn't be too difficult to change this around to suit your individual needs.



回答2:

I think that the best approach to achieve this is to use the tools that microsoft built for developers since you can't do it in simple Java. In this case use a manifest file http://msdn.microsoft.com/en-us/library/aa375632(v=vs.85).aspx Just build the wrapper .exe that asks for this privileges and then spawns your java program.