public void EigenUpdateWithoutUpdateURL() { string dir; string outDir; using (Utility.WithTempDirectory(out outDir)) using (IntegrationTestHelper.WithFakeInstallDirectory(out dir)) { var di = new DirectoryInfo(dir); var progress = new Subject<int>(); var bundledRelease = ReleaseEntry.GenerateFromFile(di.GetFiles("*.nupkg").First().FullName); var fixture = new InstallManager(bundledRelease, outDir); var pkg = new ZipPackage(Path.Combine(dir, "SampleUpdatingApp.1.1.0.0.nupkg")); var progressValues = new List<int>(); progress.Subscribe(progressValues.Add); fixture.ExecuteInstall(dir, pkg, progress).Wait(); var filesToLookFor = new[] { "SampleUpdatingApp\\app-1.1.0.0\\SampleUpdatingApp.exe", "SampleUpdatingApp\\packages\\RELEASES", "SampleUpdatingApp\\packages\\SampleUpdatingApp.1.1.0.0.nupkg", }; filesToLookFor.ForEach(f => Assert.True(File.Exists(Path.Combine(outDir, f)), "Could not find file: " + f)); // Progress should be monotonically increasing progressValues.Count.ShouldBeGreaterThan(2); progressValues.Zip(progressValues.Skip(1), (prev, cur) => cur - prev).All(x => x > 0).ShouldBeTrue(); } }
public WixUiBootstrapper(IWiXEvents wixEvents, TinyIoCContainer testKernel = null, IRoutingState router = null, IFileSystemFactory fileSystem = null, string currentAssemblyDir = null) { Kernel = testKernel ?? createDefaultKernel(); this.fileSystem = fileSystem ?? AnonFileSystem.Default; this.currentAssemblyDir = currentAssemblyDir ?? Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); RxApp.ConfigureServiceLocator( (type, contract) => String.IsNullOrEmpty(contract) ? Kernel.Resolve(type) : Kernel.Resolve(type, contract), (type, contract) => Kernel.ResolveAll(type, true), (c, t, s) => { if (String.IsNullOrEmpty(s)) { Kernel.Register(t, c, Guid.NewGuid().ToString()); } else { Kernel.Register(t, c, s); } }); RxRouting.ViewModelToViewFunc = findViewClassNameForViewModelName; Kernel.Register<IWixUiBootstrapper>(this); Kernel.Register<IScreen>(this); Kernel.Register(wixEvents); Router = router ?? new RoutingState(); WiXEvents = wixEvents; _BundledRelease = new Lazy<ReleaseEntry>(readBundledReleasesFile); registerExtensionDlls(Kernel); UserError.RegisterHandler(ex => { if (wixEvents.DisplayMode != Display.Full) { this.Log().Error(ex.ErrorMessage); wixEvents.ShouldQuit(); } var errorVm = RxApp.GetService<IErrorViewModel>(); errorVm.Error = ex; RxApp.DeferredScheduler.Schedule(() => Router.Navigate.Execute(errorVm)); return Observable.Return(RecoveryOptionResult.CancelOperation); }); bundledPackageMetadata = new Lazy<IPackage>(openBundledPackage); wixEvents.DetectPackageCompleteObs.Subscribe(eventArgs => { var error = convertHResultToError(eventArgs.Status); if (error != null) { UserError.Throw(error); return; } if (wixEvents.Action == LaunchAction.Uninstall) { var uninstallVm = RxApp.GetService<IUninstallingViewModel>(); Router.Navigate.Execute(uninstallVm); wixEvents.Engine.Plan(LaunchAction.Uninstall); return; } // TODO: If the app is already installed, run it and bail // If Display is silent, we should just exit here. if (wixEvents.Action == LaunchAction.Install) { if (wixEvents.DisplayMode != Display.Full) { wixEvents.Engine.Plan(LaunchAction.Install); return; } var welcomeVm = RxApp.GetService<IWelcomeViewModel>(); welcomeVm.PackageMetadata = bundledPackageMetadata.Value; welcomeVm.ShouldProceed.Subscribe(_ => wixEvents.Engine.Plan(LaunchAction.Install)); // NB: WiX runs a "Main thread" that all of these events // come back on, and a "UI thread" where it actually runs // the WPF window. Gotta proxy to the UI thread. RxApp.DeferredScheduler.Schedule(() => Router.Navigate.Execute(welcomeVm)); } }); var executablesToStart = Enumerable.Empty<string>(); wixEvents.PlanCompleteObs.Subscribe(eventArgs => { var installManager = new InstallManager(BundledRelease); var error = convertHResultToError(eventArgs.Status); if (error != null) { UserError.Throw(error); return; } if (wixEvents.Action == LaunchAction.Uninstall) { installManager.ExecuteUninstall().Subscribe( _ => wixEvents.Engine.Apply(wixEvents.MainWindowHwnd), ex => UserError.Throw(new UserError("Failed to uninstall", ex.Message, innerException: ex))); return; } IObserver<int> progress = null; if (wixEvents.DisplayMode == Display.Full) { var installingVm = RxApp.GetService<IInstallingViewModel>(); progress = installingVm.ProgressValue; installingVm.PackageMetadata = bundledPackageMetadata.Value; RxApp.DeferredScheduler.Schedule(() => Router.Navigate.Execute(installingVm)); } installManager.ExecuteInstall(this.currentAssemblyDir, bundledPackageMetadata.Value, progress).Subscribe( toStart => { executablesToStart = toStart ?? executablesToStart; wixEvents.Engine.Apply(wixEvents.MainWindowHwnd); }, ex => UserError.Throw("Failed to install application", ex)); }); wixEvents.ApplyCompleteObs.Subscribe(eventArgs => { var error = convertHResultToError(eventArgs.Status); if (error != null) { UserError.Throw(error); return; } if (wixEvents.DisplayMode == Display.Full && wixEvents.Action == LaunchAction.Install) { foreach (var path in executablesToStart) { Process.Start(path); } } wixEvents.ShouldQuit(); }); wixEvents.ErrorObs.Subscribe(eventArgs => UserError.Throw("An installation error has occurred: " + eventArgs.ErrorMessage)); wixEvents.Engine.Detect(); }
public WixUiBootstrapper( IWiXEvents wixEvents, TinyIoCContainer testKernel = null, IRoutingState router = null, IFileSystemFactory fileSystem = null, string currentAssemblyDir = null, string targetRootDirectory = null) { Kernel = testKernel ?? createDefaultKernel(); this.fileSystem = fileSystem ?? AnonFileSystem.Default; this.currentAssemblyDir = currentAssemblyDir ?? Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); RxApp.ConfigureServiceLocator( (type, contract) => { this.Log().Debug("Resolving type '{0}' with contract '{1}'", type, contract); return String.IsNullOrEmpty(contract) ? Kernel.Resolve(type) : Kernel.Resolve(type, contract); }, (type, contract) => Kernel.ResolveAll(type, true), (c, t, s) => { this.Log().Debug("Registering type '{0}' for interface '{1}' and contract '{2}'", c, t, s); if (String.IsNullOrEmpty(s)) { Kernel.Register(t, c, Guid.NewGuid().ToString()); } else { Kernel.Register(t, c, s); } }); RxRouting.ViewModelToViewFunc = findViewClassNameForViewModelName; Kernel.Register<IWixUiBootstrapper>(this); Kernel.Register<IScreen>(this); Kernel.Register(wixEvents); Router = router ?? new RoutingState(); WiXEvents = wixEvents; _BundledRelease = new Lazy<ReleaseEntry>(readBundledReleasesFile); registerExtensionDlls(Kernel); UserError.RegisterHandler(ex => { this.Log().ErrorException("Something unexpected happened", ex.InnerException); if (wixEvents.DisplayMode != Display.Full) { this.Log().Error(ex.ErrorMessage); wixEvents.ShouldQuit(); } var errorVm = RxApp.GetService<IErrorViewModel>(); errorVm.Error = ex; errorVm.Shutdown.Subscribe(_ => wixEvents.ShouldQuit()); errorVm.OpenLogsFolder.Subscribe(_ => openLogsFolder()); RxApp.DeferredScheduler.Schedule(() => Router.Navigate.Execute(errorVm)); return Observable.Return(RecoveryOptionResult.CancelOperation); }); bundledPackageMetadata = new Lazy<IPackage>(openBundledPackage); wixEvents.DetectPackageCompleteObs.Subscribe(eventArgs => { this.Log().Info("DetectPackageCompleteObs: got id: '{0}', state: '{1}', status: '{2}'", eventArgs.PackageId, eventArgs.State, eventArgs.Status); var error = convertHResultToError(eventArgs.Status); if (error != null) { UserError.Throw(error); return; } if (wixEvents.Action == LaunchAction.Uninstall) { if (wixEvents.DisplayMode != Display.Full) { this.Log().Info("Shimmer is doing a silent uninstall! Sneaky!"); wixEvents.Engine.Plan(LaunchAction.Uninstall); return; } this.Log().Info("Shimmer is doing an uninstall! Sadface!"); var uninstallVm = RxApp.GetService<IUninstallingViewModel>(); Router.Navigate.Execute(uninstallVm); wixEvents.Engine.Plan(LaunchAction.Uninstall); return; } // TODO: If the app is already installed, run it and bail // If Display is silent, we should just exit here. if (wixEvents.Action == LaunchAction.Install) { if (wixEvents.DisplayMode != Display.Full) { this.Log().Info("Shimmer is doing a silent install! Sneaky!"); wixEvents.Engine.Plan(LaunchAction.Install); return; } this.Log().Info("We are doing an UI install! Huzzah!"); var welcomeVm = RxApp.GetService<IWelcomeViewModel>(); welcomeVm.PackageMetadata = bundledPackageMetadata.Value; welcomeVm.ShouldProceed.Subscribe(_ => wixEvents.Engine.Plan(LaunchAction.Install)); // NB: WiX runs a "Main thread" that all of these events // come back on, and a "UI thread" where it actually runs // the WPF window. Gotta proxy to the UI thread. RxApp.DeferredScheduler.Schedule(() => Router.Navigate.Execute(welcomeVm)); } }); var executablesToStart = Enumerable.Empty<string>(); wixEvents.PlanCompleteObs.Subscribe(eventArgs => { this.Log().Info("PlanCompleteObs: got status: '{0}'", eventArgs.Status); var installManager = new InstallManager(BundledRelease, targetRootDirectory); var error = convertHResultToError(eventArgs.Status); if (error != null) { UserError.Throw(error); return; } if (wixEvents.Action == LaunchAction.Uninstall) { var task = installManager.ExecuteUninstall(BundledRelease.Version); task.Subscribe( _ => wixEvents.Engine.Apply(wixEvents.MainWindowHwnd), ex => UserError.Throw(new UserError("Failed to uninstall", ex.Message, innerException: ex))); // the installer can close before the uninstall is done // which means the UpdateManager is not disposed correctly // which means an error is thrown in the destructor // // let's wait for it to finish // // oh, and .Wait() is unnecesary here // because the subscriber handles an exception var result = task.FirstOrDefault(); return; } IObserver<int> progress = null; if (wixEvents.DisplayMode == Display.Full) { var installingVm = RxApp.GetService<IInstallingViewModel>(); progress = installingVm.ProgressValue; installingVm.PackageMetadata = bundledPackageMetadata.Value; RxApp.DeferredScheduler.Schedule(() => Router.Navigate.Execute(installingVm)); } installManager.ExecuteInstall(this.currentAssemblyDir, bundledPackageMetadata.Value, progress).Subscribe( toStart => { executablesToStart = toStart ?? executablesToStart; wixEvents.Engine.Apply(wixEvents.MainWindowHwnd); }, ex => UserError.Throw("Failed to install application", ex)); }); wixEvents.ApplyCompleteObs.Subscribe(eventArgs => { this.Log().Info("ApplyCompleteObs: got restart: '{0}', result: '{1}', status: '{2}'", eventArgs.Restart, eventArgs.Result, eventArgs.Status); var error = convertHResultToError(eventArgs.Status); if (error != null) { UserError.Throw(error); return; } if (wixEvents.DisplayMode == Display.Full && wixEvents.Action == LaunchAction.Install) { var processFactory = Kernel.Resolve<IProcessFactory>(); foreach (var path in executablesToStart) { processFactory.Start(path); } } wixEvents.ShouldQuit(); }); wixEvents.ErrorObs.Subscribe( eventArgs => { this.Log().Info("ErrorObs: got id: '{0}', result: '{1}', code: '{2}'", eventArgs.PackageId, eventArgs.Result, eventArgs.ErrorCode); UserError.Throw("An installation error has occurred: " + eventArgs.ErrorMessage); }); wixEvents.Engine.Detect(); }
public void InstallWithContentInPackageDropsInSameFolder() { string dir; string outDir; var package = "ProjectWithContent.1.0.0.0-beta-full.nupkg"; using (Utility.WithTempDirectory(out outDir)) using (IntegrationTestHelper.WithFakeInstallDirectory(package, out dir)) { try { var di = new DirectoryInfo(dir); var bundledRelease = ReleaseEntry.GenerateFromFile(di.GetFiles("*.nupkg").First().FullName); var fixture = new InstallManager(bundledRelease, outDir); var pkg = new ZipPackage(Path.Combine(dir, package)); fixture.ExecuteInstall(dir, pkg).Wait(); var filesToLookFor = new[] { "ProjectWithContent\\app-1.0.0.0\\project-with-content.exe", "ProjectWithContent\\app-1.0.0.0\\some-words.txt", "ProjectWithContent\\app-1.0.0.0\\dir\\item-in-subdirectory.txt", "ProjectWithContent\\packages\\RELEASES", "ProjectWithContent\\packages\\ProjectWithContent.1.0.0.0-beta-full.nupkg", }; filesToLookFor.ForEach(f => Assert.True(File.Exists(Path.Combine(outDir, f)), "Could not find file: " + f)); } finally { Directory.Delete(dir, true); } } }
public void UninstallRemovesEverything() { string dir; string appDir; using (IntegrationTestHelper.WithFakeInstallDirectory(out dir)) using (IntegrationTestHelper.WithFakeAlreadyInstalledApp(out appDir)) { var di = new DirectoryInfo(dir); var progress = new Subject<int>(); var bundledRelease = ReleaseEntry.GenerateFromFile(di.GetFiles("*.nupkg").First().FullName); var fixture = new InstallManager(bundledRelease, appDir); var progressValues = new List<int>(); progress.Subscribe(progressValues.Add); fixture.ExecuteUninstall().First(); di = new DirectoryInfo(appDir); di.GetDirectories().Any().ShouldBeFalse(); di.GetFiles().Any().ShouldBeFalse(); } }
public void UninstallDoesntCrashOnMissingAppDirectory() { string dir; string appDir; InstallManager fixture; using (IntegrationTestHelper.WithFakeInstallDirectory(out dir)) using (IntegrationTestHelper.WithFakeAlreadyInstalledApp(out appDir)) { var di = new DirectoryInfo(dir); var bundledRelease = ReleaseEntry.GenerateFromFile(di.GetFiles("*.nupkg").First().FullName); fixture = new InstallManager(bundledRelease, appDir); } fixture.ExecuteUninstall().First(); }