diff --git a/FeedBuilder/FeedBuilder.csproj b/FeedBuilder/FeedBuilder.csproj index aa6b2fd3..8fcafd30 100644 --- a/FeedBuilder/FeedBuilder.csproj +++ b/FeedBuilder/FeedBuilder.csproj @@ -12,7 +12,7 @@ FeedBuilder 512 WindowsForms - v2.0 + v3.5 1591 @@ -136,6 +136,7 @@ + SettingsSingleFileGenerator Settings.Designer.cs @@ -153,4 +154,4 @@ - + \ No newline at end of file diff --git a/FeedBuilder/Properties/Resources.Designer.cs b/FeedBuilder/Properties/Resources.Designer.cs index 8408bebd..12793502 100644 --- a/FeedBuilder/Properties/Resources.Designer.cs +++ b/FeedBuilder/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.269 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. diff --git a/FeedBuilder/Properties/Settings.Designer.cs b/FeedBuilder/Properties/Settings.Designer.cs index f7457cc0..263c0a84 100644 --- a/FeedBuilder/Properties/Settings.Designer.cs +++ b/FeedBuilder/Properties/Settings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.269 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -12,7 +12,7 @@ namespace FeedBuilder { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + [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()))); @@ -37,6 +37,7 @@ public string BaseURL { } [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Configuration.SettingsProviderAttribute(typeof(FeedBuilder.FeedBuilderSettingsProvider))] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("True")] public bool CleanUp { @@ -142,6 +143,9 @@ public bool IgnoreDebugSymbols { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.SettingsProviderAttribute(typeof(FeedBuilder.FeedBuilderSettingsProvider))] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("\r\n\r\n *.pdb\r\n *.config\r\n")] public global::System.Collections.Specialized.StringCollection IgnoreFiles { get { return ((global::System.Collections.Specialized.StringCollection)(this["IgnoreFiles"])); diff --git a/FeedBuilder/app.config b/FeedBuilder/app.config new file mode 100644 index 00000000..2fa6e95d --- /dev/null +++ b/FeedBuilder/app.config @@ -0,0 +1,3 @@ + + + diff --git a/src/NAppUpdate.Framework/NAppUpdate.Framework.csproj b/src/NAppUpdate.Framework/NAppUpdate.Framework.csproj index b1ac3823..555394ac 100644 --- a/src/NAppUpdate.Framework/NAppUpdate.Framework.csproj +++ b/src/NAppUpdate.Framework/NAppUpdate.Framework.csproj @@ -10,7 +10,7 @@ Properties NAppUpdate.Framework NAppUpdate.Framework - v2.0 + v3.5 512 true NAppUpdate.snk @@ -33,6 +33,7 @@ false false true + true @@ -101,6 +102,7 @@ + diff --git a/src/NAppUpdate.Framework/UpdateManager.cs b/src/NAppUpdate.Framework/UpdateManager.cs index 1fc1346d..91a7e39e 100644 --- a/src/NAppUpdate.Framework/UpdateManager.cs +++ b/src/NAppUpdate.Framework/UpdateManager.cs @@ -506,10 +506,20 @@ public void ApplyUpdates(bool relaunchApplication, bool updaterDoLogging, bool u public void ReinstateIfRestarted() { + if (!IsAfterRestart()) + { + return; + } + lock (UpdatesToApply) { - var dto = NauIpc.ReadDto(Config.UpdateProcessName) as NauIpc.NauDto; - if (dto == null) return; + NauIpc.NauDto dto = NauIpc.ReadDto(Config.UpdateProcessName); + + if (dto == null) + { + return; + } + Config = dto.Configs; UpdatesToApply = dto.Tasks; Logger = new Logger(dto.LogItems); @@ -581,5 +591,18 @@ public void CleanUp() ShouldStop = false; } } + + private bool IsAfterRestart() + { + foreach (string arg in Environment.GetCommandLineArgs()) + { + if (arg == "-nappupdate-afterrestart") + { + return true; + } + } + + return false; + } } } \ No newline at end of file diff --git a/src/NAppUpdate.Framework/Updater/updater.exe b/src/NAppUpdate.Framework/Updater/updater.exe index 0519ecba..94c4caa2 100644 Binary files a/src/NAppUpdate.Framework/Updater/updater.exe and b/src/NAppUpdate.Framework/Updater/updater.exe differ diff --git a/src/NAppUpdate.Framework/Utils/NauIpc.cs b/src/NAppUpdate.Framework/Utils/NauIpc.cs index 91f84a24..52b08c54 100644 --- a/src/NAppUpdate.Framework/Utils/NauIpc.cs +++ b/src/NAppUpdate.Framework/Utils/NauIpc.cs @@ -9,6 +9,7 @@ using System.Runtime.Serialization.Formatters.Binary; using NAppUpdate.Framework.Common; using NAppUpdate.Framework.Tasks; +using System.IO.Pipes; namespace NAppUpdate.Framework.Utils { @@ -29,158 +30,76 @@ internal class NauDto public bool RelaunchApplication { get; set; } } - [DllImport("kernel32.dll", SetLastError = true)] - private static extern SafeFileHandle CreateNamedPipe( - String pipeName, - uint dwOpenMode, - uint dwPipeMode, - uint nMaxInstances, - uint nOutBufferSize, - uint nInBufferSize, - uint nDefaultTimeOut, - IntPtr lpSecurityAttributes); - - [DllImport("kernel32.dll", SetLastError = true)] - private static extern int ConnectNamedPipe( - SafeFileHandle hNamedPipe, - IntPtr lpOverlapped); - - [DllImport("kernel32.dll", SetLastError = true)] - private static extern SafeFileHandle CreateFile( - String pipeName, - uint dwDesiredAccess, - uint dwShareMode, - IntPtr lpSecurityAttributes, - uint dwCreationDisposition, - uint dwFlagsAndAttributes, - IntPtr hTemplate); - - //private const uint DUPLEX = (0x00000003); - private const uint WRITE_ONLY = (0x00000002); - private const uint FILE_FLAG_OVERLAPPED = (0x40000000); - - const uint GENERIC_READ = (0x80000000); - //static readonly uint GENERIC_WRITE = (0x40000000); - const uint OPEN_EXISTING = 3; - - //Which really isn't an error... - const uint ERROR_PIPE_CONNECTED = 535; - - internal static string GetPipeName(string syncProcessName) - { - return string.Format("\\\\.\\pipe\\{0}", syncProcessName); - } - - private class State - { - public readonly EventWaitHandle eventWaitHandle; - public int result { get; set; } - public SafeFileHandle clientPipeHandle { get; set; } - public Exception exception; - - public State() - { - eventWaitHandle = new ManualResetEvent(false); - } - } - - internal static uint BUFFER_SIZE = 4096; + private const int PIPE_TIMEOUT = 15000; + /// + /// Launches the specifies process and sends the dto object to it using a named pipe + /// + /// Dto object to send + /// Process info for the process to start + /// Name of the pipe to write to + /// The started process public static Process LaunchProcessAndSendDto(NauDto dto, ProcessStartInfo processStartInfo, string syncProcessName) { Process p; - State state = new State(); - - using (state.clientPipeHandle = CreateNamedPipe( - GetPipeName(syncProcessName), - WRITE_ONLY | FILE_FLAG_OVERLAPPED, - 0, - 1, // 1 max instance (only the updater utility is expected to connect) - BUFFER_SIZE, - BUFFER_SIZE, - 0, - IntPtr.Zero)) + + using (NamedPipeServerStream pipe = new NamedPipeServerStream(syncProcessName, PipeDirection.Out, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous)) { - //failed to create named pipe - if (state.clientPipeHandle.IsInvalid) + p = Process.Start(processStartInfo); + + if (p == null) { - throw new Exception("Launch process client: Failed to create named pipe, handle is invalid."); + throw new ProcessStartFailedException("The process failed to start"); } - // This will throw Win32Exception if the user denies UAC - p = Process.Start(processStartInfo); - - ThreadPool.QueueUserWorkItem(ConnectPipe, state); - //A rather arbitary five seconds, perhaps better to be user configurable at some point? - state.eventWaitHandle.WaitOne(10000); + var asyncResult = pipe.BeginWaitForConnection(null, null); - //failed to connect client pipe - if (state.result == 0) + if (asyncResult.AsyncWaitHandle.WaitOne(PIPE_TIMEOUT)) { - throw new Exception("Launch process client: Failed to connect to named pipe", state.exception); + pipe.EndWaitForConnection(asyncResult); + + BinaryFormatter formatter = new BinaryFormatter(); + formatter.Serialize(pipe, dto); } + else if (p.HasExited) + { + Type exceptionType = Marshal.GetExceptionForHR(p.ExitCode).GetType(); - //client connection successfull - using (var fStream = new FileStream(state.clientPipeHandle, FileAccess.Write, (int)BUFFER_SIZE, true)) + throw new TimeoutException(string.Format("The NamedPipeServerStream timed out waiting for a named pipe connection, " + + "but the process has exited with exit code: {0} ({1})", p.ExitCode, exceptionType.FullName)); + } + else { - new BinaryFormatter().Serialize(fStream, dto); - fStream.Flush(); - fStream.Close(); + throw new TimeoutException("The NamedPipeServerStream timed out waiting for a named pipe connection."); } } return p; } - internal static void ConnectPipe(object stateObject) + /// + /// Reads the dto object from the named pipe + /// + /// Name of the pipe to read from + /// The dto object read from the pipe + public static NauDto ReadDto(string syncProcessName) { - State state = (State)stateObject; + NauDto dto; - try - { - state.result = ConnectNamedPipe(state.clientPipeHandle, IntPtr.Zero); - } - catch (Exception e) + using (NamedPipeClientStream pipe = new NamedPipeClientStream(".", syncProcessName, PipeDirection.In, PipeOptions.Asynchronous)) { - state.exception = e; - } + pipe.Connect(PIPE_TIMEOUT); - int error = Marshal.GetLastWin32Error(); - //Check for the oddball: ERROR - PIPE CONNECTED - //Ref: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365146%28v=vs.85%29.aspx - if (error == ERROR_PIPE_CONNECTED) - { - state.result = 1; - } - else if (error != 0) - { - state.exception = new Win32Exception(error); + BinaryFormatter formatter = new BinaryFormatter(); + dto = formatter.Deserialize(pipe) as NauDto; } - state.eventWaitHandle.Set(); // signal we're done - } - - - internal static object ReadDto(string syncProcessName) - { - using (SafeFileHandle pipeHandle = CreateFile( - GetPipeName(syncProcessName), - GENERIC_READ, - 0, - IntPtr.Zero, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - IntPtr.Zero)) + if (dto == null || dto.Configs == null) { - - if (pipeHandle.IsInvalid) - return null; - - using (var fStream = new FileStream(pipeHandle, FileAccess.Read, (int)BUFFER_SIZE, true)) - { - return new BinaryFormatter().Deserialize(fStream); - } + throw new Exception("Failed to read the dto from the pipe stream"); } + + return dto; } internal static void ExtractUpdaterFromResource(string updaterPath, string hostExeName) @@ -212,4 +131,4 @@ internal static void ExtractUpdaterFromResource(string updaterPath, string hostE } } } -} \ No newline at end of file +} diff --git a/src/NAppUpdate.Framework/Utils/ProcessStartFailedException.cs b/src/NAppUpdate.Framework/Utils/ProcessStartFailedException.cs new file mode 100644 index 00000000..fa52f874 --- /dev/null +++ b/src/NAppUpdate.Framework/Utils/ProcessStartFailedException.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NAppUpdate.Framework.Utils +{ + /// + /// Thrown if the Process.Start() call returns null, e.g. the updater process fails to start at all. + /// + internal class ProcessStartFailedException : Exception + { + public ProcessStartFailedException(string message) : base(message) { } + } + +} diff --git a/src/NAppUpdate.Updater/AppStart.cs b/src/NAppUpdate.Updater/AppStart.cs index 5edc9a2b..825206db 100644 --- a/src/NAppUpdate.Updater/AppStart.cs +++ b/src/NAppUpdate.Updater/AppStart.cs @@ -8,6 +8,7 @@ using NAppUpdate.Framework.Common; using NAppUpdate.Framework.Tasks; using NAppUpdate.Framework.Utils; +using System.Runtime.InteropServices; namespace NAppUpdate.Updater { @@ -16,15 +17,43 @@ internal static class AppStart private static ArgumentsParser _args; private static Logger _logger; private static ConsoleForm _console; + private static NauIpc.NauDto _dto; + private static string _logFilePath = string.Empty; + private static string _workingDir = string.Empty; + private static bool _appRunning = true; private static void Main() { - //Debugger.Launch(); - string tempFolder = string.Empty; - string logFile = string.Empty; - _args = ArgumentsParser.Get(); + try + { + Setup(); + PerformUpdates(); + } + catch (Exception ex) + { + Environment.ExitCode = Marshal.GetHRForException(ex); + + Log(ex); + + if (!_appRunning && !_args.Log && !_args.ShowConsole) + { + MessageBox.Show(ex.ToString()); + } + + EventLog.WriteEntry("NAppUpdate.Updater", ex.ToString(), EventLogEntryType.Error); + } + finally + { + Teardown(); + } + } + private static void Setup() + { + _workingDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); _logger = UpdateManager.Instance.Logger; + _args = ArgumentsParser.Get(); + _args.ParseCommandLineArgs(); if (_args.ShowConsole) { @@ -34,212 +63,191 @@ private static void Main() Log("Starting to process cold updates..."); - var workingDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); if (_args.Log) { // Setup a temporary location for the log file, until we can get the DTO - logFile = Path.Combine(workingDir, @"NauUpdate.log"); + _logFilePath = Path.Combine(_workingDir, @"NauUpdate.log"); } + } - try + private static void PerformUpdates() + { + string syncProcessName = _args.ProcessName; + + if (string.IsNullOrEmpty(syncProcessName)) { - // Get the update process name, to be used to create a named pipe and to wait on the application - // to quit - string syncProcessName = _args.ProcessName; - if (string.IsNullOrEmpty(syncProcessName)) //Application.Exit(); - throw new ArgumentException("The command line needs to specify the mutex of the program to update.", "ar" + "gs"); + throw new ArgumentException("Required command line argument is missing", "ProcessName"); + } - Log("Update process name: '{0}'", syncProcessName); + Log("Update process name: '{0}'", syncProcessName); - // Load extra assemblies to the app domain, if present - var availableAssemblies = FileSystem.GetFiles(workingDir, "*.exe|*.dll", SearchOption.TopDirectoryOnly); - foreach (var assemblyPath in availableAssemblies) - { - Log("Loading {0}", assemblyPath); + // Load extra assemblies to the app domain, if present + var availableAssemblies = FileSystem.GetFiles(_workingDir, "*.exe|*.dll", SearchOption.TopDirectoryOnly); + foreach (var assemblyPath in availableAssemblies) + { + Log("Loading {0}", assemblyPath); - if (assemblyPath.Equals(Assembly.GetEntryAssembly().Location, StringComparison.InvariantCultureIgnoreCase) || assemblyPath.EndsWith("NAppUpdate.Framework.dll")) - { - Log("\tSkipping (part of current execution)"); - continue; - } + if (assemblyPath.Equals(Assembly.GetEntryAssembly().Location, StringComparison.InvariantCultureIgnoreCase) || assemblyPath.EndsWith("NAppUpdate.Framework.dll")) + { + Log("\tSkipping (part of current execution)"); + continue; + } - try - { - // ReSharper disable UnusedVariable - var assembly = Assembly.LoadFile(assemblyPath); - // ReSharper restore UnusedVariable - } - catch (BadImageFormatException ex) - { - Log("\tSkipping due to an error: {0}", ex.Message); - } + try + { + // ReSharper disable UnusedVariable + var assembly = Assembly.LoadFile(assemblyPath); + // ReSharper restore UnusedVariable + } + catch (BadImageFormatException ex) + { + Log("\tSkipping due to an error: {0}", ex.Message); } + } - // Connect to the named pipe and retrieve the updates list - var dto = NauIpc.ReadDto(syncProcessName) as NauIpc.NauDto; + // Connect to the named pipe and retrieve the updates list + _dto = NauIpc.ReadDto(syncProcessName); - // Make sure we start updating only once the application has completely terminated - Thread.Sleep(1000); // Let's even wait a bit - bool createdNew; - using (var mutex = new Mutex(false, syncProcessName + "Mutex", out createdNew)) + // Make sure we start updating only once the application has completely terminated + Thread.Sleep(1000); // Let's even wait a bit + bool createdNew; + using (var mutex = new Mutex(false, syncProcessName + "Mutex", out createdNew)) + { + try { - try - { - if (!createdNew) mutex.WaitOne(); - } - catch (AbandonedMutexException) + if (!createdNew) { - // An abandoned mutex is exactly what we are expecting... - } - finally - { - Log("The application has terminated (as expected)"); + mutex.WaitOne(); } } + catch (AbandonedMutexException) + { + // An abandoned mutex is exactly what we are expecting... + } + finally + { + Log("The application has terminated (as expected)"); + _appRunning = false; + } + } - bool updateSuccessful = true; - - if (dto == null || dto.Configs == null) throw new Exception("Invalid DTO received"); + _logger.LogItems.InsertRange(0, _dto.LogItems); + _dto.LogItems = _logger.LogItems; - if (dto.LogItems != null) // shouldn't really happen - _logger.LogItems.InsertRange(0, dto.LogItems); - dto.LogItems = _logger.LogItems; + // Get some required environment variables + string appPath = _dto.AppPath; + string appDir = _dto.WorkingDirectory ?? Path.GetDirectoryName(appPath) ?? string.Empty; - // Get some required environment variables - string appPath = dto.AppPath; - string appDir = dto.WorkingDirectory ?? Path.GetDirectoryName(appPath) ?? string.Empty; - tempFolder = dto.Configs.TempFolder; - string backupFolder = dto.Configs.BackupFolder; - bool relaunchApp = dto.RelaunchApplication; + if (!string.IsNullOrEmpty(_dto.AppPath)) + { + _logFilePath = Path.Combine(Path.GetDirectoryName(_dto.AppPath), @"NauUpdate.log"); // now we can log to a more accessible location + } - if (!string.IsNullOrEmpty(dto.AppPath)) logFile = Path.Combine(Path.GetDirectoryName(dto.AppPath), @"NauUpdate.log"); // now we can log to a more accessible location + if (_dto.Tasks == null) + { + throw new Exception("The Task list received in the dto is null"); + } + else if (_dto.Tasks.Count == 0) + { + throw new Exception("The Task list received in the dto is empty"); + } - if (dto.Tasks == null || dto.Tasks.Count == 0) throw new Exception("Could not find the updates list (or it was empty)."); + Log("Got {0} task objects", _dto.Tasks.Count); - Log("Got {0} task objects", dto.Tasks.Count); + // Perform the actual off-line update process + foreach (var t in _dto.Tasks) + { + Log("Task \"{0}\": {1}", t.Description, t.ExecutionStatus); - //This can be handy if you're trying to debug the updater.exe! - //#if (DEBUG) + if (t.ExecutionStatus != TaskExecutionStatus.RequiresAppRestart && t.ExecutionStatus != TaskExecutionStatus.RequiresPrivilegedAppRestart) { - if (_args.ShowConsole) - { - _console.WriteLine(); - _console.WriteLine("Pausing to attach debugger. Press any key to continue."); - _console.ReadKey(); - } + Log("\tSkipping"); + continue; + } + + Exception exception = null; + try + { + Log("\tExecuting..."); + t.ExecutionStatus = t.Execute(true); + } + catch (Exception ex) + { + t.ExecutionStatus = TaskExecutionStatus.Failed; + exception = ex; } - //#endif - // Perform the actual off-line update process - foreach (var t in dto.Tasks) + if (t.ExecutionStatus != TaskExecutionStatus.Successful) { - Log("Task \"{0}\": {1}", t.Description, t.ExecutionStatus); + string taskFailedMessage = string.Format("Update failed, task execution failed, description: {0}, execution status: {1}", t.Description, t.ExecutionStatus); + throw new Exception(taskFailedMessage, exception); + } + } - if (t.ExecutionStatus != TaskExecutionStatus.RequiresAppRestart && t.ExecutionStatus != TaskExecutionStatus.RequiresPrivilegedAppRestart) - { - Log("\tSkipping"); - continue; - } + Log("Finished successfully"); + Log("Removing backup folder"); - Log("\tExecuting..."); + if (Directory.Exists(_dto.Configs.BackupFolder)) + { + FileSystem.DeleteDirectory(_dto.Configs.BackupFolder); + } - // TODO: Better handling on failure: logging, rollbacks - try - { - t.ExecutionStatus = t.Execute(true); - } - catch (Exception ex) - { - Log(ex); - updateSuccessful = false; - t.ExecutionStatus = TaskExecutionStatus.Failed; - } + // Start the application only if requested to do so + if (_dto.RelaunchApplication) + { + Log("Re-launching process {0} with working dir {1}", appPath, appDir); - if (t.ExecutionStatus == TaskExecutionStatus.Successful) continue; - Log("\tTask execution failed"); - updateSuccessful = false; - break; - } + bool useShellExecute = !_args.ShowConsole; - if (updateSuccessful) + ProcessStartInfo info = new ProcessStartInfo { - Log("Finished successfully"); - Log("Removing backup folder"); - if (Directory.Exists(backupFolder)) FileSystem.DeleteDirectory(backupFolder); - } - else + UseShellExecute = useShellExecute, + WorkingDirectory = appDir, + FileName = appPath, + Arguments = "-nappupdate-afterrestart" + }; + + try { - MessageBox.Show("Update Failed"); - Log(Logger.SeverityLevel.Error, "Update failed"); + NauIpc.LaunchProcessAndSendDto(_dto, info, syncProcessName); + _appRunning = true; } - - // Start the application only if requested to do so - if (relaunchApp) + catch (Exception ex) { - Log("Re-launching process {0} with working dir {1}", appPath, appDir); - ProcessStartInfo info; - if (_args.ShowConsole) - { - info = new ProcessStartInfo - { - UseShellExecute = false, - WorkingDirectory = appDir, - FileName = appPath, - }; - } - else - { - info = new ProcessStartInfo - { - UseShellExecute = true, - WorkingDirectory = appDir, - FileName = appPath, - }; - } - - try - { - NauIpc.LaunchProcessAndSendDto(dto, info, syncProcessName); - } - catch (Exception ex) - { - throw new UpdateProcessFailedException("Unable to relaunch application and/or send DTO", ex); - } + throw new UpdateProcessFailedException("Unable to relaunch application and/or send DTO", ex); } - - Log("All done"); - //Application.Exit(); } - catch (Exception ex) + } + + private static void Teardown() + { + if (_args.Log) { - // supressing catch because if at any point we get an error the update has failed - Log(ex); + // at this stage we can't make any assumptions on correctness of the path + FileSystem.CreateDirectoryStructure(_logFilePath, true); + _logger.Dump(_logFilePath); } - finally + + if (_args.ShowConsole) { if (_args.Log) { - // at this stage we can't make any assumptions on correctness of the path - FileSystem.CreateDirectoryStructure(logFile, true); - _logger.Dump(logFile); - } - - if (_args.ShowConsole) - { - if (_args.Log) - { - _console.WriteLine(); - _console.WriteLine("Log file was saved to {0}", logFile); - _console.WriteLine(); - } _console.WriteLine(); - _console.WriteLine("Press any key or close this window to exit."); - _console.ReadKey(); + _console.WriteLine("Log file was saved to {0}", _logFilePath); + _console.WriteLine(); } - if (!string.IsNullOrEmpty(tempFolder)) SelfCleanUp(tempFolder); - Application.Exit(); + _console.WriteLine(); + _console.WriteLine("Press any key or close this window to exit."); + _console.ReadKey(); + } + + if (_dto != null && _dto.Configs != null & !string.IsNullOrEmpty(_dto.Configs.TempFolder)) + { + SelfCleanUp(_dto.Configs.TempFolder); } + + Application.Exit(); } private static void SelfCleanUp(string tempFolder) @@ -274,9 +282,13 @@ private static void Log(Logger.SeverityLevel severity, string message, params ob message = string.Format(message, args); _logger.Log(severity, message); - if (_args.ShowConsole) _console.WriteLine(message); - Application.DoEvents(); + if (_args.ShowConsole) + { + _console.WriteLine(message); + + Application.DoEvents(); + } } private static void Log(Exception ex) @@ -292,9 +304,9 @@ private static void Log(Exception ex) _console.WriteLine(); _console.WriteLine("The updater will close when you close this window."); - } - Application.DoEvents(); + Application.DoEvents(); + } } } -} \ No newline at end of file +} diff --git a/src/NAppUpdate.Updater/NAppUpdate.Updater.csproj b/src/NAppUpdate.Updater/NAppUpdate.Updater.csproj index fba3a29d..bfdae1e2 100644 --- a/src/NAppUpdate.Updater/NAppUpdate.Updater.csproj +++ b/src/NAppUpdate.Updater/NAppUpdate.Updater.csproj @@ -10,7 +10,7 @@ Properties NAppUpdate.Updater NAppUpdate.Updater - v2.0 + v3.5 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 @@ -36,6 +36,7 @@ false true OnBuildSuccess + true diff --git a/src/NAppUpdate.Updater/Properties/Settings.Designer.cs b/src/NAppUpdate.Updater/Properties/Settings.Designer.cs index c10ec226..d8b18369 100644 --- a/src/NAppUpdate.Updater/Properties/Settings.Designer.cs +++ b/src/NAppUpdate.Updater/Properties/Settings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.225 +// Runtime Version:4.0.30319.34014 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -12,7 +12,7 @@ namespace NAppUpdate.Updater.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + [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()))); diff --git a/src/NAppUpdate.Updater/app.config b/src/NAppUpdate.Updater/app.config index 0df7832f..ea93c858 100644 --- a/src/NAppUpdate.Updater/app.config +++ b/src/NAppUpdate.Updater/app.config @@ -1,3 +1,3 @@ - +