windows 如何使文件自我更新(本机 C++)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1009356/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 12:39:16  来源:igfitidea点击:

How do I make a file self-update (Native C++)

c++windowsnative

提问by Clark Gaebel

I'm using Microsoft Visual Studio 2008 with a Windows target deployment. How would I make a file "update itself"? I've already got the "transmitting over a network" part down, but how do I make an executable write over itself?

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

Basically, I want to write an auto-updater for a directory that also includes the auto-updater, and the updater needs to update EVERYTHING in the directory.

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

Maybe a ways to pend the changes to the file for until the file lock is released would work. If I were to do that though, I'd probably follow it up with a hot-patch.

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

采纳答案by wprl

Write a new executable and delete or save a copy of the old one -- you could send a diff over the network and have a third program, the update monitor or whatever, to apply it. It would be just a small script that could be started from the remote app when it realizes an update is available. The updater could rename itself to $UPDATER_OLD_VERSION or whatever, write an updated copy of itself with the appropriate name, and then when the new updater is run you check if there is a file named $UPDATER_OLD_VERSION in the app directory and delete it. All other files could just be updated/overwritten.

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

回答by Mark Lakata

This is how I did it recently. There is a brief overlap of the old program running and the new programming running. It makes use of the trick that you can rename the current executable and bring the new file in place before you shut down the old one. This is not 100% fail safe, but the only way this could "brick" your application is if CopyFile fails.

我最近就是这样做的。旧程序运行和新程序运行有短暂的重叠。它利用了一种技巧,您可以在关闭旧文件之前重命名当前可执行文件并将新文件放置到位。这不是 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.
}

回答by muusbolla

You cannot generally modify an app while it is running. You willneed to close down the original program and modify it from another location.

您通常无法在应用程序运行时对其进行修改。你需要从其他位置关闭原来的程序并对其进行修改。

回答by Bob Moore

You can't overwrite a file while it's executing, but you CAN rename it. In my updater, I rename the existing exe to something meaningful (oldname_dateandtime), then write the new copy in. Then auto-shut our system down and restart it from a service. When the app starts, it's the new version running.

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

回答by Rob

I do this using an InnoSetup setup.exe that is launched silently and shuts my app down before it starts installing the new files. I had to add custom Pascal [Code] sections to ensure everything shuts down but it does the job.

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

回答by Hongseok Yoon

When I made a updater, I should separate the program several. The main reason was just same as what you want to do. Simply say, B updates target application plusA and A updates B. I tried to find another way but what I did was made extra small and simple updater. :(

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

回答by anand

I think you are talking about file versions and updaters. As you said you need autoupdater.So you need to create a service which monitors your install directory and compares the file version on your disk with server.

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

Once mismatch happens you can ask latest data from server . If the files going to be replaced are in use you have to mark them for deletion / unregistration during next reboot and you can mention these using registry.

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

You can copy all files in cache and later during reboot copy them to install directory.

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