diff --git a/src/CreateReleasePackage/CreateReleasePackage.csproj b/src/CreateReleasePackage/CreateReleasePackage.csproj
index 9fa08efa..53fd5b91 100644
--- a/src/CreateReleasePackage/CreateReleasePackage.csproj
+++ b/src/CreateReleasePackage/CreateReleasePackage.csproj
@@ -9,7 +9,7 @@
Properties
CreateReleasePackage
CreateReleasePackage
- v4.0
+ v4.5
512
..\
true
@@ -28,6 +28,7 @@
false
false
true
+
AnyCPU
@@ -38,6 +39,7 @@
DEBUG;TRACE
prompt
4
+ false
AnyCPU
@@ -47,6 +49,7 @@
TRACE
prompt
4
+ false
diff --git a/src/CreateReleasePackage/app.config b/src/CreateReleasePackage/app.config
index 118c7c04..50db73bb 100644
--- a/src/CreateReleasePackage/app.config
+++ b/src/CreateReleasePackage/app.config
@@ -1,19 +1,19 @@
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
\ No newline at end of file
+
diff --git a/src/SampleUpdatingApp/Properties/Resources.Designer.cs b/src/SampleUpdatingApp/Properties/Resources.Designer.cs
index b4c28fe6..afe705c9 100644
--- a/src/SampleUpdatingApp/Properties/Resources.Designer.cs
+++ b/src/SampleUpdatingApp/Properties/Resources.Designer.cs
@@ -1,17 +1,17 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.17626
+// Runtime Version:4.0.30319.34003
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
-namespace SampleUpdatingApp.Properties
-{
-
-
+namespace SampleUpdatingApp.Properties {
+ using System;
+
+
///
/// A strongly-typed resource class, for looking up localized strings, etc.
///
@@ -22,48 +22,40 @@ namespace SampleUpdatingApp.Properties
[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
- {
-
+ 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()
- {
+ internal Resources() {
}
-
+
///
/// Returns the cached ResourceManager instance used by this class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager
- {
- get
- {
- if ((resourceMan == null))
- {
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleUpdatingApp.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
-
+
///
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture
- {
- get
- {
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
return resourceCulture;
}
- set
- {
+ set {
resourceCulture = value;
}
}
diff --git a/src/SampleUpdatingApp/Properties/Settings.Designer.cs b/src/SampleUpdatingApp/Properties/Settings.Designer.cs
index 9aeeb9ed..7becbdbe 100644
--- a/src/SampleUpdatingApp/Properties/Settings.Designer.cs
+++ b/src/SampleUpdatingApp/Properties/Settings.Designer.cs
@@ -1,28 +1,24 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.17626
+// Runtime Version:4.0.30319.34003
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
-namespace SampleUpdatingApp.Properties
-{
-
-
+namespace SampleUpdatingApp.Properties {
+
+
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
- internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
- {
-
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
-
- public static Settings Default
- {
- get
- {
+
+ public static Settings Default {
+ get {
return defaultInstance;
}
}
diff --git a/src/SampleUpdatingApp/SampleUpdatingApp.csproj b/src/SampleUpdatingApp/SampleUpdatingApp.csproj
index 60401c2b..e9ae1aac 100644
--- a/src/SampleUpdatingApp/SampleUpdatingApp.csproj
+++ b/src/SampleUpdatingApp/SampleUpdatingApp.csproj
@@ -9,12 +9,13 @@
Properties
SampleUpdatingApp
SampleUpdatingApp
- v4.0
+ v4.5
512
{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
4
..\
true
+
AnyCPU
@@ -25,6 +26,7 @@
DEBUG;TRACE
prompt
4
+ false
AnyCPU
@@ -34,6 +36,7 @@
TRACE
prompt
4
+ false
diff --git a/src/SampleUpdatingApp/app.config b/src/SampleUpdatingApp/app.config
index cdd95f8d..b0100b8b 100644
--- a/src/SampleUpdatingApp/app.config
+++ b/src/SampleUpdatingApp/app.config
@@ -1,24 +1,24 @@
-
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
\ No newline at end of file
+
diff --git a/src/Squirrel.Client/InstallManager.cs b/src/Squirrel.Client/InstallManager.cs
index fb7faee9..371f21b0 100644
--- a/src/Squirrel.Client/InstallManager.cs
+++ b/src/Squirrel.Client/InstallManager.cs
@@ -67,7 +67,7 @@ public IObservable> ExecuteInstall(string currentAssemblyDir, IPack
return updateUsingDeltas;
}
- Task> executeInstall(
+ async Task> executeInstall(
string currentAssemblyDir,
IPackage bundledPackageMetadata,
bool ignoreDeltaUpdates = false,
@@ -83,7 +83,13 @@ Task> executeInstall(
var realCopyFileProgress = new Subject();
var realApplyProgress = new Subject();
- var eigenUpdateObs = Observable.Using(() => new UpdateManager(currentAssemblyDir, bundledPackageMetadata.Id, fxVersion, TargetRootDirectory), eigenUpdater => {
+ List ret = null;
+
+ using (var eigenUpdater = new UpdateManager(
+ currentAssemblyDir,
+ bundledPackageMetadata.Id,
+ fxVersion,
+ TargetRootDirectory)) {
// The real update takes longer than the eigenupdate because we're
// downloading from the Internet instead of doing everything
// locally, so give it more weight
@@ -95,57 +101,65 @@ Task> executeInstall(
.Select(x => (int) x)
.Subscribe(progress);
- var updateInfoObs = eigenUpdater.CheckForUpdate(ignoreDeltaUpdates, eigenCheckProgress);
-
- return updateInfoObs.SelectMany(updateInfo => {
- log.Info("The checking of releases completed - and there was much rejoicing");
+ var updateInfo = await eigenUpdater.CheckForUpdate(ignoreDeltaUpdates, eigenCheckProgress);
- if (!updateInfo.ReleasesToApply.Any()) {
+ log.Info("The checking of releases completed - and there was much rejoicing");
- var rootDirectory = TargetRootDirectory ?? Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
+ if (!updateInfo.ReleasesToApply.Any()) {
- var version = updateInfo.CurrentlyInstalledVersion;
- var releaseFolder = String.Format("app-{0}", version.Version);
- var absoluteFolder = Path.Combine(rootDirectory, version.PackageName, releaseFolder);
+ var rootDirectory = TargetRootDirectory ?? Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
- if (!Directory.Exists(absoluteFolder)) {
- log.Warn("executeInstall: the directory {0} doesn't exist - cannot find the current app?!!?");
- } else {
- return Observable.Return(
- Directory.GetFiles(absoluteFolder, "*.exe", SearchOption.TopDirectoryOnly).ToList());
- }
- }
+ var version = updateInfo.CurrentlyInstalledVersion;
+ var releaseFolder = String.Format("app-{0}", version.Version);
+ var absoluteFolder = Path.Combine(rootDirectory, version.PackageName, releaseFolder);
- foreach (var u in updateInfo.ReleasesToApply) {
- log.Info("HEY! We should be applying update {0}", u.Filename);
+ if (!Directory.Exists(absoluteFolder)) {
+ log.Warn("executeInstall: the directory {0} doesn't exist - cannot find the current app?!!?");
+ } else {
+ return Directory.GetFiles(absoluteFolder, "*.exe", SearchOption.TopDirectoryOnly)
+ .ToList();
}
+ }
- return eigenUpdater.DownloadReleases(updateInfo.ReleasesToApply, eigenCopyFileProgress)
- .Do(_ => log.Info("The downloading of releases completed - and there was much rejoicing"))
- .SelectMany(_ => eigenUpdater.ApplyReleases(updateInfo, eigenApplyProgress))
- .Do(_ => log.Info("The applying of releases completed - and there was much rejoicing"));
- });
- });
-
- return eigenUpdateObs.SelectMany(ret => {
- var updateUrl = bundledPackageMetadata.ProjectUrl != null ? bundledPackageMetadata.ProjectUrl.ToString() : null;
- updateUrl = null; //XXX REMOVE ME
- if (updateUrl == null) {
- realCheckProgress.OnNext(100); realCheckProgress.OnCompleted();
- realCopyFileProgress.OnNext(100); realCopyFileProgress.OnCompleted();
- realApplyProgress.OnNext(100); realApplyProgress.OnCompleted();
+ foreach (var u in updateInfo.ReleasesToApply) {
+ log.Info("HEY! We should be applying update {0}", u.Filename);
+ }
- return Observable.Return(ret);
+ await eigenUpdater.DownloadReleases(updateInfo.ReleasesToApply, eigenCopyFileProgress);
+
+ log.Info("The downloading of releases completed - and there was much rejoicing");
+
+ ret = await eigenUpdater.ApplyReleases(updateInfo, eigenApplyProgress);
+
+ log.Info("The applying of releases completed - and there was much rejoicing");
+ }
+
+ var updateUrl = bundledPackageMetadata.ProjectUrl != null ? bundledPackageMetadata.ProjectUrl.ToString() : null;
+ updateUrl = null; //XXX REMOVE ME
+ if (updateUrl == null) {
+ realCheckProgress.OnNext(100); realCheckProgress.OnCompleted();
+ realCopyFileProgress.OnNext(100); realCopyFileProgress.OnCompleted();
+ realApplyProgress.OnNext(100); realApplyProgress.OnCompleted();
+
+ return ret;
+ }
+
+ using(var realUpdater = new UpdateManager(
+ updateUrl,
+ bundledPackageMetadata.Id,
+ fxVersion,
+ TargetRootDirectory)) {
+ try {
+ var updateInfo = await realUpdater.CheckForUpdate(progress: realCheckProgress);
+ await realUpdater.DownloadReleases(updateInfo.ReleasesToApply, realCopyFileProgress);
+ await realUpdater.ApplyReleases(updateInfo, realApplyProgress);
+ } catch (Exception ex) {
+ log.ErrorException("Failed to update to latest remote version", ex);
+ return new List();
}
+ }
- return Observable.Using(() => new UpdateManager(updateUrl, bundledPackageMetadata.Id, fxVersion, TargetRootDirectory), realUpdater => {
- return realUpdater.CheckForUpdate(progress: realCheckProgress)
- .SelectMany(x => realUpdater.DownloadReleases(x.ReleasesToApply, realCopyFileProgress).Select(_ => x))
- .SelectMany(x => realUpdater.ApplyReleases(x, realApplyProgress))
- .Select(_ => ret)
- .LoggedCatch(this, Observable.Return(new List()), "Failed to update to latest remote version");
- });
- }).ToTask();
+ return ret;
}
public IObservable ExecuteUninstall(Version version = null)
diff --git a/src/Squirrel.Client/Squirrel.Client.csproj b/src/Squirrel.Client/Squirrel.Client.csproj
index 71d934a6..5250eb90 100644
--- a/src/Squirrel.Client/Squirrel.Client.csproj
+++ b/src/Squirrel.Client/Squirrel.Client.csproj
@@ -10,11 +10,12 @@
Properties
Squirrel.Client
Squirrel.Client
- v4.0
+ v4.5
512
..\..\src\
true
0
+
true
@@ -58,6 +59,7 @@
Full
Build
0
+ false
pdbonly
@@ -66,6 +68,7 @@
TRACE
prompt
4
+ false
@@ -138,12 +141,8 @@
-
- Designer
-
-
- Designer
-
+
+
Designer
diff --git a/src/Squirrel.Client/UpdateManager.cs b/src/Squirrel.Client/UpdateManager.cs
index 4c56d48f..af221da6 100644
--- a/src/Squirrel.Client/UpdateManager.cs
+++ b/src/Squirrel.Client/UpdateManager.cs
@@ -192,6 +192,11 @@ IObservable downloadReleases(IEnumerable releasesToDownload,
}
public IObservable> ApplyReleases(UpdateInfo updateInfo, IObserver progress = null)
+ {
+ return acquireUpdateLock().SelectMany(_ => applyReleases(updateInfo, progress).ToObservable());
+ }
+
+ async Task> applyReleases(UpdateInfo updateInfo, IObserver progress = null)
{
progress = progress ?? new Subject();
@@ -199,24 +204,25 @@ public IObservable> ApplyReleases(UpdateInfo updateInfo, IObserver<
// once the entire operation has completed, even though we technically
// could do it after DownloadUpdates finishes. We do this so that if
// we get interrupted / killed during this operation, we'll start over
- return Observable.Using(_ => acquireUpdateLock().ToTask(), (dontcare, ct) => {
- var obs = cleanDeadVersions(updateInfo.CurrentlyInstalledVersion != null ? updateInfo.CurrentlyInstalledVersion.Version : null)
- .Do(_ => progress.OnNext(10))
- .SelectMany(_ => createFullPackagesFromDeltas(updateInfo.ReleasesToApply, updateInfo.CurrentlyInstalledVersion))
- .Do(_ => progress.OnNext(50))
- .Select(release => installPackageToAppDir(updateInfo, release))
- .Do(_ => progress.OnNext(95))
- .SelectMany(ret => UpdateLocalReleasesFile().Select(_ => ret))
- .Finally(() => progress.OnCompleted())
- .PublishLast();
-
- obs.Connect();
-
- // NB: This overload of Using is high as a kite.
- var tcs = new TaskCompletionSource>>();
- tcs.SetResult(obs);
- return tcs.Task;
- });
+
+ var ret = default(List);
+ try {
+ await cleanDeadVersions(updateInfo.CurrentlyInstalledVersion != null ? updateInfo.CurrentlyInstalledVersion.Version : null);
+ progress.OnNext(10);
+
+ var release = await createFullPackagesFromDeltas(updateInfo.ReleasesToApply, updateInfo.CurrentlyInstalledVersion);
+ progress.OnNext(50);
+
+ ret = await Observable.Start(() => installPackageToAppDir(updateInfo, release), RxApp.TaskpoolScheduler);
+ progress.OnNext(95);
+
+ await UpdateLocalReleasesFile();
+ progress.OnNext(100);
+ } finally {
+ progress.OnCompleted();
+ }
+
+ return ret;
}
public IObservable UpdateLocalReleasesFile()
diff --git a/src/Squirrel.Client/app.config b/src/Squirrel.Client/app.config
index c5c407bd..e5eb4927 100644
--- a/src/Squirrel.Client/app.config
+++ b/src/Squirrel.Client/app.config
@@ -1,4 +1,4 @@
-
+
-
\ No newline at end of file
+
diff --git a/src/Squirrel.Core/ReactiveUIMicro/Rx-Shim/AwaitableAsyncSubject.cs b/src/Squirrel.Core/ReactiveUIMicro/Rx-Shim/AwaitableAsyncSubject.cs
new file mode 100644
index 00000000..f1021f3d
--- /dev/null
+++ b/src/Squirrel.Core/ReactiveUIMicro/Rx-Shim/AwaitableAsyncSubject.cs
@@ -0,0 +1,342 @@
+#define HAS_AWAIT
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive.Disposables;
+using System.Reactive.Subjects;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading;
+
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+
+/* This file is substantially copied from http://rx.codeplex.com/SourceControl/changeset/view/ef6a42709f49#Rx.NET/System.Reactive.Linq/Reactive/Subjects/AsyncSubject.cs
+ * Check LICENSE in this folder for licensing information */
+
+namespace ReactiveUIMicro
+{
+ ///
+ /// Represents the result of an asynchronous operation.
+ /// The last value before the OnCompleted notification, or the error received through OnError, is sent to all subscribed observers.
+ ///
+ /// The type of the elements processed by the subject.
+ public sealed class AwaitableAsyncSubject : ISubject, IDisposable , INotifyCompletion
+ {
+ private readonly object _gate = new object();
+
+ private ImmutableList> _observers;
+ private bool _isDisposed;
+ private bool _isStopped;
+ private T _value;
+ private bool _hasValue;
+ private Exception _exception;
+
+ ///
+ /// Creates a subject that can only receive one value and that value is cached for all future observations.
+ ///
+ public AwaitableAsyncSubject()
+ {
+ _observers = new ImmutableList>();
+ }
+
+ ///
+ /// Notifies all subscribed observers about the end of the sequence, also causing the last received value to be sent out (if any).
+ ///
+ public void OnCompleted()
+ {
+ var os = default(IObserver[]);
+
+ var v = default(T);
+ var hv = false;
+ lock (_gate)
+ {
+ CheckDisposed();
+
+ if (!_isStopped)
+ {
+ os = _observers.Data;
+ _observers = new ImmutableList>();
+ _isStopped = true;
+ v = _value;
+ hv = _hasValue;
+ }
+ }
+
+ if (os != null)
+ {
+ if (hv)
+ {
+ foreach (var o in os)
+ {
+ o.OnNext(v);
+ o.OnCompleted();
+ }
+ }
+ else
+ foreach (var o in os)
+ o.OnCompleted();
+ }
+ }
+
+ ///
+ /// Notifies all subscribed observers about the exception.
+ ///
+ /// The exception to send to all observers.
+ /// is null.
+ public void OnError(Exception error)
+ {
+ if (error == null)
+ throw new ArgumentNullException("error");
+
+ var os = default(IObserver[]);
+ lock (_gate)
+ {
+ CheckDisposed();
+
+ if (!_isStopped)
+ {
+ os = _observers.Data;
+ _observers = new ImmutableList>();
+ _isStopped = true;
+ _exception = error;
+ }
+ }
+
+ if (os != null)
+ foreach (var o in os)
+ o.OnError(error);
+ }
+
+ ///
+ /// Sends a value to the subject. The last value received before successful termination will be sent to all subscribed and future observers.
+ ///
+ /// The value to store in the subject.
+ public void OnNext(T value)
+ {
+ lock (_gate)
+ {
+ CheckDisposed();
+
+ if (!_isStopped)
+ {
+ _value = value;
+ _hasValue = true;
+ }
+ }
+ }
+
+ ///
+ /// Subscribes an observer to the subject.
+ ///
+ /// Observer to subscribe to the subject.
+ /// Disposable object that can be used to unsubscribe the observer from the subject.
+ /// is null.
+ public IDisposable Subscribe(IObserver observer)
+ {
+ if (observer == null)
+ throw new ArgumentNullException("observer");
+
+ var ex = default(Exception);
+ var v = default(T);
+ var hv = false;
+
+ lock (_gate)
+ {
+ CheckDisposed();
+
+ if (!_isStopped)
+ {
+ _observers = _observers.Add(observer);
+ return new Subscription(this, observer);
+ }
+
+ ex = _exception;
+ hv = _hasValue;
+ v = _value;
+ }
+
+ if (ex != null)
+ observer.OnError(ex);
+ else if (hv)
+ {
+ observer.OnNext(v);
+ observer.OnCompleted();
+ }
+ else
+ observer.OnCompleted();
+
+ return Disposable.Empty;
+ }
+
+ class Subscription : IDisposable
+ {
+ private readonly AwaitableAsyncSubject _subject;
+ private IObserver _observer;
+
+ public Subscription(AwaitableAsyncSubject subject, IObserver observer)
+ {
+ _subject = subject;
+ _observer = observer;
+ }
+
+ public void Dispose()
+ {
+ if (_observer != null)
+ {
+ lock (_subject._gate)
+ {
+ if (!_subject._isDisposed && _observer != null)
+ {
+ _subject._observers = _subject._observers.Remove(_observer);
+ _observer = null;
+ }
+ }
+ }
+ }
+ }
+
+ void CheckDisposed()
+ {
+ if (_isDisposed)
+ throw new ObjectDisposedException(string.Empty);
+ }
+
+ ///
+ /// Unsubscribe all observers and release resources.
+ ///
+ public void Dispose()
+ {
+ lock (_gate)
+ {
+ _isDisposed = true;
+ _observers = null;
+ _exception = null;
+ _value = default(T);
+ }
+ }
+
+#if HAS_AWAIT
+ ///
+ /// Gets an awaitable object for the current AsyncSubject.
+ ///
+ /// Object that can be awaited.
+ public AwaitableAsyncSubject GetAwaiter()
+ {
+ return this;
+ }
+
+ ///
+ /// Specifies a callback action that will be invoked when the subject completes.
+ ///
+ /// Callback action that will be invoked when the subject completes.
+ /// is null.
+ public void OnCompleted(Action continuation)
+ {
+ if (continuation == null)
+ throw new ArgumentNullException("continuation");
+
+ OnCompleted(continuation, true);
+ }
+#endif
+
+ private void OnCompleted(Action continuation, bool originalContext)
+ {
+ //
+ // [OK] Use of unsafe Subscribe: this type's Subscribe implementation is safe.
+ //
+ this.Subscribe/*Unsafe*/(new AwaitObserver(continuation, originalContext));
+ }
+
+ class AwaitObserver : IObserver
+ {
+#if HAS_AWAIT
+ private readonly SynchronizationContext _context;
+#endif
+ private readonly Action _callback;
+
+ public AwaitObserver(Action callback, bool originalContext)
+ {
+#if HAS_AWAIT
+ if (originalContext)
+ _context = SynchronizationContext.Current;
+#else
+ System.Diagnostics.Debug.Assert(!originalContext);
+#endif
+
+ _callback = callback;
+ }
+
+ public void OnCompleted()
+ {
+ InvokeOnOriginalContext();
+ }
+
+ public void OnError(Exception error)
+ {
+ InvokeOnOriginalContext();
+ }
+
+ public void OnNext(T value)
+ {
+ }
+
+ private void InvokeOnOriginalContext()
+ {
+#if HAS_AWAIT
+ if (_context != null)
+ {
+ //
+ // No need for OperationStarted and OperationCompleted calls here;
+ // this code is invoked through await support and will have a way
+ // to observe its start/complete behavior, either through returned
+ // Task objects or the async method builder's interaction with the
+ // SynchronizationContext object.
+ //
+ _context.Post(c => ((Action)c)(), _callback);
+ }
+ else
+#endif
+ {
+ _callback();
+ }
+ }
+ }
+
+ ///
+ /// Gets whether the AsyncSubject has completed.
+ ///
+ public bool IsCompleted
+ {
+ get
+ {
+ return _isStopped;
+ }
+ }
+
+ ///
+ /// Gets the last element of the subject, potentially blocking until the subject completes successfully or exceptionally.
+ ///
+ /// The last element of the subject. Throws an InvalidOperationException if no element was received.
+ /// The source sequence is empty.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Await pattern for C# and VB compilers.")]
+ public T GetResult()
+ {
+ if (!_isStopped)
+ {
+ var e = new ManualResetEvent(false);
+ OnCompleted(() => e.Set(), false);
+ e.WaitOne();
+ }
+
+ if (_exception != null) {
+ throw new InvalidOperationException("AwaitableAsyncSubject.GetResult() is rethrowing an inner exception", _exception);
+ }
+
+ if (!_hasValue)
+ throw new InvalidOperationException("AwaitableAsyncSubject.GetResult() completed without having a result. That's bad.");
+
+ return _value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Squirrel.Core/ReactiveUIMicro/Rx-Shim/GetAwaiter.cs b/src/Squirrel.Core/ReactiveUIMicro/Rx-Shim/GetAwaiter.cs
new file mode 100644
index 00000000..c3d1a903
--- /dev/null
+++ b/src/Squirrel.Core/ReactiveUIMicro/Rx-Shim/GetAwaiter.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive.Disposables;
+using System.Reactive.Subjects;
+using System.Text;
+using System.Threading;
+
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+
+/* This file is substantially copied from http://rx.codeplex.com/SourceControl/changeset/view/ef6a42709f49#Rx.NET/System.Reactive.Linq/Reactive/Linq/QueryLanguage.Awaiter.cs
+ * Check LICENSE in this folder for licensing information */
+
+namespace ReactiveUIMicro
+{
+ public static class ObservableAwaiter
+ {
+ public static AwaitableAsyncSubject GetAwaiter(this IObservable source)
+ {
+ var s = new AwaitableAsyncSubject();
+ source.SubscribeSafe(s);
+ return s;
+ }
+
+ public static AwaitableAsyncSubject GetAwaiter(this IConnectableObservable source)
+ {
+ var s = new AwaitableAsyncSubject();
+ source.SubscribeSafe(s);
+ source.Connect();
+ return s;
+ }
+
+ public static AwaitableAsyncSubject RunAsync(this IObservable source, CancellationToken cancellationToken)
+ {
+ var s = new AwaitableAsyncSubject();
+
+ var cancel = new Action(() => s.OnError(new OperationCanceledException()));
+ if (cancellationToken.IsCancellationRequested)
+ {
+ cancel();
+ return s;
+ }
+
+ var d = source.SubscribeSafe(s);
+ cancellationToken.Register(d.Dispose);
+ cancellationToken.Register(cancel);
+
+ return s;
+ }
+
+ public static AwaitableAsyncSubject RunAsync(this IConnectableObservable source, CancellationToken cancellationToken)
+ {
+ var s = new AwaitableAsyncSubject();
+
+ var cancel = new Action(() => s.OnError(new OperationCanceledException()));
+ if (cancellationToken.IsCancellationRequested)
+ {
+ cancel();
+ return s;
+ }
+
+ var d = new CompositeDisposable(source.SubscribeSafe(s), source.Connect());
+ cancellationToken.Register(d.Dispose);
+ cancellationToken.Register(cancel);
+
+ return s;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Squirrel.Core/ReactiveUIMicro/Rx-Shim/ImmutableList.cs b/src/Squirrel.Core/ReactiveUIMicro/Rx-Shim/ImmutableList.cs
new file mode 100644
index 00000000..72a8e987
--- /dev/null
+++ b/src/Squirrel.Core/ReactiveUIMicro/Rx-Shim/ImmutableList.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+
+/* This file is substantially copied from http://rx.codeplex.com/SourceControl/changeset/view/ef6a42709f49#Rx.NET/System.Reactive.Core/Reactive/Internal/ImmutableList.cs
+ * Check LICENSE in this folder for licensing information */
+
+namespace ReactiveUIMicro
+{
+ internal class ImmutableList
+ {
+ T[] data;
+
+ public ImmutableList()
+ {
+ data = new T[0];
+ }
+
+ public ImmutableList(T[] data)
+ {
+ this.data = data;
+ }
+
+ public ImmutableList Add(T value)
+ {
+ var newData = new T[data.Length + 1];
+ Array.Copy(data, newData, data.Length);
+ newData[data.Length] = value;
+ return new ImmutableList(newData);
+ }
+
+ public ImmutableList Remove(T value)
+ {
+ var i = IndexOf(value);
+ if (i < 0)
+ return this;
+ var newData = new T[data.Length - 1];
+ Array.Copy(data, 0, newData, 0, i);
+ Array.Copy(data, i + 1, newData, i, data.Length - i - 1);
+ return new ImmutableList(newData);
+ }
+
+ public int IndexOf(T value)
+ {
+ for (var i = 0; i < data.Length; ++i)
+ if (data[i].Equals(value))
+ return i;
+ return -1;
+ }
+
+ public T[] Data
+ {
+ get { return data; }
+ }
+ }
+}
+
diff --git a/src/Squirrel.Core/ReactiveUIMicro/Rx-Shim/LICENSE b/src/Squirrel.Core/ReactiveUIMicro/Rx-Shim/LICENSE
new file mode 100644
index 00000000..a208c748
--- /dev/null
+++ b/src/Squirrel.Core/ReactiveUIMicro/Rx-Shim/LICENSE
@@ -0,0 +1,15 @@
+Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+Microsoft Open Technologies would like to thank its contributors, a list
+of whom are at http://rx.codeplex.com/wikipage?title=Contributors.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you
+may not use this file except in compliance with the License. You may
+obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+implied. See the License for the specific language governing permissions
+and limitations under the License.
\ No newline at end of file
diff --git a/src/Squirrel.Core/Squirrel.Core.csproj b/src/Squirrel.Core/Squirrel.Core.csproj
index 0a4e101a..b1478f4d 100644
--- a/src/Squirrel.Core/Squirrel.Core.csproj
+++ b/src/Squirrel.Core/Squirrel.Core.csproj
@@ -10,11 +10,12 @@
Properties
Squirrel.Core
Squirrel.Core
- v4.0
+ v4.5
512
..\..\src\
true
0
+
true
@@ -58,6 +59,7 @@
Full
Build
0
+ false
pdbonly
@@ -67,6 +69,7 @@
prompt
4
true
+ false
@@ -149,6 +152,9 @@
+
+
+
@@ -158,6 +164,7 @@
+
diff --git a/src/Squirrel.Core/app.config b/src/Squirrel.Core/app.config
index c5c407bd..e5eb4927 100644
--- a/src/Squirrel.Core/app.config
+++ b/src/Squirrel.Core/app.config
@@ -1,4 +1,4 @@
-
+
-
\ No newline at end of file
+
diff --git a/src/Squirrel.Tests/Squirrel.Tests.csproj b/src/Squirrel.Tests/Squirrel.Tests.csproj
index e763feb3..542f501d 100644
--- a/src/Squirrel.Tests/Squirrel.Tests.csproj
+++ b/src/Squirrel.Tests/Squirrel.Tests.csproj
@@ -10,11 +10,12 @@
Properties
Squirrel.Tests
Squirrel.Tests
- v4.0
+ v4.5
512
..\..\src\
true
0
+
true
@@ -58,6 +59,7 @@
%28none%29
0
true
+ false
pdbonly
@@ -66,6 +68,7 @@
TRACE
prompt
4
+ false
diff --git a/src/Squirrel.Tests/app.config b/src/Squirrel.Tests/app.config
index c5c407bd..e5eb4927 100644
--- a/src/Squirrel.Tests/app.config
+++ b/src/Squirrel.Tests/app.config
@@ -1,4 +1,4 @@
-
+
-
\ No newline at end of file
+
diff --git a/src/Squirrel.Updater/App.config b/src/Squirrel.Updater/App.config
index 4c77df1f..f80039e2 100644
--- a/src/Squirrel.Updater/App.config
+++ b/src/Squirrel.Updater/App.config
@@ -1,17 +1,17 @@
-
+
-
+
-
-
+
+
-
-
+
+
diff --git a/src/Squirrel.Updater/Squirrel.Updater.csproj b/src/Squirrel.Updater/Squirrel.Updater.csproj
index 0d03833d..d3eb1fcb 100644
--- a/src/Squirrel.Updater/Squirrel.Updater.csproj
+++ b/src/Squirrel.Updater/Squirrel.Updater.csproj
@@ -9,7 +9,7 @@
Properties
Squirrel.Updater
Squirrel.Updater
- v4.0
+ v4.5
512
..\
@@ -24,6 +24,7 @@
DEBUG;TRACE
prompt
4
+ false
AnyCPU
@@ -33,6 +34,7 @@
TRACE
prompt
4
+ false
diff --git a/src/Squirrel.WiXUi/Squirrel.WiXUi.csproj b/src/Squirrel.WiXUi/Squirrel.WiXUi.csproj
index 8aa786fb..04e06ad8 100644
--- a/src/Squirrel.WiXUi/Squirrel.WiXUi.csproj
+++ b/src/Squirrel.WiXUi/Squirrel.WiXUi.csproj
@@ -9,10 +9,11 @@
Properties
Squirrel.WiXUi
Squirrel.WiXUi
- v4.0
+ v4.5
512
..\
true
+
true
@@ -23,6 +24,7 @@
prompt
4
649
+ false
pdbonly
@@ -32,6 +34,7 @@
prompt
4
649
+ false
diff --git a/src/Squirrel.WiXUiClient/Squirrel.WiXUiClient.csproj b/src/Squirrel.WiXUiClient/Squirrel.WiXUiClient.csproj
index 5f5975f5..aea80e29 100644
--- a/src/Squirrel.WiXUiClient/Squirrel.WiXUiClient.csproj
+++ b/src/Squirrel.WiXUiClient/Squirrel.WiXUiClient.csproj
@@ -9,10 +9,11 @@
Properties
Squirrel.WiXUiClient
Squirrel.WiXUiClient
- v4.0
+ v4.5
512
..\
true
+
true
@@ -22,6 +23,7 @@
DEBUG;TRACE
prompt
4
+ false
pdbonly
@@ -30,6 +32,7 @@
TRACE
prompt
4
+ false
diff --git a/src/SquirrelIAppUpdateTestTarget/Properties/Resources.Designer.cs b/src/SquirrelIAppUpdateTestTarget/Properties/Resources.Designer.cs
index bd2a5593..f0762530 100644
--- a/src/SquirrelIAppUpdateTestTarget/Properties/Resources.Designer.cs
+++ b/src/SquirrelIAppUpdateTestTarget/Properties/Resources.Designer.cs
@@ -1,17 +1,17 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.17626
+// Runtime Version:4.0.30319.34003
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
-namespace SquirrelIAppUpdateTestTarget.Properties
-{
-
-
+namespace SquirrelIAppUpdateTestTarget.Properties {
+ using System;
+
+
///
/// A strongly-typed resource class, for looking up localized strings, etc.
///
@@ -22,48 +22,40 @@ namespace SquirrelIAppUpdateTestTarget.Properties
[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
- {
-
+ 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()
- {
+ internal Resources() {
}
-
+
///
/// Returns the cached ResourceManager instance used by this class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager
- {
- get
- {
- if ((resourceMan == null))
- {
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SquirrelIAppUpdateTestTarget.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
-
+
///
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture
- {
- get
- {
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
return resourceCulture;
}
- set
- {
+ set {
resourceCulture = value;
}
}
diff --git a/src/SquirrelIAppUpdateTestTarget/Properties/Settings.Designer.cs b/src/SquirrelIAppUpdateTestTarget/Properties/Settings.Designer.cs
index b1d344ea..de306b5f 100644
--- a/src/SquirrelIAppUpdateTestTarget/Properties/Settings.Designer.cs
+++ b/src/SquirrelIAppUpdateTestTarget/Properties/Settings.Designer.cs
@@ -1,28 +1,24 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.17626
+// Runtime Version:4.0.30319.34003
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
-namespace SquirrelIAppUpdateTestTarget.Properties
-{
-
-
+namespace SquirrelIAppUpdateTestTarget.Properties {
+
+
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
- internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
- {
-
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
-
- public static Settings Default
- {
- get
- {
+
+ public static Settings Default {
+ get {
return defaultInstance;
}
}
diff --git a/src/SquirrelIAppUpdateTestTarget/SquirrelIAppUpdateTestTarget.csproj b/src/SquirrelIAppUpdateTestTarget/SquirrelIAppUpdateTestTarget.csproj
index 0f3a2cb5..a242a30a 100644
--- a/src/SquirrelIAppUpdateTestTarget/SquirrelIAppUpdateTestTarget.csproj
+++ b/src/SquirrelIAppUpdateTestTarget/SquirrelIAppUpdateTestTarget.csproj
@@ -9,12 +9,13 @@
Properties
SquirrelIAppUpdateTestTarget
SquirrelIAppUpdateTestTarget
- v4.0
+ v4.5
512
{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
4
..\
true
+
AnyCPU
@@ -25,6 +26,7 @@
DEBUG;TRACE
prompt
4
+ false
AnyCPU
@@ -34,6 +36,7 @@
TRACE
prompt
4
+ false
diff --git a/src/SquirrelIAppUpdateTestTarget/app.config b/src/SquirrelIAppUpdateTestTarget/app.config
index 118c7c04..50db73bb 100644
--- a/src/SquirrelIAppUpdateTestTarget/app.config
+++ b/src/SquirrelIAppUpdateTestTarget/app.config
@@ -1,19 +1,19 @@
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
\ No newline at end of file
+