简体   繁体   English

Windows上的Java:测试Java应用程序是否作为提升的进程运行(具有管理员权限)

[英]Java on Windows: Test if a Java application is run as an elevated process (with Administrator privileges)

Situation 情况

I have an (Eclipse RCP-based) Java application running on multiple platforms. 我有一个在多个平台上运行的(基于Eclipse RCP的)Java应用程序。 I got this figured out on all platforms except Windows. 我在Windows以外的所有平台上都发现了这个问题。

Installer : My application installer is always run in elevated mode, so it can install the application to C:\\Program files\\MyProduct . 安装程序 :我的应用程序安装程序始终以提升模式运行,因此可以将应用程序安装到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. 从用户的角度来看,这意味着安装程序只能由管理员执行,并且UAC会要求您进行确认。 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 . 自动更新自动更新功能还会写入C:\\Program Files\\MyProduct ,因此也需要管理员权限 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 (ie to see if it was ' Run as administrator '. 我希望运行时检查以查看我的Java进程是否处于提升模式 (即查看它是否以“ 以管理员身份运行 ”)。

Note it may be a Windows-only solution. 请注意,这可能是仅Windows的解决方案。 Using the Java reflection API, I can check for the Windows- and/or implementation-specific classes at runtime. 使用Java反射API,我可以在运行时检查Windows和/或实现特定的类。

Research 研究

I only found this question on StackOverflow: Detect if Java application was run as a Windows admin 我仅在StackOverflow上发现此问题: 检测Java应用程序是否以Windows管理员身份运行

However, that solution returns whether the active user is a member of the Administrator group. 但是,该解决方案将返回活动用户是否是Administrator组的成员。 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. 我知道当Eclipse RCP应用程序没有管理员权限时,它将自动在用户目录中安装更新,但是我想阻止这种情况。

I want to allow user-specific configuration (which works fine), but allowing user-specific updates would leave too much mess after uninstallation. 我想允许用户特定的配置(效果很好),但是允许用户特定的更新在卸载后会造成太多混乱。

This is what the Eclipse LocationManager does to determine if it can write to the install directory: 这是Eclipse LocationManager确定它是否可以写入安装目录的操作:

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 注意创建dll的尝试

Using JNA and the Win32 IsUserAnAdmin function : 使用JNAWin32 IsUserAnAdmin函数

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. 根据MS文档,IsUserAnAdmin()在Windows的未来版本中可能不存在。 So an even better method would be to use JNA to call the CheckTokenMembership function . 因此,更好的方法是使用JNA调用CheckTokenMembership函数 However, doing that is more complex, so the above code is what I am using today. 但是,这样做比较复杂,因此上面的代码就是我今天使用的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM