Ответ 1
Смотрите, если ClickOnce Deployment дает вам то, что вам нужно.
Я написал программу, которая обновляет себя, если находит более новую версию на сервере, но мне сложно выполнить ее чисто.
Проверка удаленного сервера и загрузка файла достаточно просты, но что? Он не может просто File.Copy( "newversion.exe", "myprogram.exe" ), потому что моя программа запущена и файл заблокирован.
Я делаю это, загружая два файла newversion и update. Затем myprogram запускает обновление и завершает работу. обновление ждет две секунды, выполняет ли копирование, затем запускает myprogram (которая теперь является обновленной версией) и выходит. myprogram ищет обновление при запуске и удаляет его и newversion, если он их находит. mypogram теперь является новой версией без файлов, оставшихся на месте.
Должен быть лучший способ, чем это, а что .net-путь для самой программы для обновления?
PS. Извините, если этот вопрос появляется дважды - в первый раз, когда я отправил его, у меня была страница с переполнением стека.
Смотрите, если ClickOnce Deployment дает вам то, что вам нужно.
Я посмотрел как на Wix, так и на ClickOnce и не любил их. Я хотел что-то более простое, для однофайловых приложений WPF типа xcopy для развертывания.
Итак, я построил один. Это класс AppUpdater, который вы можете загрузить в любое приложение WPF, автоматически обновляя его при необходимости.
Проверка номера версии и загрузка последней версии легко.
Следующая часть менее проста. Как заменить запущенное приложение? Подход, который я принял, был следующим:
каждый раз, когда он запускается, приложение проверяет известный URL-адрес для версии. Если версия не позднее версии исполняемого приложения, то больше делать нечего.
Если версия позже, приложение захватывает именованный Mutex, копирует себя (Assembly.GetExecutingAssembly(). Location) во временное место, а затем запускает новый процесс (процесс № 2) из этого временного местоположения, передавая аргумент командной строки, который говорит "вы пытаетесь обновить" и даете исходное местоположение exe.
процесс № 1 отключается.
процесс № 2 запускается - он видит, что он пытается обновить, поэтому он загружает обновленное изображение и помещает его в исходное местоположение (место, которое было передано в командной строке). Вместо того, чтобы ждать 2 секунды или любое произвольное время, он использует именованный Mutex, чтобы определить, когда завершился процесс №1.
процесс №2 затем запускает процесс №3 - используя исходное местоположение.
Процесс № 2 выключается, освобождая его названный Mutex.
запускается процесс №3. Он проверяет URL версии - видит, что он является текущим. Не требуется обновление. Процесс № 3 также ожидает, что процесс №2 выпустит свой Mutex, а затем удалит временную копию EXE - той, которая была использована процессом №2.
ИЗМЕНИТЬ
В ответ на комментарий, да, это звучит сложно. Но логика, которая делает все, что есть в модуле AppUpdater. Использовать его из WPF-приложения довольно просто:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
// add this line in your constructor
if (UpdaterCheck()) this.Hide();
}
// this is all boilerplate
private Ionic.AppUpdater.Wpf.Updater _updater;
private string _manifestUrl = "http://example.org/AppUpdates/MyApplication/Manifest.xml";
private string _infoUrl = "http://example.org/MyApplication.html";
private string _description = "MyApplication is a delightful application; it does x, y, and z. ";
// Obtain the publicKey XML from the ManifestTool that ships with Ionic AppUpdater.
// The following string is Ionic public key. You will need a different one.
// Consult the Readme for more information.
private string _publicKeyXml = "<RSAKeyValue><Modulus>sZqhvF0KX6m4blah..blah...=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
// add this boilerplate method
private bool UpdaterCheck()
{
_updater = new Ionic.AppUpdater.Wpf.Updater("This is MyApplication.",
_infoUrl,
_description,
_manifestUrl,
_publicKeyXml);
return _updater.Status.IsUpdating;
}
...
Подробности и код, который вы можете запустить здесь.
Он работает только с приложениями WPF, но было бы довольно просто создать версию WinForms. Такая же идея, хотя какая-то логика, которая генерирует пользовательский интерфейс, должна измениться.
Вы можете использовать WIX или ClickOnce. Они справляются с этим для вас.
Легко, когда вы знаете "обходной путь". Ваша программа не может загрузиться сама по себе, потому что файл заблокирован запущенным процессом. Обходной путь заключается в том, что все еще возможно RENAME файл. Итак, вот что вы делаете:
Если ваше имя программы "myprogram.exe" :
Это позволит вам обновить вашу программу без внешнего обновления.
Вы можете посмотреть .NET No Touch Deployment. Он был заменен, по крайней мере, маркетингом Click-Once.
Я написал приложение, которое использовало это. Он вытащил сборку с локального сервера интрасети. Он использовал сокеты для прослушивания определенного порта, поэтому я смог принудительно обновить их, отправив сообщение, которое породило другую программу, чтобы убить ее/перезапустить. Вероятно, это не лучшее решение, но оно сработало.
Я бы сказал, что Click-Once - лучшее решение, но я думал, что упоминаю No Touch.