8

我正在使用带有 Windows 目标部署的 Microsoft Visual Studio 2008。我将如何使文件“更新自身”?我已经完成了“通过网络传输”部分,但是如何让可执行文件自行改写呢?

基本上,我想为一个包含自动更新程序的目录编写一个自动更新程序,并且更新程序需要更新目录中的所有内容。

也许在文件锁被释放之前挂起对文件的更改的方法会起作用。如果我要这样做,我可能会用热补丁跟进它。

4

7 回答 7

5

编写一个新的可执行文件并删除或保存旧可执行文件的副本——您可以通过网络发送一个差异,并使用第三个程序、更新监视器或其他程序来应用它。它只是一个小脚本,当它意识到有更新可用时,可以从远程应用程序启动。更新程序可以将自身重命名为 $UPDATER_OLD_VERSION 或其他名称,使用适当的名称写入自身的更新副本,然后在运行新更新程序时检查应用目录中是否存在名为 $UPDATER_OLD_VERSION 的文件并将其删除。所有其他文件都可以被更新/覆盖。

于 2009-06-17T20:30:45.203 回答
4

这就是我最近的做法。旧程序运行和新程序运行有短暂的重叠。它利用了您可以重命名当前可执行文件并在关闭旧文件之前将新文件放置到位的技巧。这不是 100% 的故障安全,但是如果 CopyFile 失败,这可能会“破坏”您的应用程序的唯一方法。

#include <windows.h>
#include <iostream>
#include <fstream>

void UpgradeService::UpgradeSelf() {

  std::string temp = root         + "\\myprogram_tmp.exe";
  remove(temp.c_str()); // ignore return code

  std::string src = upgradeFolder + "\\myprogram.exe";
  std::string dst = root          + "\\myprogram.exe";


  rename(dst.c_str(),temp.c_str());
  CopyFile(src.c_str(),dst.c_str(),false);
  static char buffer[512];
  strcpy(buffer,dst.c_str());

  /* CreateProcess API initialization */
  STARTUPINFO siStartupInfo;
  PROCESS_INFORMATION piProcessInfo;
  memset(&siStartupInfo, 0, sizeof(siStartupInfo));
  memset(&piProcessInfo, 0, sizeof(piProcessInfo));
  siStartupInfo.cb = sizeof(siStartupInfo);

  ::CreateProcess(buffer, // application name/path
    NULL, // command line (optional)
    NULL, // no process attributes (default)
    NULL, // default security attributes
    false,
    CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE,
    NULL, // default env
    NULL, // default working dir
    &siStartupInfo,
    &piProcessInfo);


  ::TerminateProcess( GetCurrentProcess(),0);
  ::ExitProcess(0); // exit this process

  // this does not return.
}
于 2011-07-21T05:05:50.923 回答
3

您通常不能在应用程序运行时对其进行修改。您需要关闭原始程序并从另一个位置对其进行修改。

于 2009-06-17T20:47:40.037 回答
2

我使用 InnoSetup setup.exe 执行此操作,该程序以静默方式启动并在开始安装新文件之前关闭我的应用程序。我必须添加自定义 Pascal [代码] 部分以确保一切都关闭,但它可以完成工作。

于 2009-06-17T20:34:56.053 回答
2

你不能在文件执行时覆盖它,但你可以重命名它。在我的更新程序中,我将现有的 exe 重命名为有意义的名称(oldname_dateandtime),然后将新副本写入其中。然后自动关闭我们的系统并从服务重新启动它。当应用程序启动时,它是正在运行的新版本。

于 2009-06-17T21:04:01.597 回答
0

当我制作更新程序时,我应该将程序分开几个。主要原因和你想做的一样。简单地说,B 更新目标应用程序加上A 和 A 更新 B。我试图找到另一种方法,但我所做的只是制作了更小更简单的更新程序。:(

于 2009-06-17T23:09:42.997 回答
0

我认为您在谈论文件版本和更新程序。正如您所说,您需要自动更新程序。因此,您需要创建一个服务来监视您的安装目录并将磁盘上的文件版本与服务器进行比较。

一旦发生不匹配,您可以从服务器询问最新数据。如果要替换的文件正在使用中,您必须在下次重新启动时将它们标记为删除/注销,您可以使用注册表提及这些。

您可以复制缓存中的所有文件,然后在重新启动期间将它们复制到安装目录。

于 2009-06-18T00:05:10.887 回答