Browse Source

Automatic check for updates.

pull/1/head
Daniel Grunwald 15 years ago
parent
commit
c0e39ae490
  1. 115
      ILSpy/AboutPage.cs
  2. 11
      ILSpy/MainWindow.xaml
  3. 43
      ILSpy/MainWindow.xaml.cs

115
ILSpy/AboutPage.cs

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -9,6 +10,7 @@ using System.Net; @@ -9,6 +10,7 @@ using System.Net;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Xml;
using System.Xml.Linq;
@ -41,6 +43,8 @@ namespace ICSharpCode.ILSpy @@ -41,6 +43,8 @@ namespace ICSharpCode.ILSpy
CheckBox checkBox = new CheckBox();
checkBox.Margin = new Thickness(4);
checkBox.Content = "Automatically check for updates every week";
UpdateSettings settings = new UpdateSettings(ILSpySettings.Load());
checkBox.SetBinding(CheckBox.IsCheckedProperty, new Binding("AutomaticUpdateCheckEnabled") { Source = settings });
return new StackPanel {
Margin = new Thickness(0, 4, 0, 0),
Cursor = Cursors.Arrow,
@ -69,10 +73,9 @@ namespace ICSharpCode.ILSpy @@ -69,10 +73,9 @@ namespace ICSharpCode.ILSpy
button.Click += delegate {
button.Content = "Checking...";
button.IsEnabled = false;
GetLatestVersion().ContinueWith(
GetLatestVersionAsync().ContinueWith(
delegate (Task<AvailableVersionInfo> task) {
try {
latestAvailableVersion = task.Result;
stackPanel.Children.Clear();
ShowAvailableVersion(latestAvailableVersion, stackPanel);
} catch (Exception ex) {
@ -84,9 +87,10 @@ namespace ICSharpCode.ILSpy @@ -84,9 +87,10 @@ namespace ICSharpCode.ILSpy
};
}
static readonly Version currentVersion = new Version(RevisionClass.Major + "." + RevisionClass.Minor + "." + RevisionClass.Build + "." + RevisionClass.Revision);
static void ShowAvailableVersion(AvailableVersionInfo availableVersion, StackPanel stackPanel)
{
Version currentVersion = new Version(RevisionClass.Major + "." + RevisionClass.Minor + "." + RevisionClass.Build + "." + RevisionClass.Revision);
if (currentVersion == availableVersion.Version) {
stackPanel.Children.Add(
new Image {
@ -106,9 +110,7 @@ namespace ICSharpCode.ILSpy @@ -106,9 +110,7 @@ namespace ICSharpCode.ILSpy
Margin = new Thickness(0,0,8,0),
VerticalAlignment = VerticalAlignment.Bottom
});
if (availableVersion.DownloadUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase)
|| availableVersion.DownloadUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
if (availableVersion.DownloadUrl != null) {
Button button = new Button();
button.Content = "Download";
button.Cursor = Cursors.Arrow;
@ -122,7 +124,7 @@ namespace ICSharpCode.ILSpy @@ -122,7 +124,7 @@ namespace ICSharpCode.ILSpy
}
}
static Task<AvailableVersionInfo> GetLatestVersion()
static Task<AvailableVersionInfo> GetLatestVersionAsync()
{
var tcs = new TaskCompletionSource<AvailableVersionInfo>();
WebClient wc = new WebClient();
@ -135,8 +137,12 @@ namespace ICSharpCode.ILSpy @@ -135,8 +137,12 @@ namespace ICSharpCode.ILSpy
var bands = doc.Root.Elements("band");
var currentBand = bands.FirstOrDefault(b => (string)b.Attribute("id") == "stable") ?? bands.First();
Version version = new Version((string)currentBand.Element("latestVersion"));
version = new Version(1,0,0,0);
string url = (string)currentBand.Element("downloadUrl");
tcs.SetResult(new AvailableVersionInfo { Version = version, DownloadUrl = url });
if (!(url.StartsWith("http://", StringComparison.Ordinal) || url.StartsWith("https://", StringComparison.Ordinal)))
url = null; // don't accept non-urls
latestAvailableVersion = new AvailableVersionInfo { Version = version, DownloadUrl = url };
tcs.SetResult(latestAvailableVersion);
} catch (Exception ex) {
tcs.SetException(ex);
}
@ -151,5 +157,98 @@ namespace ICSharpCode.ILSpy @@ -151,5 +157,98 @@ namespace ICSharpCode.ILSpy
public Version Version;
public string DownloadUrl;
}
sealed class UpdateSettings : INotifyPropertyChanged
{
public UpdateSettings(ILSpySettings spySettings)
{
XElement s = spySettings["UpdateSettings"];
this.automaticUpdateCheckEnabled = (bool?)s.Element("AutomaticUpdateCheckEnabled") ?? true;
this.LastSuccessfulUpdateCheck = (DateTime?)s.Element("LastSuccessfulUpdateCheck");
}
bool automaticUpdateCheckEnabled;
public bool AutomaticUpdateCheckEnabled {
get { return automaticUpdateCheckEnabled; }
set {
if (automaticUpdateCheckEnabled != value) {
automaticUpdateCheckEnabled = value;
Save();
OnPropertyChanged("AutomaticUpdateCheckEnabled");
}
}
}
DateTime? lastSuccessfulUpdateCheck;
public DateTime? LastSuccessfulUpdateCheck {
get { return lastSuccessfulUpdateCheck; }
set {
if (lastSuccessfulUpdateCheck != value) {
lastSuccessfulUpdateCheck = value;
Save();
OnPropertyChanged("LastSuccessfulUpdateCheck");
}
}
}
public void Save()
{
ILSpySettings.SaveSettings(new XElement(
"UpdateSettings",
new XElement("AutomaticUpdateCheckEnabled", automaticUpdateCheckEnabled),
new XElement("LastSuccessfulUpdateCheck", this.LastSuccessfulUpdateCheck)
));
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
/// <summary>
/// If automatic update checking is enabled, checks if there are any updates available.
/// Returns the download URL if an update is available.
/// Returns null if no update is available, or if no check was performed.
/// </summary>
public static Task<string> CheckForUpdatesIfEnabledAsync(ILSpySettings spySettings)
{
var tcs = new TaskCompletionSource<string>();
UpdateSettings s = new UpdateSettings(spySettings);
if (s.AutomaticUpdateCheckEnabled) {
// perform update check if we never did one before;
// or if the last check wasn't in the past 7 days
if (s.LastSuccessfulUpdateCheck == null
|| s.LastSuccessfulUpdateCheck < DateTime.UtcNow.AddDays(-7)
|| s.LastSuccessfulUpdateCheck > DateTime.UtcNow)
{
GetLatestVersionAsync().ContinueWith(
delegate (Task<AvailableVersionInfo> task) {
try {
s.LastSuccessfulUpdateCheck = DateTime.UtcNow;
AvailableVersionInfo v = task.Result;
if (v.Version > currentVersion)
tcs.SetResult(v.DownloadUrl);
else
tcs.SetResult(null);
} catch (AggregateException) {
// ignore errors getting the version info
tcs.SetResult(null);
}
});
} else {
tcs.SetResult(null);
}
} else {
tcs.SetResult(null);
}
return tcs.Task;
}
}
}

11
ILSpy/MainWindow.xaml

@ -134,6 +134,17 @@ @@ -134,6 +134,17 @@
<!-- Right pane: Text Editor -->
<DockPanel
Grid.Column="2">
<Border BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top" Name="updateAvailablePanel" Visibility="Collapsed">
<DockPanel>
<Button DockPanel.Dock="Right" Click="updateAvailablePanelCloseButtonClick" MinWidth="0">X</Button>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="4,0" VerticalAlignment="Center">A new ILSpy version is available.</TextBlock>
<Button Click="downloadUpdateButtonClick">Download</Button>
</StackPanel>
</DockPanel>
</Border>
<textView:DecompilerTextView x:Name="decompilerTextView" />
</DockPanel>
</Grid>

43
ILSpy/MainWindow.xaml.cs

@ -22,10 +22,10 @@ using System.ComponentModel; @@ -22,10 +22,10 @@ using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.FlowAnalysis;
using ICSharpCode.ILSpy.TreeNodes;
@ -77,10 +77,12 @@ namespace ICSharpCode.ILSpy @@ -77,10 +77,12 @@ namespace ICSharpCode.ILSpy
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
ILSpySettings spySettings = this.spySettings;
this.spySettings = null;
// Load AssemblyList only in Loaded event so that WPF is initialized before we start the CPU-heavy stuff.
// This makes the UI come up a bit faster.
this.assemblyList = assemblyListManager.LoadList(this.spySettings, sessionSettings.ActiveAssemblyList);
this.spySettings = null;
this.assemblyList = assemblyListManager.LoadList(spySettings, sessionSettings.ActiveAssemblyList);
ShowAssemblyList(this.assemblyList);
@ -92,11 +94,42 @@ namespace ICSharpCode.ILSpy @@ -92,11 +94,42 @@ namespace ICSharpCode.ILSpy
LoadInitialAssemblies();
SharpTreeNode node = FindNodeByPath(sessionSettings.ActiveTreeViewPath, true);
if (node != null)
if (node != null) {
SelectNode(node);
else
// only if not showing the about page, perform the update check:
ShowMessageIfUpdatesAvailableAsync(spySettings);
} else {
AboutPage.Display(decompilerTextView);
}
}
#region Update Check
string updateAvailableDownloadUrl;
void ShowMessageIfUpdatesAvailableAsync(ILSpySettings spySettings)
{
AboutPage.CheckForUpdatesIfEnabledAsync(spySettings).ContinueWith(
delegate (Task<string> task) {
if (task.Result != null) {
updateAvailableDownloadUrl = task.Result;
updateAvailablePanel.Visibility = Visibility.Visible;
}
},
TaskScheduler.FromCurrentSynchronizationContext()
);
}
void updateAvailablePanelCloseButtonClick(object sender, RoutedEventArgs e)
{
updateAvailablePanel.Visibility = Visibility.Collapsed;
}
void downloadUpdateButtonClick(object sender, RoutedEventArgs e)
{
Process.Start(updateAvailableDownloadUrl);
}
#endregion
void ShowAssemblyList(AssemblyList assemblyList)
{

Loading…
Cancel
Save