Как сделать самообновление файла (Native C ++) - PullRequest
6 голосов
/ 18 июня 2009

Я использую Microsoft Visual Studio 2008 с целевым развертыванием Windows. Как мне сделать файл "обновить себя"? У меня уже отключена часть "передача по сети", но как мне сделать исполняемый файл записывающим поверх себя?

По сути, я хочу написать автообновление для каталога, который также включает автообновление, и обновителю необходимо обновить ВСЕ в каталоге.

Возможно, будут работать способы ожидания изменений в файле до тех пор, пока не будет снята блокировка файла. Хотя, если бы я сделал это, я бы, вероятно, выполнил исправление.

Ответы [ 7 ]

5 голосов
/ 18 июня 2009

Напишите новый исполняемый файл и удалите или сохраните копию старого - вы можете отправить diff по сети и иметь третью программу, монитор обновлений или что-то еще, чтобы применить его. Это будет всего лишь небольшой скрипт, который можно запустить из удаленного приложения, когда он обнаружит, что доступно обновление. Средство обновления может переименовать себя в $ UPDATER_OLD_VERSION или что-то еще, написать обновленную копию с соответствующим именем, а затем при запуске нового средства обновления проверить, есть ли файл с именем $ UPDATER_OLD_VERSION в каталоге приложения, и удалить его. Все остальные файлы могут быть просто обновлены / перезаписаны.

4 голосов
/ 21 июля 2011

Вот как я это сделал недавно. Существует краткое совпадение старой программы и новой программы. Он использует хитрость, заключающуюся в том, что вы можете переименовать текущий исполняемый файл и установить новый файл на место, прежде чем закрыть старый. Это не 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.
}
3 голосов
/ 18 июня 2009

Обычно вы не можете изменять приложение во время его работы. Вам потребуется , чтобы закрыть исходную программу и изменить ее из другого места.

2 голосов
/ 18 июня 2009

Вы не можете перезаписать файл во время его выполнения, но вы МОЖЕТЕ переименовать его. В моем модуле обновления я переименовываю существующий исполняемый файл во что-то значимое (oldname_dateandtime), затем записываю новую копию. Затем автоматически выключаем нашу систему и перезапускаем ее из службы. При запуске приложения запускается новая версия.

2 голосов
/ 18 июня 2009

Я делаю это с помощью InnoSetup setup.exe, который запускается без вывода сообщений и закрывает мое приложение, прежде чем оно начнет устанавливать новые файлы. Мне пришлось добавить пользовательские разделы Pascal [Code], чтобы все выключалось, но оно выполняло свою работу.

0 голосов
/ 18 июня 2009

Я думаю, вы говорите о версиях файлов и обновлениях. Как вы сказали, вам нужен autoupdater. Итак, вам нужно создать службу, которая отслеживает ваш установочный каталог и сравнивает версию файла на вашем диске с сервером.

При возникновении несоответствия вы можете запросить последние данные с сервера. Если файлы, которые будут заменены, используются, вы должны пометить их для удаления / отмены регистрации во время следующей перезагрузки, и вы можете упомянуть их, используя реестр.

Вы можете скопировать все файлы в кеш, а затем при перезагрузке скопировать их в каталог установки.

0 голосов
/ 18 июня 2009

Когда я сделал обновление, я должен разделить программу на несколько. Основная причина была такой же, как то, что вы хотите сделать. Проще говоря, B обновляет целевое приложение плюс A и A обновляет B. Я попытался найти другой способ, но то, что я сделал, было сделано очень маленьким и простым средством обновления. (

...