Java 在更新过程中移动JRE
我有一个Java/Eclipse应用程序,希望创建一个更新机制。Java 在更新过程中移动JRE,java,eclipse,batch-file,Java,Eclipse,Batch File,我有一个Java/Eclipse应用程序,希望创建一个更新机制。 JRE位于Eclipse安装目录(Application/JRE)中,我不想使用Equinoxp2机制 我必须执行以下步骤: 检查是否需要更新 下载并解包更新(包括JRE) 备份旧安装(在单独的目录中) 将解包的应用程序移动到安装目录 启动应用程序 现在我担心我将无法移动JRE,因为VM仍在运行。 我还认为关闭钩子可能不起作用,因为在运行的VM上也会发生这种情况 有没有人有过这样一个用例的经验,完成JRE迁移的最佳实践是什么?
JRE位于Eclipse安装目录(Application/JRE)中,我不想使用Equinoxp2机制 我必须执行以下步骤:
- 检查是否需要更新
- 下载并解包更新(包括JRE)
- 备份旧安装(在单独的目录中)
- 将解包的应用程序移动到安装目录
- 启动应用程序
我还认为关闭钩子可能不起作用,因为在运行的VM上也会发生这种情况 有没有人有过这样一个用例的经验,完成JRE迁移的最佳实践是什么?
创建一个.bat文件并在退出前运行它?我想出了一个解决方案,有一些实用程序类调用,但总的来说,我认为很清楚要做什么: 关键部分是: Runtime.getRuntime().exec(“cmd/c start\“update process\”+batFile) 当批处理文件在独立进程中启动时,批处理文件本身将执行所有复制操作
/**
* update the client installation, downloading update from server
*
* @return true if the update was successful
* @throws InvocationTargetException
* @throws InterruptedException
*/
protected boolean updateClient() throws InvocationTargetException, InterruptedException {
final File installDirectory = PathUtil.convertToFile(Platform.getInstallLocation().getURL());
if (!installDirectory.canWrite()) {
MessageDialog.openError(Display.getDefault().getActiveShell(), "Keine Schreibrechte",
"Keine Schreibrechte auf dem Installationsverzeichnis, Update kann nicht durchgeführt werden. Bitte benachrichtigen Sie einen Administrator.");
return false;
}
ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getDefault().getActiveShell());
dialog.run(false, false, new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
monitor.setTaskName("Update wird heruntergeladen");
File updateDirectory = Files.createTempDirectory("update_").toFile(); //$NON-NLS-1$
File outputDirectory = new File(updateDirectory, "PackageClient"); //$NON-NLS-1$
String arch = System.getProperty("osgi.arch"); //$NON-NLS-1$
HttpURLConnection connection = ConnectionUtil.openConnection("update/PackageClient_" + arch + ".zip"); //$NON-NLS-1$ //$NON-NLS-2$
logger.info("download update from {}", connection.getURL()); //$NON-NLS-1$
logger.info("unpack update to {}", outputDirectory); //$NON-NLS-1$
InputStream in = connection.getInputStream();
ZipUtil.unzipToDirectory(outputDirectory, in, monitor);
in.close();
// write batch file for later execution, since not able to update running application and JRE
String launcher = System.getProperty("eclipse.launcher"); //$NON-NLS-1$
File batFile = new File(updateDirectory, "update.bat"); //$NON-NLS-1$
// create batch file which will create backup, delete original installation, copy update and start application
String batchContent = String.format(
"xcopy \"%1$s\" \"%2$s\\backup\" /i /s /h /e /y\r\n" //$NON-NLS-1$
+ "FOR /D %%%%p IN (\"%1$s\\*.*\") DO rmdir \"%%%%p\" /s /q\r\ndel /q \"%1$s\\*.*\"\r\n" //$NON-NLS-1$
+ "xcopy \"%3$s\" \"%1$s\" /i /s /h /e /y\r\ncd \"%1$s\"\r\n" + "start \"\" \"%4$s\"\r\n" //$NON-NLS-1$ //$NON-NLS-2$
+ "start /MIN \"\" cmd /c rmdir \"%2$s\" /s /q exit\r\nexit", //$NON-NLS-1$
installDirectory, updateDirectory, outputDirectory, launcher);
FileUtil.writeFile(batFile, batchContent);
logger.info("launching update batch file {}", batFile); //$NON-NLS-1$
// start update batch file in independent process
Runtime.getRuntime().exec("cmd /c start \"update process\" " + batFile); //$NON-NLS-1$
} catch (Exception e) {
throw new InvocationTargetException(e);
}
}
});
return dialog.getReturnCode() == Window.OK;
}
下面是创建的批处理文件的示例:
xcopy "D:\temp\test\eclipse" "D:\temp\fdo\update_3081617184889033760\backup" /i /s /h /e /y
FOR /D %%p IN ("D:\temp\test\eclipse\*.*") DO rmdir "%%p" /s /q
del /q "D:\temp\test\eclipse\*.*"
xcopy "D:\temp\fdo\update_3081617184889033760\PackageClient" "D:\temp\test\eclipse" /i /s /h /e /y
cd "D:\temp\test\eclipse"
start "" "D:\temp\test\eclipse\Application.exe"
start /MIN "" cmd /c rmdir "D:\temp\fdo\update_3081617184889033760" /s /q exit
exit
我提出了一个解决方案,有一些实用程序类调用,但总的来说,我认为很清楚该怎么做: 关键部分是: Runtime.getRuntime().exec(“cmd/c start\“update process\”+batFile) 当批处理文件在独立进程中启动时,批处理文件本身将执行所有复制操作
/**
* update the client installation, downloading update from server
*
* @return true if the update was successful
* @throws InvocationTargetException
* @throws InterruptedException
*/
protected boolean updateClient() throws InvocationTargetException, InterruptedException {
final File installDirectory = PathUtil.convertToFile(Platform.getInstallLocation().getURL());
if (!installDirectory.canWrite()) {
MessageDialog.openError(Display.getDefault().getActiveShell(), "Keine Schreibrechte",
"Keine Schreibrechte auf dem Installationsverzeichnis, Update kann nicht durchgeführt werden. Bitte benachrichtigen Sie einen Administrator.");
return false;
}
ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getDefault().getActiveShell());
dialog.run(false, false, new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
monitor.setTaskName("Update wird heruntergeladen");
File updateDirectory = Files.createTempDirectory("update_").toFile(); //$NON-NLS-1$
File outputDirectory = new File(updateDirectory, "PackageClient"); //$NON-NLS-1$
String arch = System.getProperty("osgi.arch"); //$NON-NLS-1$
HttpURLConnection connection = ConnectionUtil.openConnection("update/PackageClient_" + arch + ".zip"); //$NON-NLS-1$ //$NON-NLS-2$
logger.info("download update from {}", connection.getURL()); //$NON-NLS-1$
logger.info("unpack update to {}", outputDirectory); //$NON-NLS-1$
InputStream in = connection.getInputStream();
ZipUtil.unzipToDirectory(outputDirectory, in, monitor);
in.close();
// write batch file for later execution, since not able to update running application and JRE
String launcher = System.getProperty("eclipse.launcher"); //$NON-NLS-1$
File batFile = new File(updateDirectory, "update.bat"); //$NON-NLS-1$
// create batch file which will create backup, delete original installation, copy update and start application
String batchContent = String.format(
"xcopy \"%1$s\" \"%2$s\\backup\" /i /s /h /e /y\r\n" //$NON-NLS-1$
+ "FOR /D %%%%p IN (\"%1$s\\*.*\") DO rmdir \"%%%%p\" /s /q\r\ndel /q \"%1$s\\*.*\"\r\n" //$NON-NLS-1$
+ "xcopy \"%3$s\" \"%1$s\" /i /s /h /e /y\r\ncd \"%1$s\"\r\n" + "start \"\" \"%4$s\"\r\n" //$NON-NLS-1$ //$NON-NLS-2$
+ "start /MIN \"\" cmd /c rmdir \"%2$s\" /s /q exit\r\nexit", //$NON-NLS-1$
installDirectory, updateDirectory, outputDirectory, launcher);
FileUtil.writeFile(batFile, batchContent);
logger.info("launching update batch file {}", batFile); //$NON-NLS-1$
// start update batch file in independent process
Runtime.getRuntime().exec("cmd /c start \"update process\" " + batFile); //$NON-NLS-1$
} catch (Exception e) {
throw new InvocationTargetException(e);
}
}
});
return dialog.getReturnCode() == Window.OK;
}
下面是创建的批处理文件的示例:
xcopy "D:\temp\test\eclipse" "D:\temp\fdo\update_3081617184889033760\backup" /i /s /h /e /y
FOR /D %%p IN ("D:\temp\test\eclipse\*.*") DO rmdir "%%p" /s /q
del /q "D:\temp\test\eclipse\*.*"
xcopy "D:\temp\fdo\update_3081617184889033760\PackageClient" "D:\temp\test\eclipse" /i /s /h /e /y
cd "D:\temp\test\eclipse"
start "" "D:\temp\test\eclipse\Application.exe"
start /MIN "" cmd /c rmdir "D:\temp\fdo\update_3081617184889033760" /s /q exit
exit
你说你不想要它,但显而易见的答案是使用p2。你回避它的原因是什么?我在互联网上发现,p2也无法更新JRE:上的评论说,你可以使用接触点引用包含更新JRE的其他文件夹。但是,这确实会留下旧的版本。更新到干净的安装是我们从p2切换到我们自己的更新机制的原因之一。旧的bundle也保存在plugins目录中,可能也会有处理方法。你说你不想要它,但显而易见的答案是使用p2。你回避它的原因是什么?我在互联网上发现,p2也无法更新JRE:上的评论说,你可以使用接触点引用包含更新JRE的其他文件夹。但是,这确实会留下旧的版本。更新到干净的安装是我们从p2切换到我们自己的更新机制的原因之一。旧的bundle也保存在plugins目录中,可能也会有一个处理方法。