From e0b9a81c9b12de226b8428d93ed916095e818798 Mon Sep 17 00:00:00 2001 From: bao-qian Date: Sat, 7 May 2016 22:44:38 +0100 Subject: [PATCH] Installer + auto update on startup 1. installer 2. auto check update on startup 3. auto start on next startup 4. remove command line arguments which breaks squirrel 5. auto generate installer on continue integration --- Deploy/{build-release.ps1 => binary_zip.ps1} | 4 +- Deploy/nuget.ps1 | 6 +- Deploy/squirrel_installer.ps1 | 15 +++ Deploy/wox.nuspec | 16 +++ Deploy/wox.plugin.nuspec | 2 +- SolutionAssemblyInfo.cs | 6 +- Wox.Infrastructure/Wox.cs | 1 + Wox/App.xaml | 4 +- Wox/App.xaml.cs | 101 +++++++++++-------- Wox/CommandArgs/CommandArgsFactory.cs | 3 +- Wox/Helper/SingleInstance.cs | 48 ++------- Wox/PublicAPIInstance.cs | 8 +- Wox/Wox.csproj | 44 +++++++- Wox/packages.config | 5 +- appveyor.yml | 19 ++-- 15 files changed, 171 insertions(+), 111 deletions(-) rename Deploy/{build-release.ps1 => binary_zip.ps1} (82%) create mode 100644 Deploy/squirrel_installer.ps1 create mode 100644 Deploy/wox.nuspec diff --git a/Deploy/build-release.ps1 b/Deploy/binary_zip.ps1 similarity index 82% rename from Deploy/build-release.ps1 rename to Deploy/binary_zip.ps1 index ec0dca4089..712eebb3eb 100644 --- a/Deploy/build-release.ps1 +++ b/Deploy/binary_zip.ps1 @@ -1,8 +1,8 @@ $sourceDirectoryName = $env:APPVEYOR_BUILD_FOLDER + "\Output\Release" $fileName = $env:APPVEYOR_BUILD_FOLDER + "\Wox-$env:APPVEYOR_BUILD_VERSION.zip" -$current_path = Convert-Path . -Write-Host "Current path: " + $current_path +$currentPath = Convert-Path . +Write-Host "Current path: " + $currentPath Write-Host "Target path: " + $sourceDirectoryName [Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") diff --git a/Deploy/nuget.ps1 b/Deploy/nuget.ps1 index 63418d798a..363566475b 100644 --- a/Deploy/nuget.ps1 +++ b/Deploy/nuget.ps1 @@ -1,7 +1,7 @@ $path = $env:APPVEYOR_BUILD_FOLDER + "\Deploy\wox.plugin.nuspec" -$current_path = Convert-Path . -Write-Host "Current path: " + $current_path -Write-Host "Target path: " + $path +$currentPath = Convert-Path . +Write-Host "Current path:" + $currentPath +Write-Host "nuspec path:" + $path & nuget pack $path -Version $env:APPVEYOR_BUILD_VERSION diff --git a/Deploy/squirrel_installer.ps1 b/Deploy/squirrel_installer.ps1 new file mode 100644 index 0000000000..9c1d010d1f --- /dev/null +++ b/Deploy/squirrel_installer.ps1 @@ -0,0 +1,15 @@ +$currentPath = Convert-Path . +Write-Host "Current path: " + $currentPath + +$path = $env:APPVEYOR_BUILD_FOLDER + "\Deploy\wox.nuspec" +Write-Host "nuspec path: " + $path +& nuget.exe pack $path -Version $env:APPVEYOR_BUILD_VERSION -Properties Configuration=Release + +$nupkgPath = $env:APPVEYOR_BUILD_FOLDER + "\Wox." + $env:APPVEYOR_BUILD_VERSION + ".nupkg" +Write-Host "nupkg path: " + $nupkgPath + +# must use Squirrel.com, Squirrel.exe will produce nothing +$squirrelPath = $env:APPVEYOR_BUILD_FOLDER + "\packages\squirrel*\tools\Squirrel.com" +Write-Host "squirrel path: " + $squirrelPath +$iconPath = $env:APPVEYOR_BUILD_FOLDER + "\Wox\Resources\app.ico" +& $squirrelPath --releasify $nupkgPath --setupIcon $iconPath --no-msi diff --git a/Deploy/wox.nuspec b/Deploy/wox.nuspec new file mode 100644 index 0000000000..448cc8ea35 --- /dev/null +++ b/Deploy/wox.nuspec @@ -0,0 +1,16 @@ + + + + Wox + Wox + $version$ + happlebao + https://github.com/Wox-launcher/Wox + https://raw.githubusercontent.com/Wox-launcher/Wox/master/Wox/Images/app.png + false + Wox - a launcher for windows + + + + + diff --git a/Deploy/wox.plugin.nuspec b/Deploy/wox.plugin.nuspec index d090bc9c5c..d88c91af8c 100644 --- a/Deploy/wox.plugin.nuspec +++ b/Deploy/wox.plugin.nuspec @@ -11,6 +11,6 @@ wox - + diff --git a/SolutionAssemblyInfo.cs b/SolutionAssemblyInfo.cs index e900203594..980e82176d 100644 --- a/SolutionAssemblyInfo.cs +++ b/SolutionAssemblyInfo.cs @@ -9,12 +9,12 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("Release build, https://github.com/Wox-launcher/Wox")] #endif -[assembly: AssemblyCompany("Wox-launcher")] +[assembly: AssemblyCompany("Wox")] [assembly: AssemblyProduct("Wox")] [assembly: AssemblyCopyright("The MIT License (MIT)")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] [assembly: AssemblyVersion("1.2.0")] -[assembly: AssemblyFileVersion("1.2.0.0")] -[assembly: AssemblyInformationalVersion("1.2-beta.2")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.2.0")] +[assembly: AssemblyInformationalVersion("1.2.0")] \ No newline at end of file diff --git a/Wox.Infrastructure/Wox.cs b/Wox.Infrastructure/Wox.cs index 94a5c45db5..3e04189dac 100644 --- a/Wox.Infrastructure/Wox.cs +++ b/Wox.Infrastructure/Wox.cs @@ -15,5 +15,6 @@ namespace Wox.Infrastructure public static readonly string UserDirectory = Path.Combine(DataPath, Plugins); public static readonly string PreinstalledDirectory = Path.Combine(ProgramPath, Plugins); public static readonly string SettingsPath = Path.Combine(DataPath, Settings); + public const string Github = "https://github.com/Wox-launcher/Wox"; } } diff --git a/Wox/App.xaml b/Wox/App.xaml index d7c5a879e3..1d7493d271 100644 --- a/Wox/App.xaml +++ b/Wox/App.xaml @@ -1,8 +1,8 @@  + Startup="OnStartup" + Activated="OnActivated"> diff --git a/Wox/App.xaml.cs b/Wox/App.xaml.cs index 0855fd8117..842bd91a40 100644 --- a/Wox/App.xaml.cs +++ b/Wox/App.xaml.cs @@ -1,43 +1,43 @@ using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; using System.Windows; -using Wox.CommandArgs; +using Squirrel; using Wox.Core.Plugin; using Wox.Helper; using Wox.Infrastructure.Image; using Wox.ViewModel; using Stopwatch = Wox.Infrastructure.Stopwatch; +using Wox.Infrastructure.Logger; namespace Wox { - public partial class App : ISingleInstanceApp + public partial class App : ISingleInstanceApp, IDisposable { private const string Unique = "Wox_Unique_Application_Mutex"; public static MainWindow Window { get; private set; } public static PublicAPIInstance API { get; private set; } - private bool _saved; + private static bool _disposed; + public static UpdateManager Updater; [STAThread] public static void Main() { + RegisterAppDomainUnhandledException(); if (SingleInstance.InitializeAsFirstInstance(Unique)) { - var application = new App(); - application.InitializeComponent(); - application.Run(); - SingleInstance.Cleanup(); + using (var application = new App()) + { + application.InitializeComponent(); + application.Run(); + } } } - protected override void OnStartup(StartupEventArgs e) + private void OnStartup(object sender, StartupEventArgs e) { Stopwatch.Debug("Startup Time", () => { - base.OnStartup(e); - RegisterUnhandledException(); + RegisterDispatcherUnhandledException(); ImageLoader.PreloadImages(); @@ -47,53 +47,72 @@ namespace Wox PluginManager.InitializePlugins(API, pluginsSettings); Window = new MainWindow(mainVM._settings, mainVM); - NotifyIconManager notifyIconManager = new NotifyIconManager(API); - CommandArgsFactory.Execute(e.Args.ToList()); + var _notifyIconManager = new NotifyIconManager(API); + + RegisterExitEvents(); }); } - [Conditional("RELEASE")] - private void RegisterUnhandledException() + private async void OnActivated(object sender, EventArgs e) { - // let exception throw as normal is better for Debug + try + { + using (Updater = await UpdateManager.GitHubUpdateManager(Infrastructure.Wox.Github, prerelease: true)) + { + await Updater.UpdateApp(); + } + } + catch (Exception exception) + { + Log.Error(exception); + } + } + + private void RegisterExitEvents() + { + AppDomain.CurrentDomain.ProcessExit += (s, e) => Dispose(); + Current.Exit += (s, e) => Dispose(); + Current.SessionEnding += (s, e) => Dispose(); + } + [Conditional("RELEASE")] + private void RegisterDispatcherUnhandledException() + { + // let exception throw as normal is better for Debug DispatcherUnhandledException += ErrorReporting.DispatcherUnhandledException; + } + + [Conditional("RELEASE")] + private static void RegisterAppDomainUnhandledException() + { + // let exception throw as normal is better for Debug AppDomain.CurrentDomain.UnhandledException += ErrorReporting.UnhandledExceptionHandle; } - public void OnActivate(IList args) + public void OnActivate() { - if (args.Count > 0 && args[0] == SingleInstance.Restart) - { - API.CloseApp(); - } - else - { - CommandArgsFactory.Execute(args); - } + API.ShowApp(); } - private void OnExit(object sender, ExitEventArgs e) + private static void Save() { - Save(); + var vm = (MainViewModel)Window.DataContext; + vm.Save(); + PluginManager.Save(); + ImageLoader.Save(); + _disposed = true; } - private void OnSessionEnding(object sender, SessionEndingCancelEventArgs e) - { - Save(); - } - private void Save() + public void Dispose() { // if sessionending is called, exit proverbially be called when log off / shutdown // but if sessionending is not called, exit won't be called when log off / shutdown - if (!_saved) + if (!_disposed) { - var vm = (MainViewModel) Window.DataContext; - vm.Save(); - PluginManager.Save(); - ImageLoader.Save(); - _saved = true; + Save(); + Updater?.Dispose(); + SingleInstance.Cleanup(); } } } -} +} \ No newline at end of file diff --git a/Wox/CommandArgs/CommandArgsFactory.cs b/Wox/CommandArgs/CommandArgsFactory.cs index 14a3f99a72..2b7a7b8b5b 100644 --- a/Wox/CommandArgs/CommandArgsFactory.cs +++ b/Wox/CommandArgs/CommandArgsFactory.cs @@ -22,7 +22,8 @@ namespace Wox.CommandArgs public static void Execute(IList args) { // todo restart command line args? - if (args.Count > 0 && args[0] != SingleInstance.Restart) + //if (args.Count > 0 && args[0] != SingleInstance.Restart) + if (args.Count > 0) { string command = args[0]; ICommandArg cmd = commandArgs.FirstOrDefault(o => o.Command.ToLower() == command); diff --git a/Wox/Helper/SingleInstance.cs b/Wox/Helper/SingleInstance.cs index 58fe0adef4..b26f59d7dd 100644 --- a/Wox/Helper/SingleInstance.cs +++ b/Wox/Helper/SingleInstance.cs @@ -186,7 +186,7 @@ namespace Wox.Helper public interface ISingleInstanceApp { - void OnActivate(IList args); + void OnActivate(); } /// @@ -238,23 +238,10 @@ namespace Wox.Helper /// private static IpcServerChannel channel; - /// - /// List of command line arguments for the application. - /// - private static IList commandLineArgs; - #endregion #region Public Properties - /// - /// Gets list of command line arguments for the application. - /// - public static IList CommandLineArgs - { - get { return commandLineArgs; } - } - #endregion #region Public Methods @@ -266,10 +253,6 @@ namespace Wox.Helper /// True if this is the first instance of the application. public static bool InitializeAsFirstInstance( string uniqueName ) { - commandLineArgs = GetCommandLineArgs(uniqueName); - //remove execute path itself - commandLineArgs.RemoveAt(0); - // Build unique application Id and the IPC channel name. string applicationIdentifier = uniqueName + Environment.UserName; @@ -283,17 +266,9 @@ namespace Wox.Helper CreateRemoteService(channelName); return true; } - // Restart - else if (commandLineArgs.Count > 0 && commandLineArgs[0] == Restart) - { - SignalFirstInstance(channelName, commandLineArgs); - singleInstanceMutex.WaitOne(TimeSpan.FromSeconds(10)); - CreateRemoteService(channelName); - return true; - } else { - SignalFirstInstance(channelName, commandLineArgs); + SignalFirstInstance(channelName); return false; } } @@ -398,7 +373,7 @@ namespace Wox.Helper /// /// Command line arguments for the second instance, passed to the first instance to take appropriate action. /// - private static void SignalFirstInstance(string channelName, IList args) + private static void SignalFirstInstance(string channelName) { IpcClientChannel secondInstanceChannel = new IpcClientChannel(); ChannelServices.RegisterChannel(secondInstanceChannel, true); @@ -414,7 +389,7 @@ namespace Wox.Helper { // Invoke a method of the remote service exposed by the first instance passing on the command line // arguments and causing the first instance to activate itself - firstInstanceRemoteServiceReference.InvokeFirstInstance(args); + firstInstanceRemoteServiceReference.InvokeFirstInstance(); } } @@ -423,11 +398,9 @@ namespace Wox.Helper /// /// Callback argument. /// Always null. - private static object ActivateFirstInstanceCallback(object arg) + private static object ActivateFirstInstanceCallback(object o) { - // Get command line args to be passed to first instance - IList args = arg as IList; - ActivateFirstInstance(args); + ActivateFirstInstance(); return null; } @@ -435,7 +408,7 @@ namespace Wox.Helper /// Activates the first instance of the application with arguments from a second instance. /// /// List of arguments to supply the first instance of the application. - private static void ActivateFirstInstance(IList args) + private static void ActivateFirstInstance() { // Set main window state and process command line args if (Application.Current == null) @@ -443,7 +416,7 @@ namespace Wox.Helper return; } - ((TApplication)Application.Current).OnActivate(args); + ((TApplication)Application.Current).OnActivate(); } #endregion @@ -459,14 +432,13 @@ namespace Wox.Helper /// /// Activates the first instance of the application. /// - /// List of arguments to pass to the first instance. - public void InvokeFirstInstance(IList args) + public void InvokeFirstInstance() { if (Application.Current != null) { // Do an asynchronous call to ActivateFirstInstance function Application.Current.Dispatcher.BeginInvoke( - DispatcherPriority.Normal, new DispatcherOperationCallback(ActivateFirstInstanceCallback), args); + DispatcherPriority.Normal, new DispatcherOperationCallback(ActivateFirstInstanceCallback)); } } diff --git a/Wox/PublicAPIInstance.cs b/Wox/PublicAPIInstance.cs index 4bfbc41a38..500df1217d 100644 --- a/Wox/PublicAPIInstance.cs +++ b/Wox/PublicAPIInstance.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using System.Windows; using NHotkey; using NHotkey.Wpf; +using Squirrel; using Wox.Core.Plugin; using Wox.Core.Resource; using Wox.Core.UserSettings; @@ -67,12 +68,7 @@ namespace Wox public void RestarApp() { - ProcessStartInfo info = new ProcessStartInfo - { - FileName = Application.ResourceAssembly.Location, - Arguments = SingleInstance.Restart - }; - Process.Start(info); + UpdateManager.RestartApp(); } public void HideApp() diff --git a/Wox/Wox.csproj b/Wox/Wox.csproj index 9fb8646837..857b5d521c 100644 --- a/Wox/Wox.csproj +++ b/Wox/Wox.csproj @@ -60,6 +60,18 @@ Wox.App + + ..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.dll + True + + + ..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.MsDelta.dll + True + + + ..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.PatchApi.dll + True + ..\packages\Exceptionless.1.5.2121\lib\net45\Exceptionless.dll True @@ -68,16 +80,28 @@ ..\packages\Exceptionless.1.5.2121\lib\net45\Exceptionless.Models.dll True - - ..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll + + ..\packages\squirrel.windows.1.4.0\lib\Net45\ICSharpCode.SharpZipLib.dll True ..\packages\JetBrains.Annotations.10.1.4\lib\net20\JetBrains.Annotations.dll True - - ..\packages\MarkdownSharp.1.13.0.0\lib\35\MarkdownSharp.dll + + ..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.dll + True + + + ..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Mdb.dll + True + + + ..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Pdb.dll + True + + + ..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Rocks.dll True @@ -92,8 +116,20 @@ ..\packages\NHotkey.Wpf.1.2.1\lib\net35\NHotkey.Wpf.dll True + + ..\packages\squirrel.windows.1.4.0\lib\Net45\NuGet.Squirrel.dll + True + + + ..\packages\Splat.1.6.2\lib\Net45\Splat.dll + True + + + ..\packages\squirrel.windows.1.4.0\lib\Net45\Squirrel.dll + True + diff --git a/Wox/packages.config b/Wox/packages.config index d6785a0d70..e822764989 100644 --- a/Wox/packages.config +++ b/Wox/packages.config @@ -1,12 +1,15 @@  + - + + + \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index f51c57f9b9..437f7f60ef 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,16 +16,17 @@ after_test: - ps: >- .\Deploy\nuget.ps1 - .\Deploy\build-release.ps1 + .\Deploy\binary_zip.ps1 + + .\Deploy\squirrel_installer.ps1 artifacts: - path: 'Wox-*.zip' - name: release_binary + name: zipped_binary - path: '*.nupkg' name: nuget_package -deploy: -- provider: NuGet - api_key: - secure: yybUOFgBuGVpbmOVZxsurC8OpkClzt9dR+/54WpMWcq6b6oyMatciaelRPnXsjRn - artifact: nuget_package - on: - branch: api +- path: '\Releases\*.exe' + name: installer +- path: '\Releases\*.nupkg' + name: installer +- path: 'Releases\RELEASES' + name: installer \ No newline at end of file