在Windows上以管理员身份运行Java应用程序
问题描述:
我正在编写一个Java安装程序,因此需要提升特权才能访问Program Files目录。在Windows上以管理员身份运行Java应用程序
public static void main(String args[]) {
if (!checkPrivileges()) { // spawn a copy w/ elevated privileges
Runtime runtime = Runtime.getRuntime();
try {
Process p = runtime.exec(
"runas /profile /user:Administrator \"java -cp . main.Main\"");
} catch (IOException e) { ... }
} else {
// Run with elevated privileges
}
}
,我使用检查权限的测试稍微偏离的回答修改发现here,看起来像这样:在此基础上,我在网上找到的信息,如下我写的实现:
private static boolean checkPrivileges() {
File testPriv = new File("C:\\Program Files\\");
if (!testPriv.canWrite()) return false;
File fileTest = null;
try {
fileTest = File.createTempFile("test", ".dll", testPriv);
} catch (IOException e) {
return false;
} finally {
if (fileTest != null)
fileTest.delete();
}
return true;
}
当我运行这个时,它失败了特权测试 - 如预期的那样 - 并且调用exec。实际上,通过查看p.isAlive()
来检查呼叫是否工作表明该过程是活着的;但是,我没有看到新流程的任何证据,Windows并未提示我授予权限。
我不熟悉在Java中使用exec()
,所以我很可能以某种方式误解了它的用法。对于这个问题,我试图在这里甚至有可能做什么?如果没有,是否有一个简单的替代方案能够真正为我带来我期待的结果?
答
好吧,我终于设法得到了一个解决方案,我很满意这个问题;这有点丑陋,但它适用于我正在做的事情。
我借用this的代码做了实际的权限提升;从那里开始,问题就是真正让这个解决方案与Java协同工作。对于该代码最终看起来像这样:
if (!checkPrivileges()) {
try {
String jarPath = DownloaderMain.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(jarPath, "UTF-8");
decodedPath = decodedPath.substring(1, decodedPath.length());
Elevator.executeAsAdministrator(System.getProperty("java.home") + "\\bin\\java", "-jar " + "\"" + decodedPath + "\"");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
// Run with elevated privileges
}
的checkPrivileges
方法是不变的,从上方和Elevator
类几乎是相同的出现在连接溶液中的一个(I只是拿出不需要main
方法) 。该解决方案假定要升高的过程是一个罐子;要改变这种情况以适应您的个人需求不应太困难。
答
我认为实现这一目标的最佳方法是使用microsoft为开发人员构建的工具,因为您无法在简单的Java中执行该工具。在这种情况下,使用清单文件 http://msdn.microsoft.com/en-us/library/aa375632(v=vs.85).aspx 只需构建包装器.exe,请求此权限,然后生成您的Java程序。
在Windows 8(也可能是其他的)中,使用'runas'实际上并没有带来UAC弹出窗口,而是提示输入密码通过stdin。尝试在命令提示符窗口中运行'runas/profile/user:Administrator notepad';这可能解释你的问题。 – Pokechu22 2014-10-30 22:11:42
这确实是这种情况。我想这只会导致一个后续问题:如何在Java中创建一个UAC弹出窗口? 或者,我的目标平台是Windows 7(即使我正在Windows 8平台上开发)。此代码是否可以完成我在该平台上的计划? – bionicOnion 2014-10-30 22:26:21
一个解决方案是在C中编写一个简单的应用程序,以便为您重新启动Java程序。您可以给应用程序一个应用程序清单,告诉Windows需要提升。但是,可能有一种方法可以直接在Java中执行,这是一个有趣的问题。 +1。 – 2014-10-30 22:34:04