场合
我有一个在多个平台上运行的(基于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
但是,该解决方案将返回活动用户是否为Administrator组的成员。用户可能仍然以非提升模式启动我的应用程序。我已经证实了这一点。
注意
我知道Eclipse RCP应用程序会在用户目录中自动安装更新,当他或她没有管理员权限时,我想阻止这种情况。
我想允许特定于用户的配置(工作正常),但允许用户特定的更新会在卸载后留下太多混乱。
答案 0 :(得分:3)
这是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;
}
请注意尝试创建dll
答案 1 :(得分:2)
使用JNA和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();
}
}
根据MS文档,未来版本的Windows中可能不存在IsUserAnAdmin()。因此,更好的方法是使用JNA来调用CheckTokenMembership function。但是,这样做更复杂,所以上面的代码就是我今天使用的。