Java on Windows: Test if a Java application is run as an elevated process (with Administrator privileges)
Asked Answered
B

2

6

Situation

I have an (Eclipse RCP-based) Java application running on multiple platforms. I got this figured out on all platforms except Windows.

Installer: My application installer is always run in elevated mode, so it can install the application to C:\Program files\MyProduct. From a user perspective, this means the installer can only be executed by an Administrator and the UAC will ask for confirmation. This works fine.

Normal usage: The application can be launched by normal users. No administrator privileges should be required. This works fine.

Auto-update: The auto-update functionality also writes to C:\Program Files\MyProduct and therefore also requires administrator privileges. That's why the application, while it can be launched as a normal application too, MUST be run as an elevated process to auto-update. From a user perspective, it should be 'Run as administrator' to auto-update.

Question

I would like a runtime check to see if my Java process is in elevated mode (i.e. to see if it was 'Run as administrator'.

Note it may be a Windows-only solution. Using the Java reflection API, I can check for the Windows- and/or implementation-specific classes at runtime.

Research

I only found this question on StackOverflow: Detect if Java application was run as a Windows admin

However, that solution returns whether the active user is a member of the Administrator group. The user may still have my application launched in non-elevated mode. I have verified this.

Note

I know that an Eclipse RCP application will automatically install updates in the user directory, when he or she has no administrator privileges, but I want to block that case.

I want to allow user-specific configuration (which works fine), but allowing user-specific updates would leave too much mess after uninstallation.

Blowbyblow answered 5/9, 2013 at 8:39 Comment(2)
Would it be enough just to check if you have write access to the install directory? This what the Eclipse location manager does when deciding where to put things.Trichromatism
That's how I solve this on Unix-based systems. Write a file, delete the file, if IOException return false, else return true. However, this test seems to pass on Windows when an administrator runs the application in non-elevated mode! I tested this manually: I can create a new project with my application and save it in the installation directory. Note a different (e.g. Word) file cannot be saved there. However, the Eclipse RCP update still moves to a private user directory! I guess because it has to modify and remove files as well.Blowbyblow
S
6

Using JNA and the Win32 IsUserAnAdmin function:

import com.sun.jna.LastErrorException;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.win32.StdCallLibrary;

public class WindowsAdminUtil {

   public interface Shell32 extends StdCallLibrary {

      boolean IsUserAnAdmin() throws LastErrorException;
   }
   public static final Shell32 INSTANCE =
           Platform.isWindows() ?
           (Shell32) Native.loadLibrary("shell32", Shell32.class) : null;

   public static boolean isUserWindowsAdmin() {
      return INSTANCE != null && INSTANCE.IsUserAnAdmin();
   }
}

According to the MS docs, IsUserAnAdmin() might not exist in future versions of Windows. So an even better method would be to use JNA to call the CheckTokenMembership function. However, doing that is more complex, so the above code is what I am using today.

Syringa answered 16/10, 2013 at 6:4 Comment(0)
T
3

This is what the Eclipse LocationManager does to determine if it can write to the install directory:

public static boolean canWrite(File installDir) {
    if (installDir.canWrite() == false)
        return false;

    if (!installDir.isDirectory())
        return false;

    File fileTest = null;
    try {
        // we use the .dll suffix to properly test on Vista virtual directories
        // on Vista you are not allowed to write executable files on virtual directories like "Program Files"
        fileTest = File.createTempFile("writtableArea", ".dll", installDir);
    } catch (IOException e) {
        //If an exception occured while trying to create the file, it means that it is not writable
        return false;
    } finally {
        if (fileTest != null)
            fileTest.delete();
    }
    return true;
}

Note the attempt to create a dll

Trichromatism answered 5/9, 2013 at 10:15 Comment(2)
Thanks for the information! I got it working with a similar approach. I now try rename a file (e.g. configuration/config.ini), which gives the same results as yours. However, I am still curious on how to get the elevated Windows status from Java, so I'll leave the question open for now. :)Blowbyblow
I was wondering why I got a DLL file with a spelling mistake in my eclipse directory. The word is "writable" and I'm on Linux so why are you writing this anyway?!Decurion

© 2022 - 2024 — McMap. All rights reserved.