Move update message logic into common

This commit is contained in:
2014-11-22 09:13:42 -05:00
parent 1050f83eae
commit 446bcaffb8
4 changed files with 317 additions and 15 deletions

View File

@@ -147,6 +147,11 @@
<ItemGroup>
<Compile Include="DateTimeExtensions.cs" />
<Compile Include="IO\ProcessAsync.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Security.cs" />
<Compile Include="Trace\BeginEndTracer.cs" />
<Compile Include="Extensions\Extensions.cs" />
@@ -204,6 +209,13 @@
<ItemGroup>
<None Include="ChrisKaczor.pfx" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
<ProjectExtensions>
<VisualStudio>

103
Properties/Resources.Designer.cs generated Normal file
View File

@@ -0,0 +1,103 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34014
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Common.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Common.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to An update to version {0} is now available..
/// </summary>
internal static string UpdateAvailable {
get {
return ResourceManager.GetString("UpdateAvailable", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You are already running the most recent version.
///
///No updates are available at this time..
/// </summary>
internal static string UpdateCheckCurrent {
get {
return ResourceManager.GetString("UpdateCheckCurrent", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Version {1} of {0} is now available.
///
///Would you like to download and install it now?.
/// </summary>
internal static string UpdateCheckNewVersion {
get {
return ResourceManager.GetString("UpdateCheckNewVersion", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} Update.
/// </summary>
internal static string UpdateCheckTitle {
get {
return ResourceManager.GetString("UpdateCheckTitle", resourceCulture);
}
}
}
}

136
Properties/Resources.resx Normal file
View File

@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="UpdateCheckNewVersion" xml:space="preserve">
<value>Version {1} of {0} is now available.
Would you like to download and install it now?</value>
</data>
<data name="UpdateCheckCurrent" xml:space="preserve">
<value>You are already running the most recent version.
No updates are available at this time.</value>
</data>
<data name="UpdateCheckTitle" xml:space="preserve">
<value>{0} Update</value>
</data>
<data name="UpdateAvailable" xml:space="preserve">
<value>An update to version {0} is now available.</value>
</data>
</root>

View File

@@ -1,4 +1,5 @@
using System;
using Common.Properties;
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
@@ -9,28 +10,36 @@ namespace Common.Update
{
public static class UpdateCheck
{
private static string _server;
public delegate void ApplicationShutdownDelegate();
public delegate void ApplicationCurrentMessageDelegate(string title, string message);
public delegate bool ApplicationUpdateMessageDelegate(string title, string message);
public static VersionInfo VersionInfo { get; private set; }
public static ApplicationShutdownDelegate ApplicationShutdown = null;
public static ApplicationCurrentMessageDelegate ApplicationCurrentMessage = null;
public static ApplicationUpdateMessageDelegate ApplicationUpdateMessage = null;
public static string UpdateServer;
public static string UpdateFile;
public static string ApplicationName { get; set; }
public static VersionInfo RemoteVersion { get; private set; }
public static string LocalInstallFile { get; private set; }
public static bool UpdateAvailable { get; private set; }
public static Version CurrentVersion
public static Version LocalVersion
{
get { return Assembly.GetExecutingAssembly().GetName().Version; }
}
public static bool CheckForUpdate(string server, string file)
public static bool CheckForUpdate()
{
_server = server;
RemoteVersion = VersionInfo.Load(UpdateServer, UpdateFile);
VersionInfo = VersionInfo.Load(_server, file);
if (VersionInfo == null)
if (RemoteVersion == null)
return false;
var serverVersion = VersionInfo.Version;
var localVersion = CurrentVersion;
var serverVersion = RemoteVersion.Version;
var localVersion = LocalVersion;
UpdateAvailable = serverVersion > localVersion;
@@ -39,12 +48,12 @@ namespace Common.Update
public static async Task<bool> DownloadUpdate()
{
if (VersionInfo == null)
if (RemoteVersion == null)
return false;
var remoteFile = _server + VersionInfo.InstallFile;
var remoteFile = UpdateServer + RemoteVersion.InstallFile;
LocalInstallFile = Path.Combine(Path.GetTempPath(), VersionInfo.InstallFile);
LocalInstallFile = Path.Combine(Path.GetTempPath(), RemoteVersion.InstallFile);
var webClient = new WebClient();
@@ -55,12 +64,54 @@ namespace Common.Update
public static bool InstallUpdate()
{
if (VersionInfo == null)
if (RemoteVersion == null)
return false;
Process.Start(LocalInstallFile, "/passive");
return true;
}
public static async void DisplayUpdateInformation(bool showIfCurrent)
{
CheckForUpdate();
// Check for an update
if (UpdateAvailable)
{
// Load the version string from the server
var serverVersion = RemoteVersion.Version;
// Format the check title
var updateCheckTitle = string.Format(Resources.UpdateCheckTitle, ApplicationName);
// Format the message
var updateCheckMessage = string.Format(Resources.UpdateCheckNewVersion, ApplicationName, serverVersion);
// Ask the user to update
if (ApplicationUpdateMessage(updateCheckTitle, updateCheckMessage))
return;
// Get the update
await DownloadUpdate();
// Start to install the update
InstallUpdate();
// Restart the application
ApplicationShutdown();
}
else if (showIfCurrent)
{
// Format the check title
var updateCheckTitle = string.Format(Resources.UpdateCheckTitle, ApplicationName);
// Format the message
var updateCheckMessage = string.Format(Resources.UpdateCheckCurrent, ApplicationName);
ApplicationCurrentMessage(updateCheckTitle, updateCheckMessage);
}
}
}
}