5

As the title says, I'm wondering if it is possible for a program written in Java (and only java) to relaunch himself (preferably a .jar) with administrator privileges, showing in the way the native Windows UAC (in order to make it more trustable for the user), i did my homework and found out that it is possible to accomplish this using bridges between c++ and java, but i would really like to do this as a pure java project.

P.S: In the remote case that this result to be impossible, can someone show me the "easy" way to do this using another language (i mean, I've found tutorials, but they are to complicated for something I think it should not be that complicated).

P.S2: In case it is possible to accomplish this, would it work, on other platforms (OS X, Linux)

Ordiel
  • 2,442
  • 3
  • 36
  • 52
  • Do you want to restart it with admin privileges or start it in the first place with elevated rights? If the second, then you can use the manifest to force elevated rights (which will automatically bring up the UAC). – brimborium Nov 08 '12 at 13:46
  • Just relaunch the program with elevated privileges, can you show me the way (link, tutorial (if it is explained for dummies it would be wonderful)) to do it with the manifest please. (In deed I'm planing to build a Java installer generator, that is why i want to make it just using java, because i would like to add this capability to my installers, for example an option like "ask for administrator privileges for jar..." ) – Ordiel Nov 08 '12 at 13:59
  • 1
    My chain looks like this: 1. Code in eclipse, 2. Export as Runnable Jar, 3. wrap up to an *.exe with [Launch4J](http://launch4j.sourceforge.net/), 4. wrap the executable + all the needed directories into an installer with [InnoSetup](http://www.jrsoftware.org/isinfo.php). You can now set the manifest file within launch4J. For some help on that, read the [second post here](http://www.mathworks.com/matlabcentral/newsreader/view_thread/313257). It explains everything and also has links to more tutorials and valid manifest examples. – brimborium Nov 08 '12 at 14:07
  • 1
    There is a solution using JNA found [here][1]. [1]: http://stackoverflow.com/questions/11041509/elevating-a-processbuilder-process-via-uac – dARKpRINCE May 08 '14 at 07:16

5 Answers5

9

It cannot be done in pure java.

Best bet would be to write this to a file:

@echo Set objShell = CreateObject("Shell.Application") > %temp%\sudo.tmp.vbs
@echo args = Right("%*", (Len("%*") - Len("%1"))) >> %temp%\sudo.tmp.vbs
@echo objShell.ShellExecute "%1", args, "", "runas" >> %temp%\sudo.tmp.vbs
@cscript %temp%\sudo.tmp.vbs

and save it as something.bat in Windows temp directory (as we have access to this).

You would then execute this from your application using Runtime or ProcessBuilder and exit your application (System.exit(0);).

You should add an immediate start up check to your application that checks if the program has elevation, if it has proceed if not re-run the batch and exit.

Here is an example I made (this must be run when compiled as a Jar or it wont work):

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.JOptionPane;

/**
 *
 * @author David
 */
public class UacTest {

    public static String jarName = "UacTest.jar", batName = "elevate.bat";

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        if (checkForUac()) {//uac is on
            JOptionPane.showMessageDialog(null, "I am not elevated");
            //attempt elevation
            new UacTest().elevate();
            System.exit(0);
        } else {//uac is not on
            //if we get here we are elevated
            JOptionPane.showMessageDialog(null, "I am elevated");
        }

    }

    private static boolean checkForUac() {
        File dummyFile = new File("c:/aaa.txt");
        dummyFile.deleteOnExit();

        try {
            //attempt to craete file in c:/
            try (FileWriter fw = new FileWriter(dummyFile, true)) {
            }
        } catch (IOException ex) {//we cannot UAC muts be on
            //ex.printStackTrace();
            return true;
        }
        return false;
    }

    private void elevate() {
        //create batch file in temporary directory as we have access to it regardless of UAC on or off
        File file = new File(System.getProperty("java.io.tmpdir") + "/" + batName);
        file.deleteOnExit();

        createBatchFile(file);

        runBatchFile();

    }

    private String getJarLocation() {
        return getClass().getProtectionDomain().getCodeSource().getLocation().getPath().substring(1);
    }

    private void runBatchFile() {
        //JOptionPane.showMessageDialog(null, getJarLocation());

        Runtime runtime = Runtime.getRuntime();
        String[] cmd = new String[]{"cmd.exe", "/C",
            System.getProperty("java.io.tmpdir") + "/" + batName + " java -jar " + getJarLocation()};
        try {
            Process proc = runtime.exec(cmd);
            //proc.waitFor();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void createBatchFile(File file) {
        try {
            try (FileWriter fw = new FileWriter(file, true)) {
                fw.write(
                        "@echo Set objShell = CreateObject(\"Shell.Application\") > %temp%\\sudo.tmp.vbs\r\n"
                        + "@echo args = Right(\"%*\", (Len(\"%*\") - Len(\"%1\"))) >> %temp%\\sudo.tmp.vbs\r\n"
                        + "@echo objShell.ShellExecute \"%1\", args, \"\", \"runas\" >> %temp%\\sudo.tmp.vbs\r\n"
                        + "@cscript %temp%\\sudo.tmp.vbs\r\n"
                        + "del /f %temp%\\sudo.tmp.vbs\r\n");
            }
        } catch (IOException ex) {
            //ex.printStackTrace();
        }
    }
}
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
  • Thanks, I like your answer, but 2 things (I've never used bat files before, I think today is a good day to start) but I can't see in the example you gave anything related to the name (URI) of my program, I mean how the .bat will know which program should it launch?, the second one, how can java check its level of elevation? (maybe the second one should be another question, I'm going to do a research, but some (more) help would be appreciated) – Ordiel Nov 08 '12 at 14:12
  • mmm, I search about that batch file, and it receives as a parameter the program you want to run (well at least http://social.technet.microsoft.com/Forums/en-US/w7itproappcompat/thread/05cce5f6-3c3a-4bb8-8b72-8c1ce4b5eff1 this article says that, and it is really logic, you "trim" the args to execute the first arg under the parameters of the rest of the args (I would have do the same under a UNI/LINU X system with a bash script)), the real problem is that even when I send my jar as a parameter it does not run (neither crash), just open the console and that's all any suggestion... – Ordiel Nov 08 '12 at 17:16
  • 1
    For future readers: if you don't want ugly cmd window popping up: modify like staring with `@echo objShell.ShellExecute` and add `0` parameter after `runas`, just like this: `"@echo objShell.ShellExecute \"%1\", args, \"\", \"runas\", 0 >> %temp%\\sudo.tmp.vbs\r\n"` – Trynkiewicz Mariusz Apr 10 '21 at 21:33
1

Use a batch file and the runas command.

nfechner
  • 17,295
  • 7
  • 45
  • 64
0

I doubt "only Java". At best you would have to have a JNI wrapper around the MSFT module. Unless just invoking the exe using ProcessBuilder counts as "only Java" -- your code to bring up the user console would be only Java but not what it invokes. IOW, Win does not come with a Java API

amphibient
  • 29,770
  • 54
  • 146
  • 240
0

To relaunch your application elevated, you have to call ShellExecute or ShellExecuteEx function from Windows API and use runas verb.

You can use these API in pure Java with JNA library.

To relaunch yourself, you would have to know the full path to java.exe or javaw.exe, the command-line parameters (class path, if any, and the path to your jar). Obviously you can get this information by using Windows API.


What do you mean by remote case?
You cannot start remote elevated process this way.

You can re-launch your application elevated from a network share. Yet it won't work with mapped drives: after elevation there's no access to user's mapped drives.


No, this can't work on other platforms. UAC is a Windows feature. It's similar to sudo in Linux in some ways, so for Linux you can use sudo $pathtojava/java.exe <yourparameters>. However this won't work nicely if your application is not started from a console. Window Managers usually have wrappers which prompt for password in a GUI dialog.

Alexey Ivanov
  • 11,541
  • 4
  • 39
  • 68
0

Just do this with Hackaprofaw (v29). Also it was released in 2002 and started development in 1997 soooooo ye. in 2021 its on version 29.10.7 but-

if raw ram = 0
 disable "featureII" program = "JAVA(math = any)"
run on "Hackaprofaw (math = v29(x))
when "featureII" disabled
 end