5

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?

Community
  • 1
  • 1
bionicOnion
  • 1,494
  • 3
  • 16
  • 25
  • 1
    In windows 8 (probably others as well), using `runas` doesn't actually bring up a UAC popup, but instead it prompts for the password to be entered through stdin. Try running `runas /profile /user:Administrator notepad` in a command prompt window; that may explain your issue. – Pokechu22 Oct 30 '14 at 22:11
  • 1
    That does indeed seem to be the case here. I suppose that this just leads to a follow up question: how can I bring up a UAC popup in Java? Alternatively, my target platform is Windows 7 (even though I'm developing on a Windows 8 platform). Will this code do what I'm intending on that platform? – bionicOnion Oct 30 '14 at 22:26
  • 1
    One solution would be to write a simple application in C to relaunch your Java program for you. You can give the application an application manifest to tell Windows that elevation is required. However, there may well be a way to do it directly in Java, and it's an interesting question. +1. – Harry Johnston Oct 30 '14 at 22:34

2 Answers2

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.

Community
  • 1
  • 1
bionicOnion
  • 1,494
  • 3
  • 16
  • 25
0

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.

specializt
  • 1,913
  • 15
  • 26
Maksim
  • 215
  • 2
  • 12