Files
Aleksandar Pesic 7f816d96cc async/await pattern improved in FluentTerminal.SystemTray project (#648)
* Continuation options and code cosmetics in async methods.

* ConfigureAwait in FluentTerminal.App.ViewModels project adjusted.

* async/await in FluentTerminal.SystemTray project.
2020-01-08 18:42:59 +01:00

128 lines
6.4 KiB
C#

using Autofac;
using FluentTerminal.App.Services;
using FluentTerminal.App.Services.Adapters;
using FluentTerminal.App.Services.Implementation;
using FluentTerminal.SystemTray.Services;
using GlobalHotKey;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Threading;
using Windows.Storage;
namespace FluentTerminal.SystemTray
{
public static class Program
{
private const string MutexName = "FluentTerminalMutex";
[STAThread]
public static void Main(string[] args)
{
if (!Mutex.TryOpenExisting(MutexName, out _))
{
using (new Mutex(false, MutexName))
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
JsonConvert.DefaultSettings = () =>
{
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
};
settings.Converters.Add(new StringEnumConverter(typeof(CamelCaseNamingStrategy)));
return settings;
};
var applicationDataContainers = new ApplicationDataContainers
{
LocalSettings = new ApplicationDataContainerAdapter(ApplicationData.Current.LocalSettings),
RoamingSettings = new ApplicationDataContainerAdapter(ApplicationData.Current.RoamingSettings),
KeyBindings = new ApplicationDataContainerAdapter(ApplicationData.Current.RoamingSettings.CreateContainer(Constants.KeyBindingsContainerName, ApplicationDataCreateDisposition.Always)),
ShellProfiles = new ApplicationDataContainerAdapter(ApplicationData.Current.LocalSettings.CreateContainer(Constants.ShellProfilesContainerName, ApplicationDataCreateDisposition.Always)),
Themes = new ApplicationDataContainerAdapter(ApplicationData.Current.RoamingSettings.CreateContainer(Constants.ThemesContainerName, ApplicationDataCreateDisposition.Always))
};
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterInstance(applicationDataContainers);
containerBuilder.RegisterType<NotificationService>().As<INotificationService>().InstancePerDependency();
containerBuilder.RegisterType<TerminalsManager>().SingleInstance();
containerBuilder.RegisterType<ToggleWindowService>().SingleInstance();
containerBuilder.RegisterInstance(new HotKeyManager()).SingleInstance();
containerBuilder.RegisterType<SystemTrayApplicationContext>().SingleInstance();
containerBuilder.RegisterType<AppCommunicationService>().SingleInstance();
containerBuilder.RegisterType<DefaultValueProvider>().As<IDefaultValueProvider>();
containerBuilder.RegisterType<SettingsService>().As<ISettingsService>().SingleInstance();
containerBuilder.RegisterType<UpdateService>().As<IUpdateService>().SingleInstance();
containerBuilder.RegisterInstance(Dispatcher.CurrentDispatcher).SingleInstance();
var container = containerBuilder.Build();
// TODO: It's maybe better to wait for logging to be configured before continuing?
// ReSharper disable once AssignmentIsFullyDiscarded
_ = ConfigureLoggingAsync();
var appCommunicationService = container.Resolve<AppCommunicationService>();
if (args.Length > 0 && args[2] == "appLaunched")
{
// ReSharper disable once AssignmentIsFullyDiscarded
_ = appCommunicationService.StartAppServiceConnectionAsync();
}
#if !STORE
// ReSharper disable once AssignmentIsFullyDiscarded
_ = Task.Factory.StartNew(() => container.Resolve<IUpdateService>().CheckForUpdateAsync());
#endif
var settingsService = container.Resolve<ISettingsService>();
// ReSharper disable once AssignmentIsFullyDiscarded
_ = Task.Factory.StartNew(() => Utilities.MuteTerminal(settingsService.GetApplicationSettings().MuteTerminalBeeps));
if (settingsService.GetApplicationSettings().EnableTrayIcon)
{
Application.Run(container.Resolve<SystemTrayApplicationContext>());
}
else
{
Application.Run();
}
}
}
else
{
var eventWaitHandle = EventWaitHandle.OpenExisting(AppCommunicationService.EventWaitHandleName, System.Security.AccessControl.EventWaitHandleRights.Modify);
eventWaitHandle.Set();
}
}
private static async Task ConfigureLoggingAsync()
{
var logDirectory = await ApplicationData.Current.LocalCacheFolder.CreateFolderAsync("Logs", CreationCollisionOption.OpenIfExists).AsTask().ConfigureAwait(false);
var logFile = Path.Combine(logDirectory.Path, "fluentterminal.systemtray.log");
var configFile = await logDirectory.CreateFileAsync("config.json", CreationCollisionOption.OpenIfExists).AsTask().ConfigureAwait(false);
var configContent = await FileIO.ReadTextAsync(configFile).AsTask().ConfigureAwait(false);
var config = JsonConvert.DeserializeObject<Logger.Configuration>(configContent) ?? new Logger.Configuration();
Logger.Instance.Initialize(logFile, config);
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
TaskScheduler.UnobservedTaskException += (sender, e) =>
Logger.Instance.Error(e.Exception, "Unobserved Task Exception");
}
private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Logger.Instance.Error((Exception)e.ExceptionObject, "Unhandled Exception");
}
}
}