Пример #1
0
        private static void Setup()
        {
            _workingDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            _logger     = UpdateManager.Instance.Logger;
            _args       = ArgumentsParser.Get();

            _args.ParseCommandLineArgs();

            Log("Starting to process cold updates...");

            if (_args.Log)
            {
                // Setup a temporary location for the log file, until we can get the DTO
                _logFilePath = Path.Combine(_workingDir, @"NauUpdate.log");
            }
        }
Пример #2
0
        private static void Setup()
        {
            _workingDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            _logger     = UpdateManager.Instance.Logger;
            _args       = ArgumentsParser.Get();

            _args.ParseCommandLineArgs();
            if (_args.ShowConsole)
            {
                _console = new ConsoleForm();
                _console.Show();
            }

            Log("Starting to process cold updates...");

            if (_args.Log)
            {
                _logFilePath = Path.Combine(_workingDir, @"NauUpdate.log");
            }
        }
Пример #3
0
        private static void Main()
        {
            //Debugger.Launch();
            string tempFolder = string.Empty;
            string logFile = string.Empty;
            _args = ArgumentsParser.Get();

            _logger = UpdateManager.Instance.Logger;
            _args.ParseCommandLineArgs();
            if (_args.ShowConsole)
            {
                _console = new ConsoleForm();
                _console.Show();
            }

            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");
            }

            try
            {
                // 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");

                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);

                    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);
                    }
                }

                // Connect to the named pipe and retrieve the updates list
                var dto = NauIpc.ReadDto(syncProcessName) as NauIpc.NauDto;

                // 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
                    {
                        if (!createdNew) mutex.WaitOne();
                    }
                    catch (AbandonedMutexException)
                    {
                        // An abandoned mutex is exactly what we are expecting...
                    }
                    finally
                    {
                        Log("The application has terminated (as expected)");
                    }
                }

                bool updateSuccessful = true;

                if (dto == null || dto.Configs == null) throw new Exception("Invalid DTO received");

                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;
                tempFolder = dto.Configs.TempFolder;
                string backupFolder = dto.Configs.BackupFolder;
                bool relaunchApp = dto.RelaunchApplication;

                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 || 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);

                //This can be handy if you're trying to debug the updater.exe!
                //#if (DEBUG)
                {
                    if (_args.ShowConsole)
                    {
                        _console.WriteLine();
                        _console.WriteLine("Pausing to attach debugger.  Press any key to continue.");
                        _console.ReadKey();
                    }

                }
                //#endif

                // Perform the actual off-line update process
                foreach (var t in dto.Tasks)
                {
                    Log("Task \"{0}\": {1}", t.Description, t.ExecutionStatus);

                    if (t.ExecutionStatus != TaskExecutionStatus.RequiresAppRestart && t.ExecutionStatus != TaskExecutionStatus.RequiresPrivilegedAppRestart)
                    {
                        Log("\tSkipping");
                        continue;
                    }

                    Log("\tExecuting...");

                    // TODO: Better handling on failure: logging, rollbacks
                    try
                    {
                        t.ExecutionStatus = t.Execute(true);
                    }
                    catch (Exception ex)
                    {
                        Log(ex);
                        updateSuccessful = false;
                        t.ExecutionStatus = TaskExecutionStatus.Failed;
                    }

                    if (t.ExecutionStatus == TaskExecutionStatus.Successful) continue;
                    Log("\tTask execution failed");
                    updateSuccessful = false;
                    break;
                }

                if (updateSuccessful)
                {
                    Log("Finished successfully");
                    Log("Removing backup folder");
                    if (Directory.Exists(backupFolder)) FileSystem.DeleteDirectory(backupFolder);
                }
                else
                {
                    MessageBox.Show("Update Failed");
                    Log(Logger.SeverityLevel.Error, "Update failed");
                }

                // Start the application only if requested to do so
                if (relaunchApp)
                {
                    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);
                    }
                }

                Log("All done");
                //Application.Exit();
            }
            catch (Exception ex)
            {
                // supressing catch because if at any point we get an error the update has failed
                Log(ex);
            }
            finally
            {
                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();
                }
                if (!string.IsNullOrEmpty(tempFolder)) SelfCleanUp(tempFolder);
                Application.Exit();
            }
        }
Пример #4
0
 public static ArgumentsParser Get()
 {
     return(_instance ?? (_instance = new ArgumentsParser()));
 }
Пример #5
0
        private static void Main()
        {
            string tempFolder = string.Empty;
            string logFile    = string.Empty;

            _args = ArgumentsParser.Get();

            _logger = UpdateManager.Instance.Logger;
            _args.ParseCommandLineArgs();
            if (_args.ShowConsole)
            {
                //_console = new ConsoleForm();
                //_console.Show();
            }

            Log("Starting to process cold updates...");
            Log("Arguments parsed: {0}{1}.", Environment.NewLine, _args.DumpArgs());

            var workingDir = Directory.GetCurrentDirectory();

            if (_args.Log)
            {
                // Setup a temporary location for the log file, until we can get the DTO
                logFile = Path.Combine(workingDir, @"NauUpdate.log");
            }

            try {
                // 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");
                }

                Log("Update process name: '{0}'", syncProcessName);
//TODO: I suppose this was done to load custom tasks, however there were some problems when loading an assembly which later was updated (msg: can't update because file is in use).
//                // Load extra assemblies to the app domain, if present
//                Log("Getting files in : '{0}'", workingDir);
//                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;
//                    }

//                    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;

                // Make sure we start updating only once the application has completely terminated
                Thread.Sleep(100);                 // hell, let's even wait a bit
                bool createdNew;
                using (var mutex = new Mutex(false, syncProcessName + "Mutex", out createdNew)) {
                    try {
                        if (!createdNew)
                        {
                            mutex.WaitOne();
                        }
                    } catch (AbandonedMutexException) {
                        // An abandoned mutex is exactly what we are expecting...
                    } finally {
                        Log("The application has terminated (as expected)");
                    }
                }

                bool updateSuccessful = true;

                if (dto == null || dto.Configs == null)
                {
                    throw new Exception("Invalid DTO received");
                }

                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;
                tempFolder = dto.Configs.TempFolder;
                string backupFolder = dto.Configs.BackupFolder;
                bool   relaunchApp  = dto.RelaunchApplication;

                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 || 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);

//This can be handy if you're trying to debug the updater.exe!
//#if (DEBUG)
//{
//                if (_args.ShowConsole) {
//                    _console.WriteLine();
//                    _console.WriteLine("Pausing to attach debugger.  Press any key to continue.");
//                    _console.ReadKey();
//                }

//}
//#endif

                // Perform the actual off-line update process
                foreach (var t in dto.Tasks)
                {
                    Log("Task \"{0}\": {1}", t.Description, t.ExecutionStatus);

                    if (t.ExecutionStatus != TaskExecutionStatus.RequiresAppRestart && t.ExecutionStatus != TaskExecutionStatus.RequiresPrivilegedAppRestart)
                    {
                        Log("\tSkipping");
                        continue;
                    }

                    Log("\tExecuting...");

                    // TODO: Better handling on failure: logging, rollbacks
                    try {
                        t.ExecutionStatus = t.Execute(true);
                    } catch (Exception ex) {
                        Log(ex);
                        updateSuccessful  = false;
                        t.ExecutionStatus = TaskExecutionStatus.Failed;
                    }

                    if (t.ExecutionStatus == TaskExecutionStatus.Successful)
                    {
                        continue;
                    }
                    Log("\tTask execution failed");
                    updateSuccessful = false;
                    break;
                }

                if (updateSuccessful)
                {
                    Log("Finished successfully");
                    Log("Removing backup folder");
                    if (Directory.Exists(backupFolder))
                    {
                        FileSystem.DeleteDirectory(backupFolder);
                    }
                }
                else
                {
                    Console.WriteLine("Update Failed");
                    //MessageBox.Show();
                    Log(Logger.SeverityLevel.Error, "Update failed");
                }

                // Start the application only if requested to do so
                if (relaunchApp)
                {
                    Log("Re-launching process {0} with working dir {1}", appPath, appDir);

                    var info = new ProcessStartInfo {
                        UseShellExecute  = false,
                        WorkingDirectory = appDir,
                        FileName         = appPath,
                    };

                    var p = NauIpc.LaunchProcessAndSendDto(dto, info, syncProcessName);
                    if (p == null)
                    {
                        throw new UpdateProcessFailedException("Unable to relaunch application and/or send DTO");
                    }
                }

                Log("All done");
                //Application.Exit();
            } catch (Exception ex) {
                // supressing catch because if at any point we get an error the update has failed
                Log(ex);
            } finally {
                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("Exiting.");                     //Must not read console!
                    //see: http://msdn.microsoft.com/en-us/library/system.console.aspx
                    //Especially:
                    //Console class members that work normally when the underlying stream is directed to a console might
                    //throw an exception if the stream is redirected, for example, to a file. Program your application to
                    //catch System.IO.IOException exceptions if you redirect a standard stream. You can also use
                    //the IsOutputRedirected, IsInputRedirected, and IsErrorRedirected properties to determine whether
                    //a standard stream is redirected before performing an operation that throws an System.IO.IOException exception.
                }
                if (!string.IsNullOrEmpty(tempFolder))
                {
                    SelfCleanUp(tempFolder);
                }
                //return;
                //Application.Exit();
            }
        }
Пример #6
0
        private static void Main()
        {
            //Debugger.Launch();
            string tempFolder = "";
            try
            {
                _args = ArgumentsParser.Get();
                string logFile = System.Reflection.Assembly.GetEntryAssembly().Location;
                logFile = Path.Combine(Path.GetDirectoryName(logFile), "logs");
                logFile = Path.Combine(logFile, "NauUpdate.log");
                _logger = new Logger(logFile);
                _args.ParseCommandLineArgs();
                if (_args.ShowConsole)
                {
                    _console = new ConsoleForm();
                    _console.Show();
                }
                Log("==========================================");
                Log("Starting...");
                if (_args.Log)
                    _console.WriteLine("Logging to {0}", logFile);

                // 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.", "args");
                //Log("The command line needs to specify the mutex of the program to update.");
                Log("Object to update: '{0}'", syncProcessName);

                // Connect to the named pipe and retrieve the updates list
                var PIPE_NAME = string.Format("\\\\.\\pipe\\{0}", syncProcessName);
                var o = GetUpdates(PIPE_NAME);

                Log("Connecting to updater pipe: " + PIPE_NAME);
                Log(o != null ? "Connected to updater pipe." : "Failed to read updates from the updater pipe.");
                Log("Waiting for application to terminate.");

                // Make sure we start updating only once the application has completely terminated
                bool createdNew;
                using (var mutex = new Mutex(false, syncProcessName, out createdNew))
                {
                    try
                    {
                        if (!createdNew) mutex.WaitOne();
                    }
                    catch (AbandonedMutexException)
                    {
                        // An abandoned mutex is exactly what we are expecting...
                        Log("The application has terminated (as expected).");
                    }
                }

                bool relaunchApp = true, updateSuccessful = true;
                string appPath, appDir, backupFolder;
                {
                    Dictionary<string, object> dict = null;
                    if (o is Dictionary<string, object>)
                        dict = o as Dictionary<string, object>;

                    if (dict == null || dict.Count == 0)
                    {
                        throw new Exception("Could not find the updates list (or it was empty).");
                        //Application.Exit();
                        //return;
                    }

                    // Get some required environment variables
                    appPath = dict["ENV:AppPath"].ToString();
                    appDir = dict["ENV:WorkingDirectory"] as string ?? Path.GetDirectoryName(appPath);
                    tempFolder = dict["ENV:TempFolder"].ToString();
                    backupFolder = dict["ENV:BackupFolder"].ToString();
                    relaunchApp = dict["ENV:RelaunchApplication"] as bool? ?? true;

                    // Perform the actual off-line update process
                    Log("Starting the updates...");
                    var en = dict.GetEnumerator();
                    while (en.MoveNext())
                    {
                        if (en.Current.Key.StartsWith("ENV:"))
                            continue;
                        else
                        {
                            Log("* Updating {0} ({1})", en.Current.Key, en.Current.Value);
                            IUpdateAction a = null;
                            if (en.Current.Value is string)
                            {
                                Log("\tCopying {0} {1}", en.Current.Value, Path.Combine(appDir, en.Current.Key));
                                a = new FileCopyAction(en.Current.Value.ToString(), Path.Combine(appDir, en.Current.Key));
                            }
                            else if (en.Current.Value is byte[])
                            {
                                Log("\tDumping {0}", en.Current.Value);
                                a = new FileDumpAction(Path.Combine(appDir, en.Current.Key), (byte[])en.Current.Value);
                            }

                            if (a == null)
                                Log("\tUpdate action: null");
                            else
                            {
                                Log("\tUpdate action: {0}", a.ToString());
                                try
                                {
                                    if (!a.Do())
                                    {
                                        Log("\tUpdate action failed: {0}", en.Current.Value);
                                        updateSuccessful = false;
                                        break;
                                    }
                                    else Log("\tUpdate action succeeded: {0}", en.Current.Value);
                                }
                                catch (Exception e)
                                {
                                    MessageBox.Show("Update failed: " + e.Message);
                                    Log("\tUpdate failed: {0}", e.Message);
                                    updateSuccessful = false;
                                    break;
                                }
                            }
                        }
                    }
                }

                if (updateSuccessful)
                {
                    if (Directory.Exists(backupFolder))
                        Directory.Delete(backupFolder, true);
                }
                else
                {
                    MessageBox.Show("Update Failed.");
                    Log("Update failed.");
                }

                // Start the application only if requested to do so
                if (relaunchApp)
                {
                    try
                    {
                        Log("Relaunching the application...");
                        Process.Start(new ProcessStartInfo
                                        {
                                            UseShellExecute = true,
                                            WorkingDirectory = appDir,
                                            FileName = appPath,
                                        });
                    }
                    catch (Win32Exception e)
                    {
                        MessageBox.Show(e.ToString());
                        Log("Update failed: " + e);
                    }
                }

                //MessageBox.Show(string.Format("Re-launched process {0} with working dir {1}", appPath, appDir));

                Log("All done.");
                //Application.Exit();
            }
            catch (Exception ex)
            {
                //supressing catch because if at any point we get an error the update has failed
                Log("*********************************");
                Log("   An error has occurred:");
                Log("   " + ex.Message);
                Log("*********************************");
                if (_args.ShowConsole)
                {
                    _console.WriteLine();
                    _console.WriteLine("The updater will close when you close this window.");
                }
            }
            finally
            {
                if (_args.ShowConsole)
                {
                    _console.WriteLine();
                    _console.WriteLine("Press any key or close this window to exit.");
                    _console.ReadKey();
                }
                CleanUp(tempFolder);
                Application.Exit();
            }
        }
Пример #7
0
 public static ArgumentsParser Get()
 {
     if (_instance == null) _instance = new ArgumentsParser();
     return _instance;
 }
Пример #8
0
 public static ArgumentsParser Get()
 {
     return _instance ?? (_instance = new ArgumentsParser());
 }
Пример #9
0
        private static void Main()
        {
            //Debugger.Launch();
            string tempFolder = "";
            try
            {
                _args = ArgumentsParser.Get();
                string logFile = System.Reflection.Assembly.GetEntryAssembly().Location;
                logFile = Path.Combine(Path.GetDirectoryName(logFile), "logs");
                logFile = Path.Combine(logFile, "NauUpdate.log");
                _logger = new Logger(logFile);
                _args.ParseCommandLineArgs();
                if (_args.ShowConsole)
                {
                    _console = new ConsoleForm();
                    _console.Show();
                }

                Log("Starting...");
                if (_args.Log)
                    _console.WriteLine("Logging to {0}", logFile);

                // 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.", "args");

                Log("Update process name: '{0}'", syncProcessName);

                // Connect to the named pipe and retrieve the updates list
                var dto = NauIpc.ReadDto(syncProcessName) as NauIpc.NauDto;

                // Make sure we start updating only once the application has completely terminated
                bool createdNew;
                using (var mutex = new Mutex(false, syncProcessName + "Mutex", out createdNew))
                {
                    try
                    {
                        if (!createdNew) mutex.WaitOne();
                    }
                    catch (AbandonedMutexException)
                    {
                        // An abandoned mutex is exactly what we are expecting...
                        Log("The application has terminated (as expected).");
                    }
                }

                bool updateSuccessful = true;

                if (dto == null || dto.Configs == null)
                {
                    throw new Exception("Invalid DTO received");
                }

                Log("Got {0} task objects", dto.Tasks.Count);

                // 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 (dto.Tasks == null || dto.Tasks.Count == 0)
                {
                    throw new Exception("Could not find the updates list (or it was empty).");
                }

                // Perform the actual off-line update process
                Log("Starting the updates...");

                foreach (var t in dto.Tasks)
                {
                    Log("Task \"{0}\": {1}", t.Description, t.ExecutionStatus);

                    if (t.ExecutionStatus != TaskExecutionStatus.RequiresAppRestart
                        && t.ExecutionStatus != TaskExecutionStatus.RequiresPrivilegedAppRestart)
                        continue;

                    Log("\tExecuting...");

                    try
                    {
                        t.ExecutionStatus = t.Execute(true);
                    }
                    catch (Exception ex)
                    {
                        // TODO: Log message
                        Log("\tFailed: {0}", ex.Message);
                        updateSuccessful = false;
                        t.ExecutionStatus = TaskExecutionStatus.Failed;
                        MessageBox.Show("Update failed: " + ex.Message);
                    }

                    if (t.ExecutionStatus != TaskExecutionStatus.Successful)
                    {
                        Log("\tTask execution failed failed");
                        updateSuccessful = false;
                        break;
                    }
                }

                if (updateSuccessful)
                {
                    Log("Finished");
                    Log("Removing backup folder");
                    if (Directory.Exists(backupFolder))
                        FileSystem.DeleteDirectory(backupFolder);
                }
                else
                {
                    MessageBox.Show("Update Failed.");
                    Log("Update failed.");
                }

                // Start the application only if requested to do so
                if (relaunchApp)
                {
                    try
                    {
                        Log("Re-launching process {0} with working dir {1}", appPath, appDir);

                        var info = new ProcessStartInfo
                                   	{
                                   		UseShellExecute = true,
                                   		WorkingDirectory = appDir,
                                   		FileName = appPath,
                                   	};

                        var p = NauIpc.LaunchProcessAndSendDto(dto, info, syncProcessName);
                        if (p == null)
                        {
                            Log("Unable to relaunch application");
                        }
                    }
                    catch (Win32Exception e)
                    {
                        MessageBox.Show(e.ToString());
                        Log("Update failed: " + e);
                    }
                }

                Log("All done.");
                //Application.Exit();
            }
            catch (Exception ex)
            {
                //supressing catch because if at any point we get an error the update has failed
                Log("*********************************");
                Log("   An error has occurred:");
                Log("   " + ex.Message);
                Log("*********************************");
                if (_args.ShowConsole)
                {
                    _console.WriteLine();
                    _console.WriteLine("The updater will close when you close this window.");
                }
            }
            finally
            {
                if (_args.ShowConsole)
                {
                    _console.WriteLine();
                    _console.WriteLine("Press any key or close this window to exit.");
                    _console.ReadKey();
                }
                if (!string.IsNullOrEmpty(tempFolder)) SelfCleanUp(tempFolder);
                Application.Exit();
            }
        }
Пример #10
0
        private static void Setup()
        {
            _workingDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            _logger = UpdateManager.Instance.Logger;
            _args = ArgumentsParser.Get();

            _args.ParseCommandLineArgs();
            if (_args.ShowConsole)
            {
                _console = new ConsoleForm();
                _console.Show();
            }

            Log("Starting to process cold updates...");

            if (_args.Log)
            {
                // Setup a temporary location for the log file, until we can get the DTO
                _logFilePath = Path.Combine(_workingDir, @"NauUpdate.log");
            }
        }
Пример #11
0
        private static void Main()
        {
            //Debugger.Launch();
            string tempFolder = string.Empty;
            string logFile    = string.Empty;

            _args = ArgumentsParser.Get();

            _logger = UpdateManager.Instance.Logger;
            _args.ParseCommandLineArgs();
            if (_args.ShowConsole)
            {
                _console = new ConsoleForm();
                _console.Show();
            }

            Log("Starting to process cold updates...");

            var workingDir = Path.GetDirectoryName(System.Reflection.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");
            }

            try
            {
                // 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.", "args");
                }

                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);

                    if (assemblyPath.Equals(System.Reflection.Assembly.GetEntryAssembly().Location, StringComparison.InvariantCultureIgnoreCase) ||
                        assemblyPath.EndsWith("NAppUpdate.Framework.dll"))
                    {
                        Log("\tSkipping (part of current execution)");
                        continue;
                    }

                    try
                    {
                        var assembly = System.Reflection.Assembly.LoadFile(assemblyPath);
                    }
                    catch (System.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;

                // Make sure we start updating only once the application has completely terminated
                Thread.Sleep(100);                 // hell, let's even wait a bit
                bool createdNew;
                using (var mutex = new Mutex(false, syncProcessName + "Mutex", out createdNew))
                {
                    try
                    {
                        if (!createdNew)
                        {
                            mutex.WaitOne();
                        }
                    }
                    catch (AbandonedMutexException)
                    {
                        // An abandoned mutex is exactly what we are expecting...
                        Log("The application has terminated (as expected)");
                    }
                }

                bool updateSuccessful = true;

                if (dto == null || dto.Configs == null)
                {
                    throw new Exception("Invalid DTO received");
                }

                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;
                tempFolder = dto.Configs.TempFolder;
                string backupFolder = dto.Configs.BackupFolder;
                bool   relaunchApp  = dto.RelaunchApplication;

                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 || 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);

                // Perform the actual off-line update process
                foreach (var t in dto.Tasks)
                {
                    Log("Task \"{0}\": {1}", t.Description, t.ExecutionStatus);

                    if (t.ExecutionStatus != TaskExecutionStatus.RequiresAppRestart &&
                        t.ExecutionStatus != TaskExecutionStatus.RequiresPrivilegedAppRestart)
                    {
                        Log("\tSkipping");
                        continue;
                    }

                    Log("\tExecuting...");

                    // TODO: Better handling on failure: logging, rollbacks
                    try
                    {
                        t.ExecutionStatus = t.Execute(true);
                    }
                    catch (Exception ex)
                    {
                        Log(ex);
                        updateSuccessful  = false;
                        t.ExecutionStatus = TaskExecutionStatus.Failed;
                    }

                    if (t.ExecutionStatus != TaskExecutionStatus.Successful)
                    {
                        Log("\tTask execution failed");
                        updateSuccessful = false;
                        break;
                    }
                }

                if (updateSuccessful)
                {
                    Log("Finished successfully");
                    Log("Removing backup folder");
                    if (Directory.Exists(backupFolder))
                    {
                        FileSystem.DeleteDirectory(backupFolder);
                    }
                }
                else
                {
                    MessageBox.Show("Update Failed");
                    Log(Logger.SeverityLevel.Error, "Update failed");
                }

                // Start the application only if requested to do so
                if (relaunchApp)
                {
                    Log("Re-launching process {0} with working dir {1}", appPath, appDir);

                    var info = new ProcessStartInfo
                    {
                        UseShellExecute  = true,
                        WorkingDirectory = appDir,
                        FileName         = appPath,
                    };

                    var p = NauIpc.LaunchProcessAndSendDto(dto, info, syncProcessName);
                    if (p == null)
                    {
                        throw new UpdateProcessFailedException("Unable to relaunch application");
                    }
                }

                Log("All done");
                //Application.Exit();
            }
            catch (Exception ex)
            {
                // supressing catch because if at any point we get an error the update has failed
                Log(ex);
            }
            finally
            {
                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();
                }
                if (!string.IsNullOrEmpty(tempFolder))
                {
                    SelfCleanUp(tempFolder);
                }
                Application.Exit();
            }
        }
Пример #12
0
        private static void Main()
        {
            string tempFolder = string.Empty;
            string logFile = string.Empty;
            _args = ArgumentsParser.Get();
            _args.ParseCommandLineArgs();

            var workingDir = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);

            try
            {
                // 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");

                // Load extra assemblies to the app domain, if present
                var availableAssemblies = FileSystem.GetFiles(workingDir, "*.exe|*.dll", SearchOption.TopDirectoryOnly);
                foreach (var assemblyPath in availableAssemblies)
                {
                    if (assemblyPath.Equals(System.Reflection.Assembly.GetEntryAssembly().Location, StringComparison.InvariantCultureIgnoreCase)
                        || assemblyPath.EndsWith("AppUpdate.dll"))
                    {
                        continue;
                    }

                    try
                    {
                        var assembly = System.Reflection.Assembly.LoadFile(assemblyPath);
                    }
                    catch (System.BadImageFormatException ex)
                    {
                    }
                }

                // Connect to the named pipe and retrieve the updates list
                var dto = NauIpc.ReadDto(syncProcessName) as NauIpc.NauDto;

                // Make sure we start updating only once the application has completely terminated
                Thread.Sleep(1000); // hell, let's even wait a bit
                bool createdNew;
                using (var mutex = new Mutex(false, syncProcessName + "Mutex", out createdNew))
                {
                    try
                    {
                        if (!createdNew) mutex.WaitOne();
                    }
                    catch (AbandonedMutexException)
                    {
                        // An abandoned mutex is exactly what we are expecting...
                    }
                    finally
                    {
                    }
                }

                bool updateSuccessful = true;

                if (dto == null || dto.Configs == null) throw new Exception("Invalid DTO received");

                if (dto.LogItems != null) // shouldn't really happen
                {
                }

                // 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 (dto.Tasks == null || dto.Tasks.Count == 0)
                    throw new Exception("Could not find the updates list (or it was empty).");

                //This can be handy if you're trying to debug the updater.exe!
                //#if (DEBUG)
                //{
                //                if (_args.ShowConsole) {
                //                    _console.WriteLine();
                //                    _console.WriteLine("Pausing to attach debugger.  Press any key to continue.");
                //                    _console.ReadKey();
                //                }

                //}
                //#endif

                // Perform the actual off-line update process
                foreach (var t in dto.Tasks)
                {
                    if (t.ExecutionStatus != TaskExecutionStatus.RequiresAppRestart
                        && t.ExecutionStatus != TaskExecutionStatus.RequiresPrivilegedAppRestart)
                    {
                        continue;
                    }

                    // TODO: Better handling on failure: logging, rollbacks
                    try
                    {
                        t.ExecutionStatus = t.Execute(true);
                    }
                    catch (Exception ex)
                    {
                        updateSuccessful = false;
                        t.ExecutionStatus = TaskExecutionStatus.Failed;
                    }

                    if (t.ExecutionStatus == TaskExecutionStatus.Successful) continue;
                    updateSuccessful = false;
                    break;
                }

                if (updateSuccessful)
                {
                    if (Directory.Exists(backupFolder))
                        FileSystem.DeleteDirectory(backupFolder);
                }
                else
                {
                    if (Directory.Exists(backupFolder))
                    {
                        foreach (string backFiles in Directory.GetFiles(backupFolder, "*.*", SearchOption.AllDirectories))
                        {
                            File.Copy(backFiles, backFiles.Replace(backupFolder, appDir));
                        }
                        FileSystem.DeleteDirectory(backupFolder);
                    }
                    MessageBox.Show("Unsuccessful update.  Attempted to revert.");
                }

                // Start the application only if requested to do so
                if (relaunchApp)
                {
                    var info = new ProcessStartInfo
                                {
                                    UseShellExecute = true,
                                    WorkingDirectory = appDir,
                                    FileName = appPath,
                                };

                    var p = NauIpc.LaunchProcessAndSendDto(dto, info, syncProcessName);
                    if (p == null) throw new UpdateProcessFailedException("Unable to relaunch application and/or send DTO");
                }
            }
            catch (Exception ex)
            {
                // supressing catch because if at any point we get an error the update has failed
            }
            finally
            {
                if (!string.IsNullOrEmpty(tempFolder)) SelfCleanUp(tempFolder);
                Application.Exit();
            }
        }