123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- using System;
- using System.Collections;
- using System.ComponentModel;
- using System.Globalization;
- using System.IO;
- using System.Reflection;
- using System.Windows.Forms;
- namespace Microsoft.Samples.AppUpdater
- {
- public class AppUpdater : Component, ISupportInitialize
- {
- public delegate bool CheckForUpdateEventHandler(object sender, EventArgs e);
- public delegate void UpdateDetectedEventHandler(object sender, UpdateDetectedEventArgs e);
- public delegate void UpdateCompleteEventHandler(object sender, UpdateCompleteEventArgs e);
- public delegate void NotifyUpdateFileInfoEventHandler(object sender, NotifyUpdateFileInfoEventArgs e);
- public const int RestartAppReturnValue = 2;
- private Container components;
- private bool LoadingAssembly;
- private Control EventControl;
- internal AppManifest Manifest;
- private AppDownloader _Downloader;
- private ServerPoller _Poller;
- private string _UpdateUrl = "http://localhost/";
- private ChangeDetectionModes _ChangeDetectionMode = ChangeDetectionModes.DirectFileCheck;
- private bool _ShowDefaultUI;
- private bool _AutoFileLoad;
- [Category("AppUpdate Configuration")]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
- [Description("The object that downloads and installs new updates.")]
- [TypeConverter(typeof(ExpandableObjectConverter))]
- public AppDownloader Downloader
- {
- get
- {
- return _Downloader;
- }
- set
- {
- _Downloader = value;
- }
- }
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
- [TypeConverter(typeof(ExpandableObjectConverter))]
- [Description("The object that periodically polls for new updates.")]
- [Category("AppUpdate Configuration")]
- public ServerPoller Poller
- {
- get
- {
- return _Poller;
- }
- set
- {
- _Poller = value;
- }
- }
- [Category("AppUpdate Configuration")]
- [Description("The Url to download updates from.")]
- [DefaultValue("http://localhost/")]
- public string UpdateUrl
- {
- get
- {
- return _UpdateUrl;
- }
- set
- {
- _UpdateUrl = value;
- }
- }
- [Category("AppUpdate Configuration")]
- [Description("The way to detect new updates.")]
- [DefaultValue(ChangeDetectionModes.DirectFileCheck)]
- public ChangeDetectionModes ChangeDetectionMode
- {
- get
- {
- return _ChangeDetectionMode;
- }
- set
- {
- _ChangeDetectionMode = value;
- }
- }
- [Category("AppUpdate Configuration")]
- [Description("Determines whether the default UI is shown or supressed.")]
- [DefaultValue(false)]
- public bool ShowDefaultUI
- {
- get
- {
- return _ShowDefaultUI;
- }
- set
- {
- _ShowDefaultUI = value;
- }
- }
- [DefaultValue(false)]
- [Description("Enables auto-download of missing assemblies.")]
- [Category("AppUpdate Configuration")]
- public bool AutoFileLoad
- {
- get
- {
- return _AutoFileLoad;
- }
- set
- {
- _AutoFileLoad = value;
- }
- }
- public event CheckForUpdateEventHandler OnCheckForUpdate;
- public event UpdateDetectedEventHandler OnUpdateDetected;
- public event UpdateCompleteEventHandler OnUpdateComplete;
- public event NotifyUpdateFileInfoEventHandler OnNotifyUpdateFileInfo;
- public AppUpdater()
- {
- Poller = new ServerPoller(this);
- Downloader = new AppDownloader(this);
- }
- public AppUpdater(IContainer container)
- {
- Poller = new ServerPoller(this);
- Downloader = new AppDownloader(this);
- container.Add(this);
- InitializeComponent();
- }
- public AppUpdater(string updateUrl, ChangeDetectionModes changeDetectionMode, bool showDefaultUI, bool autoFileLoad, bool validateAssemblies)
- {
- Poller = new ServerPoller(this);
- Downloader = new AppDownloader(this);
- UpdateUrl = updateUrl;
- ChangeDetectionMode = changeDetectionMode;
- ShowDefaultUI = showDefaultUI;
- AutoFileLoad = autoFileLoad;
- Downloader.ValidateAssemblies = validateAssemblies;
- Initialize();
- }
- public void BeginInit()
- {
- }
- public void EndInit()
- {
- if (!base.DesignMode)
- {
- Initialize();
- }
- }
- private void InitializeComponent()
- {
- components = new Container();
- }
- public void Initialize()
- {
- string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\";
- string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location);
- fileNameWithoutExtension += ".xml";
- path = Path.Combine(path, fileNameWithoutExtension);
- Manifest = AppManifest.Load(path);
- if (ChangeDetectionMode == ChangeDetectionModes.DirectFileCheck)
- {
- EnableManifestGeneration();
- }
- if (AutoFileLoad)
- {
- EnableFileAutoLoad();
- }
- if (Poller.AutoStart)
- {
- Poller.Start();
- }
- Downloader.OnUpdateComplete += OnDownloaderComplete;
- Downloader.OnNotifyUpdateFileInfo += OnDownloaderUpdateFileInfo;
- Application.ApplicationExit += OnApplicationExit;
- EventControl = new Control();
- _ = EventControl.Handle;
- if (Manifest.State.Phase != 0)
- {
- Downloader.Start();
- }
- }
- public void DownloadUpdate()
- {
- Downloader.Start();
- }
- public bool CheckForUpdates()
- {
- bool flag = false;
- if (this.OnCheckForUpdate != null)
- {
- flag = this.OnCheckForUpdate(this, new EventArgs());
- }
- else if (ChangeDetectionMode == ChangeDetectionModes.ServerManifestCheck)
- {
- ServerManifest serverManifest = new ServerManifest();
- serverManifest.Load(UpdateUrl);
- flag = serverManifest.IsServerVersionNewer(GetLatestInstalledVersion());
- }
- else
- {
- foreach (object resource2 in Manifest.Resources.ResourceList)
- {
- Resource resource = (Resource)((DictionaryEntry)resource2).Value;
- string url = UpdateUrl + resource.Name;
- string filePath = resource.FilePath;
- if (WebFileLoader.CheckForFileUpdate(url, filePath))
- {
- flag = true;
- }
- }
- }
- if (this.OnUpdateDetected != null)
- {
- Delegate[] invocationList = this.OnUpdateDetected.GetInvocationList();
- for (int i = 0; i < invocationList.Length; i++)
- {
- UpdateDetectedEventHandler method = (UpdateDetectedEventHandler)invocationList[i];
- UpdateDetectedEventArgs updateDetectedEventArgs = new UpdateDetectedEventArgs();
- updateDetectedEventArgs.HasNewVersion = flag;
- EventControl.BeginInvoke(method, this, updateDetectedEventArgs);
- }
- }
- return flag;
- }
- public static Version GetLatestInstalledVersion()
- {
- string directoryName = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
- directoryName = Path.Combine(Directory.GetParent(directoryName).FullName, "AppStart.config");
- AppStartConfig appStartConfig = AppStartConfig.Load(directoryName);
- AssemblyName assemblyName = AssemblyName.GetAssemblyName(appStartConfig.AppExePath);
- return assemblyName.Version;
- }
- public void RestartApp()
- {
- Environment.ExitCode = 2;
- Application.Exit();
- Poller.Stop();
- Downloader.Stop();
- }
- private void OnDownloaderComplete(object sender, UpdateCompleteEventArgs args)
- {
- if (this.OnUpdateComplete != null)
- {
- Delegate[] invocationList = this.OnUpdateComplete.GetInvocationList();
- for (int i = 0; i < invocationList.Length; i++)
- {
- UpdateCompleteEventHandler method = (UpdateCompleteEventHandler)invocationList[i];
- EventControl.BeginInvoke(method, sender, args);
- }
- }
- EventControl.BeginInvoke(new UpdateCompleteEventHandler(UpdateCompleteOps), sender, args);
- }
- private void OnDownloaderUpdateFileInfo(object sender, NotifyUpdateFileInfoEventArgs args)
- {
- if (this.OnUpdateComplete != null)
- {
- Delegate[] invocationList = this.OnNotifyUpdateFileInfo.GetInvocationList();
- for (int i = 0; i < invocationList.Length; i++)
- {
- NotifyUpdateFileInfoEventHandler method = (NotifyUpdateFileInfoEventHandler)invocationList[i];
- EventControl.BeginInvoke(method, sender, args);
- }
- }
- }
- private void UpdateCompleteOps(object sender, UpdateCompleteEventArgs args)
- {
- if (!ShowDefaultUI)
- {
- return;
- }
- if (args.UpdateSucceeded)
- {
- UpdateForm updateForm = new UpdateForm();
- if (updateForm.ShowDialog() == DialogResult.Yes)
- {
- RestartApp();
- }
- }
- else
- {
- string text = "The auto-update of this application failed with the following error message: \r\n\r\n" + args.ErrorMessage + "\r\n\r\nTo correct this problem, try rebooting the computer & re-launching this application.";
- MessageBox.Show(text, "Application Update Failed", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
- }
- }
- private void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args)
- {
- string[] array = args.LoadedAssembly.Location.Split('\\');
- int num = array.Length - 1;
- string name = array[num];
- if (!Manifest.Resources.ResourceExists(name) && IsLocalAssembly(args.LoadedAssembly))
- {
- Resource resource = new Resource();
- resource.FilePath = args.LoadedAssembly.Location;
- resource.Name = name;
- resource.AddedAtRuntime = true;
- Manifest.Resources.AddResource(resource);
- Manifest.Update();
- }
- }
- private Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
- {
- if (LoadingAssembly)
- {
- return null;
- }
- LoadingAssembly = true;
- string[] array = args.Name.Split(new char[1]
- {
- ','
- }, 2);
- string text = array[0] + ".dll";
- string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, text);
- string text2;
- if (ChangeDetectionMode == ChangeDetectionModes.DirectFileCheck)
- {
- text2 = UpdateUrl + text;
- }
- else
- {
- ServerManifest serverManifest = new ServerManifest();
- serverManifest.Load(UpdateUrl);
- text2 = Path.Combine(serverManifest.ApplicationUrl, text);
- }
- try
- {
- WebFileLoader.UpdateFile(text2, filePath);
- }
- catch (Exception)
- {
- if (ShowDefaultUI)
- {
- MessageBox.Show("Unable to auto-download the missing parts of the application from:\r\n" + text2 + "\r\n\r\nMake sure your connected to the network. If the problem persists re-install the application.");
- }
- return null;
- }
- try
- {
- return Assembly.Load(args.Name);
- }
- catch (Exception)
- {
- return null;
- }
- finally
- {
- LoadingAssembly = false;
- }
- }
- private bool IsLocalAssembly(Assembly assembly)
- {
- string text = assembly.Location.Replace("/", "\\").ToLower(new CultureInfo("en-US"));
- string text2 = AppDomain.CurrentDomain.BaseDirectory.ToLower(new CultureInfo("en-US"));
- if (text.StartsWith(text2.ToLower(new CultureInfo("en-US"))) && !assembly.FullName.StartsWith("AppManager"))
- {
- return true;
- }
- return false;
- }
- private void OnApplicationExit(object sender, EventArgs args)
- {
- Poller.Stop();
- Downloader.Stop();
- }
- private void EnableFileAutoLoad()
- {
- AppDomain currentDomain = AppDomain.CurrentDomain;
- currentDomain.AssemblyResolve += OnAssemblyResolve;
- }
- private void DisableFileAutoLoad()
- {
- AppDomain currentDomain = AppDomain.CurrentDomain;
- currentDomain.AssemblyResolve -= OnAssemblyResolve;
- }
- private void EnableManifestGeneration()
- {
- AppDomain currentDomain = AppDomain.CurrentDomain;
- currentDomain.AssemblyLoad += OnAssemblyLoad;
- Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
- for (int i = 0; i < assemblies.Length; i++)
- {
- if (IsLocalAssembly(assemblies[i]))
- {
- Resource resource = new Resource();
- string[] array = assemblies[i].Location.Split('\\');
- int num = array.Length - 1;
- resource.FilePath = assemblies[i].Location;
- resource.Name = array[num];
- resource.AddedAtRuntime = true;
- Manifest.Resources.AddResource(resource);
- Manifest.Update();
- }
- }
- }
- private void DisableManifestGeneration()
- {
- AppDomain currentDomain = AppDomain.CurrentDomain;
- currentDomain.AssemblyLoad -= OnAssemblyLoad;
- }
- }
- }
|