5

情况

我有一个在多个平台上运行的(基于 Eclipse RCP 的)Java 应用程序。我在除 Windows 之外的所有平台上都解决了这个问题。

安装程序:我的应用程序安装程序始终在提升模式下运行,因此它可以将应用程序安装到C:\Program files\MyProduct. 从用户的角度来看,这意味着安装程序只能由管理员执行,并且 UAC 将要求确认。这工作正常。

正常使用普通用户可以启动该应用程序。不需要管理员权限。这工作正常。

自动更新自动更新功能也写入C:\Program Files\MyProduct,因此也需要管理员权限。这就是为什么应用程序虽然也可以作为普通应用程序启动,但必须作为提升的进程运行才能自动更新。从用户的角度来看,自动更新应该是“以管理员身份运行”。

问题

我想要运行时检查以查看我的Java 进程是否处于提升模式(即查看它是否为“以管理员身份运行”。

请注意,它可能是仅限 Windows 的解决方案。使用 Java 反射 API,我可以在运行时检查特定于 Windows 和/或实现的类。

研究

我只在 StackOverflow 上发现了这个问题: Detect if Java application was run as a Windows admin

但是,该解决方案会返回活动用户是否是管理员组的成员。用户可能仍然让我的应用程序以非提升模式启动。我已经验证了这一点。

笔记

我知道当他或她没有管理员权限时,Eclipse RCP 应用程序会自动在用户目录中安装更新,但我想阻止这种情况。

我想允许用户特定的配置(工作正常),但允许用户特定的更新会在卸载后留下太多的混乱。

4

2 回答 2

3

使用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();
   }
}

根据 MS 文档,未来版本的 Windows 中可能不存在 IsUserAnAdmin()。所以更好的方法是使用 JNA 调用CheckTokenMembership 函数。但是,这样做更复杂,所以上面的代码就是我今天使用的。

于 2013-10-16T06:04:12.347 回答
3

这是 EclipseLocationManager确定是否可以写入安装目录的操作:

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

注意创建 dll 的尝试

于 2013-09-05T10:15:52.260 回答