C++ 如何进行文件自我更新(本机C+;+;)

C++ 如何进行文件自我更新(本机C+;+;),c++,windows,native,C++,Windows,Native,我正在使用Microsoft Visual Studio 2008和Windows目标部署。如何使文件“自我更新”?我已经把“通过网络传输”部分搞定了,但是如何让一个可执行文件自己写呢 基本上,我想为一个目录编写一个自动更新程序,该目录也包含自动更新程序,更新程序需要更新目录中的所有内容 也许有一种方法可以在释放文件锁之前暂停对文件的更改。如果我要这么做的话,我可能会用一个热补丁来跟进。编写一个新的可执行文件并删除或保存旧文件的副本——你可以通过网络发送一个diff,然后使用第三个程序,更新监视

我正在使用Microsoft Visual Studio 2008和Windows目标部署。如何使文件“自我更新”?我已经把“通过网络传输”部分搞定了,但是如何让一个可执行文件自己写呢

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


也许有一种方法可以在释放文件锁之前暂停对文件的更改。如果我要这么做的话,我可能会用一个热补丁来跟进。

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

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

一般来说,你不能在应用程序运行时修改它。您需要关闭原始程序并从其他位置对其进行修改。

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

当我制作一个更新程序时,我应该将程序分为几个部分。主要原因和你想做的一样。简单地说,B更新目标应用程序plusA,A更新B。
我试图找到另一种方法,但我所做的是使更新程序变得非常小和简单(

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

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


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

我最近就是这样做的。运行的旧程序和运行的新程序有一个短暂的重叠。它利用了一种技巧,即您可以重命名当前可执行文件,并在关闭旧文件之前将新文件放在适当的位置。This不是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.
}
#包括
#包括
#包括
void UpgradeService::UpgradeSelf(){
std::string temp=root+“\\myprogram\u tmp.exe”;
remove(temp.c_str());//忽略返回代码
std::string src=upgradeFolder+“\\myprogram.exe”;
std::string dst=root+“\\myprogram.exe”;
重命名(dst.c_str(),temp.c_str());
复制文件(src.c_str(),dst.c_str(),false);
静态字符缓冲区[512];
strcpy(缓冲区,dst.c_str());
/*CreateProcess API初始化*/
STARTUPINFO-siStartupInfo;
进程信息piProcessInfo;
memset(&siStartupInfo,0,sizeof(siStartupInfo));
memset(&piProcessInfo,0,sizeof(piProcessInfo));
siStartupInfo.cb=sizeof(siStartupInfo);
::CreateProcess(缓冲区,//应用程序名称/路径
NULL,//命令行(可选)
NULL,//没有进程属性(默认)
NULL,//默认安全属性
假,,
创建默认错误模式创建新控制台,
NULL,//默认环境
NULL,//默认工作目录
&siStartupInfo,
&piProcessInfo);
::TerminateProcess(GetCurrentProcess(),0);
::ExitProcess(0);//退出此进程
//这不会回来。
}

可能的DUPE:不是一个DUPE,这是专门的本地C++。不。这个解决方案太麻烦了。我宁愿不拥有“临时数据”。如果计算机在中间崩溃,那么WOWUS会怎样?它比临时覆盖实际的EXE写临时数据要好得多。此外,修复是很容易的:写一个TEMPFILE,然后调用MOVEFILE文件把它放在它的最终位置。在同一卷上,MOVEFILE是原子的,所以崩溃不会使它处于不一致的状态。D的建议是这样做的。一般情况下,你正在更新的应用程序不能更新自己。如你所说,如果计算机在中间崩溃,如果写一个设备驱动程序或黑客操作系统,那么我认为像这样的方案是唯一的方法。当你在Windows下运行一个可执行文件时,操作系统会保持它的打开写。锁定。我也这样做,并在启动时清理旧版本。我们保留旧版本,以便我们的现场服务工程师在出现问题时可以恢复。当然,我们有现场服务工程师的特权:-)。旧版本在下一次升级时被清除。