Skip to content

Commit

Permalink
Introducing proper logging capability
Browse files Browse the repository at this point in the history
  • Loading branch information
synhershko committed Jul 11, 2012
1 parent 419e5ba commit 086d2bc
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 106 deletions.
63 changes: 63 additions & 0 deletions src/NAppUpdate.Framework/Common/Logger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;

namespace NAppUpdate.Framework.Common
{
public class Logger
{
[Serializable]
public enum SeverityLevel
{
Debug,
Warning,
Error
}

[Serializable]
public class LogItem
{
public DateTime Timestamp { get; set; }
public string Message { get; set; }
public Exception Exception { get; set; }
public SeverityLevel Severity { get; set; }
}

public List<LogItem> LogItems { get; private set; }

public Logger()
{
LogItems = new List<LogItem>();
}

public Logger(List<LogItem> logItems)
{
LogItems = logItems;
}

public void Log(SeverityLevel severity, string message, params object[] args)
{
LogItems.Add(new LogItem
{
Message = string.Format(message, args),
Severity = severity,
Timestamp = DateTime.Now,
});
}

public void Log(Exception exception)
{
Log(exception, string.Empty);
}

public void Log(Exception exception, string message)
{
LogItems.Add(new LogItem
{
Message = message,
Severity = SeverityLevel.Error,
Timestamp = DateTime.Now,
Exception = exception,
});
}
}
}
1 change: 1 addition & 0 deletions src/NAppUpdate.Framework/NAppUpdate.Framework.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Common\INauFieldsHolder.cs" />
<Compile Include="Common\Logger.cs" />
<Compile Include="Common\NauConfigurations.cs" />
<Compile Include="Common\NauFieldAttribute.cs" />
<Compile Include="Common\UpdateProcessAsyncResult.cs" />
Expand Down
4 changes: 4 additions & 0 deletions src/NAppUpdate.Framework/UpdateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ public enum UpdateProcessState

public IUpdateSource UpdateSource { get; set; }
public IUpdateFeedReader UpdateFeedReader { get; set; }

private Logger _logger = new Logger();

public IEnumerable<IUpdateTask> Tasks { get { return UpdatesToApply; } }

Expand Down Expand Up @@ -430,6 +432,7 @@ public void ApplyUpdates(bool relaunchApplication, bool updaterDoLogging, bool u
AppPath = ApplicationPath,
WorkingDirectory = Environment.CurrentDirectory,
RelaunchApplication = relaunchApplication,
LogItems = _logger.LogItems,
};

NauIpc.ExtractUpdaterFromResource(Config.TempFolder, Instance.Config.UpdateExecutableName);
Expand Down Expand Up @@ -484,6 +487,7 @@ public void ReinstateIfRestarted()
{
Config = dto.Configs;
UpdatesToApply = dto.Tasks;
_logger = new Logger(dto.LogItems);
State = UpdateProcessState.AfterRestart;
}
}
Expand Down
1 change: 1 addition & 0 deletions src/NAppUpdate.Framework/Utils/NauIpc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ internal class NauDto
{
public NauConfigurations Configs { get; set; }
public IList<IUpdateTask> Tasks { get; set; }
public List<Logger.LogItem> LogItems { get; set; }
public string AppPath { get; set; }
public string WorkingDirectory { get; set; }
public bool RelaunchApplication { get; set; }
Expand Down
159 changes: 89 additions & 70 deletions src/NAppUpdate.Updater/AppStart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using System.Diagnostics;
using System.Windows.Forms;
using System.Threading;
using NAppUpdate.Framework;
using NAppUpdate.Framework.Common;
using NAppUpdate.Framework.Tasks;
using NAppUpdate.Framework.Utils;

Expand All @@ -18,25 +20,31 @@ internal static class AppStart
private static void Main()
{
//Debugger.Launch();
string tempFolder = "";
try
string tempFolder = string.Empty;
string logFile = string.Empty;
_args = ArgumentsParser.Get();

_logger = new Logger();
_args.ParseCommandLineArgs();
if (_args.ShowConsole)
{
_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();
}
_console = new ConsoleForm();
_console.Show();
}

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

if (_args.Log)
{
logFile = System.Reflection.Assembly.GetEntryAssembly().Location;
logFile = Path.Combine(Path.GetDirectoryName(logFile), @"logs\NauUpdate.log");

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

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;
Expand All @@ -60,7 +68,7 @@ private static void Main()
catch (AbandonedMutexException)
{
// An abandoned mutex is exactly what we are expecting...
Log("The application has terminated (as expected).");
Log("The application has terminated (as expected)");
}
}

Expand All @@ -71,7 +79,11 @@ private static void Main()
throw new Exception("Invalid DTO received");
}

Log("Got {0} task objects", dto.Tasks.Count);
if (dto.LogItems != null) // shouldn't really happen
{
dto.LogItems.AddRange(_logger.LogItems);
_logger = new Logger(dto.LogItems);
}

// Get some required environment variables
string appPath = dto.AppPath;
Expand All @@ -85,95 +97,79 @@ private static void Main()
throw new Exception("Could not find the updates list (or it was empty).");
}

// Perform the actual off-line update process
Log("Starting the updates...");
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)
{
// TODO: Log message
Log("\tFailed: {0}", ex.Message);
Log(ex);
updateSuccessful = false;
t.ExecutionStatus = TaskExecutionStatus.Failed;
MessageBox.Show("Update failed: " + ex.Message);
}

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

if (updateSuccessful)
{
Log("Finished");
Log("Finished successfully");
Log("Removing backup folder");
if (Directory.Exists(backupFolder))
FileSystem.DeleteDirectory(backupFolder);
}
else
{
MessageBox.Show("Update Failed.");
Log("Update failed.");
MessageBox.Show("Update Failed");
Log(Logger.SeverityLevel.Error, "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("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.");
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.");
}
// supressing catch because if at any point we get an error the update has failed
Log(ex);
}
finally
{
Expand All @@ -192,17 +188,18 @@ private static void SelfCleanUp(string tempFolder)
{
try
{
// Delete the updater EXE and the temp folder)
// Delete the updater EXE and the temp folder
Log("Removing updater and temp folder... {0}", tempFolder);
try
{
var Info = new ProcessStartInfo();
//Application.ExecutablePath
Info.Arguments = string.Format(@"/C ping 1.1.1.1 -n 1 -w 3000 > Nul & echo Y|del ""{0}\*.*"" & rmdir ""{0}"""
, tempFolder);
Info.WindowStyle = ProcessWindowStyle.Hidden;
Info.CreateNoWindow = true;
Info.FileName = "cmd.exe";
var Info = new ProcessStartInfo
{
Arguments = string.Format(@"/C ping 1.1.1.1 -n 1 -w 3000 > Nul & echo Y|del ""{0}\*.*"" & rmdir ""{0}""", tempFolder),
WindowStyle = ProcessWindowStyle.Hidden,
CreateNoWindow = true,
FileName = "cmd.exe"
};

Process.Start(Info);
}
catch { /* ignore exceptions thrown while trying to clean up */ }
Expand All @@ -213,13 +210,35 @@ private static void SelfCleanUp(string tempFolder)
}

private static void Log(string message, params object[] args)
{
Log(Logger.SeverityLevel.Debug, message, args);
}

private static void Log(Logger.SeverityLevel severity, string message, params object[] args)
{
message = string.Format(message, args);
if (_args.Log)
_logger.Log(message);

_logger.Log(severity, message);
if (_args.ShowConsole)
_console.WriteLine(message);

Application.DoEvents();
}

private static void Log(Exception ex)
{
_logger.Log(ex);

if (_args.ShowConsole)
{
_console.WriteLine("*********************************");
_console.WriteLine(" An error has occurred:");
_console.WriteLine(" " + ex.Message);
_console.WriteLine("*********************************");

_console.WriteLine();
_console.WriteLine("The updater will close when you close this window.");
}
}
}
}
Loading

0 comments on commit 086d2bc

Please sign in to comment.