В данной статье речь пойдет о том как сделать автообновление продукта и собственно создание самого ланчера/апдейтера. Хочу сразу отменить, что в данном руководстве речь пойдет о создании примитивного апдейтера, который качает только 1 файл. Класс Core.cs using System.Windows.Forms; namespace AutoUpdater { public static class Tools { public static DialogResult InfoBowShow(string text) { return MessageBox.Show(text, "Информация", MessageBoxButtons.OK, MessageBoxIcon.Information); } } } Код using System.Windows.Forms; namespace AutoUpdater { public static class Tools { public static DialogResult InfoBowShow(string text) { return MessageBox.Show(text, "Информация", MessageBoxButtons.OK, MessageBoxIcon.Information); } } } Класс Core.Settings.cs public class Settings { // Путь к файлу с настройками private String configFile = "updater.xml"; // Свойства для передачи данных из файла настроек public String UpdateServerVersionsUrl { get; set; } public String UpdateServerMainExeUrl { get; set; } public String LocalMainExe { get; set; } public Int32 Version { get; set; } public Settings() { Version = 0; } #region :: Methods :: public void Save() { try { XmlDocument xdoc = new XmlDocument(); { xdoc.AppendChild(xdoc.CreateNode(XmlNodeType.XmlDeclaration, "", "")); XmlNode conf = xdoc.CreateElement("ConfigurationFile"); { XmlNode lNode = xdoc.CreateElement("UpdateServerVersionsUrl"); XmlNode lNodeText = xdoc.CreateTextNode(UpdateServerVersionsUrl); lNode.AppendChild(lNodeText); conf.AppendChild(lNode); XmlNode pNode = xdoc.CreateElement("UpdateServerMainExeUrl"); XmlNode pNodeText = xdoc.CreateTextNode(UpdateServerMainExeUrl); pNode.AppendChild(pNodeText); conf.AppendChild(pNode); XmlNode mNode = xdoc.CreateElement("LocalMainExe"); XmlNode mNodeText = xdoc.CreateTextNode(LocalMainExe); mNode.AppendChild(mNodeText); conf.AppendChild(mNode); XmlNode vNode = xdoc.CreateElement("Version"); XmlNode vNodeText = xdoc.CreateTextNode(Version.ToString()); vNode.AppendChild(vNodeText); conf.AppendChild(vNode); } xdoc.AppendChild(conf); } xdoc.Save(configFile); } catch { } } public void Load() { if (File.Exists(configFile)) { try { XmlDocument xdoc = new XmlDocument(); xdoc.Load(configFile); XmlNode reader = xdoc.SelectSingleNode("ConfigurationFile/UpdateServerVersionsUrl"); if (reader != null) UpdateServerVersionsUrl = reader.InnerText; reader = xdoc.SelectSingleNode("ConfigurationFile/UpdateServerMainExeUrl"); if (reader != null) UpdateServerMainExeUrl = reader.InnerText; reader = xdoc.SelectSingleNode("ConfigurationFile/LocalMainExe"); if (reader != null) LocalMainExe = reader.InnerText; reader = xdoc.SelectSingleNode("ConfigurationFile/Version"); if (reader != null) { int tmpInt = 0; if (Int32.TryParse(reader.InnerText, out tmpInt)) Version = Int32.Parse(reader.InnerText); } } catch { } } } #endregion } } Код public class Settings { // Путь к файлу с настройками private String configFile = "updater.xml"; // Свойства для передачи данных из файла настроек public String UpdateServerVersionsUrl { get; set; } public String UpdateServerMainExeUrl { get; set; } public String LocalMainExe { get; set; } public Int32 Version { get; set; } public Settings() { Version = 0; } #region :: Methods :: public void Save() { try { XmlDocument xdoc = new XmlDocument(); { xdoc.AppendChild(xdoc.CreateNode(XmlNodeType.XmlDeclaration, "", "")); XmlNode conf = xdoc.CreateElement("ConfigurationFile"); { XmlNode lNode = xdoc.CreateElement("UpdateServerVersionsUrl"); XmlNode lNodeText = xdoc.CreateTextNode(UpdateServerVersionsUrl); lNode.AppendChild(lNodeText); conf.AppendChild(lNode); XmlNode pNode = xdoc.CreateElement("UpdateServerMainExeUrl"); XmlNode pNodeText = xdoc.CreateTextNode(UpdateServerMainExeUrl); pNode.AppendChild(pNodeText); conf.AppendChild(pNode); XmlNode mNode = xdoc.CreateElement("LocalMainExe"); XmlNode mNodeText = xdoc.CreateTextNode(LocalMainExe); mNode.AppendChild(mNodeText); conf.AppendChild(mNode); XmlNode vNode = xdoc.CreateElement("Version"); XmlNode vNodeText = xdoc.CreateTextNode(Version.ToString()); vNode.AppendChild(vNodeText); conf.AppendChild(vNode); } xdoc.AppendChild(conf); } xdoc.Save(configFile); } catch { } } public void Load() { if (File.Exists(configFile)) { try { XmlDocument xdoc = new XmlDocument(); xdoc.Load(configFile); XmlNode reader = xdoc.SelectSingleNode("ConfigurationFile/UpdateServerVersionsUrl"); if (reader != null) UpdateServerVersionsUrl = reader.InnerText; reader = xdoc.SelectSingleNode("ConfigurationFile/UpdateServerMainExeUrl"); if (reader != null) UpdateServerMainExeUrl = reader.InnerText; reader = xdoc.SelectSingleNode("ConfigurationFile/LocalMainExe"); if (reader != null) LocalMainExe = reader.InnerText; reader = xdoc.SelectSingleNode("ConfigurationFile/Version"); if (reader != null) { int tmpInt = 0; if (Int32.TryParse(reader.InnerText, out tmpInt)) Version = Int32.Parse(reader.InnerText); } } catch { } } } #endregion } } Класс Core.AutoUpdater.cs using System; using System.IO; using System.Net; using System.Threading; using System.Diagnostics; namespace AutoUpdater { public class Core { // Класс-структура, который мы будем передавать как аргумент в событие, // которое вызывается после проверки версии сервера public class AutoUpdateEventArg { // Флаг отражающий успех или провал попытки получить версию сервера public Boolean UpdateSuccess { get; set; } // Флаг отражающий нужно ли нам обновление public Boolean NeedToUpdate { get; set; } public AutoUpdateEventArg(bool UpdateSuccess, bool NeedToUpdate) { this.UpdateSuccess = UpdateSuccess; this.NeedToUpdate = NeedToUpdate; } } // Создание нового делегата public delegate void AutoUpdateCheckDelegate(AutoUpdateEventArg arg); // Создание события на базе делегата public event AutoUpdateCheckDelegate CheckForUpdatesCompleted; // Метод вызова события внутри класса инициатора private void OnCheckForUpdatesCompleted(AutoUpdateEventArg arg) { if (CheckForUpdatesCompleted != null) CheckForUpdatesCompleted(arg); } // Объект класса настроек private Settings settings; // Объект класса WebClient private WebClient downloader; // Свойства public WebClient Downloader { get { return downloader; } } public Int32 CurrentVersion { get; set; } public Int32 ServerVersion { get; set; } public Core() { downloader = new WebClient(); settings = new Settings(); // Загружаем файл настроек settings.Load(); // Устанавилваем начальные значения версий this.ServerVersion = 0; this.CurrentVersion = settings.Version; } // Метод, для проверки на сколько успешно загрузились настройки public bool CheckSettings() { // Если хотябы одно из 3х свойств настроек пустое if (String.IsNullOrEmpty(settings.LocalMainExe) || String.IsNullOrEmpty(settings.UpdateServerMainExeUrl) || String.IsNullOrEmpty(settings.UpdateServerVersionsUrl)) { // возвращаем false; return false; } else return true; } // Метод для запуска главного файла (не автообновления) public void RunMainExe() { try { using (Process p = new Process() { StartInfo = new ProcessStartInfo(settings.LocalMainExe) }) { p.Start(); System.Windows.Forms.Application.Exit(); } } catch { Tools.InfoBowShow("Ошибка при запуске главного приложения!"); System.Windows.Forms.Application.Exit(); } } // Метод проверки наличиия обновления на сервере public void CheckForUpdates() { // Создаем объект класса Thread и инициализируем его Thread checkerThread = new Thread(new ThreadStart(delegate { try { // Веб запрос к нашему серверу по URL с файлом хранящим версию на сервере HttpWebRequest request = (HttpWebRequest)WebRequest.Create(settings.UpdateServerVersionsUrl); // Ответ сервера HttpWebResponse response = (HttpWebResponse)request.GetResponse(); // Используем чтение потока данных using (StreamReader reader = new StreamReader(response.GetResponseStream())) { // Пытаемся получить версию сервера, приобразуя в Int32 из строки // строка это содержимое файла версий с сервера ServerVersion = Int32.Parse(reader.ReadToEnd()); // Если версия сервера выше, то мы сообщаем о завершении проверки и передаем // флаги, что проверка прошла успешно и надо обновиться if (ServerVersion > CurrentVersion) OnCheckForUpdatesCompleted(new AutoUpdateEventArg(true, true)); // В противном случаи говорим, что проверка прошла успешно, но обновления не надо else OnCheckForUpdatesCompleted(new AutoUpdateEventArg(true, false)); } } catch { // Если возникает ошибка, то говорим, что проверка не удалась и обновления не нужно OnCheckForUpdatesCompleted(new AutoUpdateEventArg(false, false)); } })); // Запускаем наш поток, чтобы он выполнил код выше checkerThread.Start(); } // Метод для скачивания обновленной версии файла с сервера public void DownloadUpdates() { // Запускаем асинхронное скачивание файла // Указываем URL - что качать и путь куда сохранить downloader.DownloadFileAsync(new Uri(settings.UpdateServerMainExeUrl), settings.LocalMainExe); // Добавляем обработчик события downloader.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(downloader_DownloadFileCompleted); } // Если скачивание обновленного файла прошло успешно, что сохраняем в настройки версию с сервера private void downloader_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { settings.Version = ServerVersion; settings.Save(); } } } Код using System; using System.IO; using System.Net; using System.Threading; using System.Diagnostics; namespace AutoUpdater { public class Core { // Класс-структура, который мы будем передавать как аргумент в событие, // которое вызывается после проверки версии сервера public class AutoUpdateEventArg { // Флаг отражающий успех или провал попытки получить версию сервера public Boolean UpdateSuccess { get; set; } // Флаг отражающий нужно ли нам обновление public Boolean NeedToUpdate { get; set; } public AutoUpdateEventArg(bool UpdateSuccess, bool NeedToUpdate) { this.UpdateSuccess = UpdateSuccess; this.NeedToUpdate = NeedToUpdate; } } // Создание нового делегата public delegate void AutoUpdateCheckDelegate(AutoUpdateEventArg arg); // Создание события на базе делегата public event AutoUpdateCheckDelegate CheckForUpdatesCompleted; // Метод вызова события внутри класса инициатора private void OnCheckForUpdatesCompleted(AutoUpdateEventArg arg) { if (CheckForUpdatesCompleted != null) CheckForUpdatesCompleted(arg); } // Объект класса настроек private Settings settings; // Объект класса WebClient private WebClient downloader; // Свойства public WebClient Downloader { get { return downloader; } } public Int32 CurrentVersion { get; set; } public Int32 ServerVersion { get; set; } public Core() { downloader = new WebClient(); settings = new Settings(); // Загружаем файл настроек settings.Load(); // Устанавилваем начальные значения версий this.ServerVersion = 0; this.CurrentVersion = settings.Version; } // Метод, для проверки на сколько успешно загрузились настройки public bool CheckSettings() { // Если хотябы одно из 3х свойств настроек пустое if (String.IsNullOrEmpty(settings.LocalMainExe) || String.IsNullOrEmpty(settings.UpdateServerMainExeUrl) || String.IsNullOrEmpty(settings.UpdateServerVersionsUrl)) { // возвращаем false; return false; } else return true; } // Метод для запуска главного файла (не автообновления) public void RunMainExe() { try { using (Process p = new Process() { StartInfo = new ProcessStartInfo(settings.LocalMainExe) }) { p.Start(); System.Windows.Forms.Application.Exit(); } } catch { Tools.InfoBowShow("Ошибка при запуске главного приложения!"); System.Windows.Forms.Application.Exit(); } } // Метод проверки наличиия обновления на сервере public void CheckForUpdates() { // Создаем объект класса Thread и инициализируем его Thread checkerThread = new Thread(new ThreadStart(delegate { try { // Веб запрос к нашему серверу по URL с файлом хранящим версию на сервере HttpWebRequest request = (HttpWebRequest)WebRequest.Create(settings.UpdateServerVersionsUrl); // Ответ сервера HttpWebResponse response = (HttpWebResponse)request.GetResponse(); // Используем чтение потока данных using (StreamReader reader = new StreamReader(response.GetResponseStream())) { // Пытаемся получить версию сервера, приобразуя в Int32 из строки // строка это содержимое файла версий с сервера ServerVersion = Int32.Parse(reader.ReadToEnd()); // Если версия сервера выше, то мы сообщаем о завершении проверки и передаем // флаги, что проверка прошла успешно и надо обновиться if (ServerVersion > CurrentVersion) OnCheckForUpdatesCompleted(new AutoUpdateEventArg(true, true)); // В противном случаи говорим, что проверка прошла успешно, но обновления не надо else OnCheckForUpdatesCompleted(new AutoUpdateEventArg(true, false)); } } catch { // Если возникает ошибка, то говорим, что проверка не удалась и обновления не нужно OnCheckForUpdatesCompleted(new AutoUpdateEventArg(false, false)); } })); // Запускаем наш поток, чтобы он выполнил код выше checkerThread.Start(); } // Метод для скачивания обновленной версии файла с сервера public void DownloadUpdates() { // Запускаем асинхронное скачивание файла // Указываем URL - что качать и путь куда сохранить downloader.DownloadFileAsync(new Uri(settings.UpdateServerMainExeUrl), settings.LocalMainExe); // Добавляем обработчик события downloader.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(downloader_DownloadFileCompleted); } // Если скачивание обновленного файла прошло успешно, что сохраняем в настройки версию с сервера private void downloader_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { settings.Version = ServerVersion; settings.Save(); } } } Настройка автообновления: Клиентский файл - updater.xml <?xml version="1.0"?> <ConfigurationFile> <UpdateServerVersionsUrl>http://localhost/autoupdater/versions.file</UpdateServerVersionsUrl> <UpdateServerMainExeUrl>http://localhost/autoupdater/mainFile.exe</UpdateServerMainExeUrl> <LocalMainExe>mainFile.exe</LocalMainExe> <Version>1</Version> </ConfigurationFile> Код <?xml version="1.0"?> <ConfigurationFile> <UpdateServerVersionsUrl>http://localhost/autoupdater/versions.file</UpdateServerVersionsUrl> <UpdateServerMainExeUrl>http://localhost/autoupdater/mainFile.exe</UpdateServerMainExeUrl> <LocalMainExe>mainFile.exe</LocalMainExe> <Version>1</Version> </ConfigurationFile> Разъяснения: Ключ: UpdateServerVersionsUrl - путь на сервере к файлу с версиями Ключ: UpdateServerMainExeUrl - путь к файлу, который будет скачан с сервера Ключ: LocalMainExe - главный файл, который запускается из автообновления и куда сохранится скачанный файл. Ключ: Version - текущая версия локального главного файла. Скачать Virus Total - нет exe файлов,только исходники. by TBX1n