static void Main() { //for some fun try out this command line parameter: chummer://plugin:SINners:Load:5ff55b9d-7d1c-4067-a2f5-774127346f4e PageViewTelemetry pvt = null; var startTime = DateTimeOffset.UtcNow; using (GlobalChummerMutex = new Mutex(false, @"Global\" + strChummerGuid)) { // Set default cultures based on the currently set language CultureInfo.DefaultThreadCurrentCulture = GlobalOptions.CultureInfo; CultureInfo.DefaultThreadCurrentUICulture = GlobalOptions.CultureInfo; string strPostErrorMessage = string.Empty; string settingsDirectoryPath = Path.Combine(Utils.GetStartupPath, "settings"); if (!Directory.Exists(settingsDirectoryPath)) { try { Directory.CreateDirectory(settingsDirectoryPath); } catch (UnauthorizedAccessException ex) { string strMessage = LanguageManager.GetString("Message_Insufficient_Permissions_Warning", GlobalOptions.Language, false); if (string.IsNullOrEmpty(strMessage)) { strMessage = ex.ToString(); } strPostErrorMessage = strMessage; } catch (Exception ex) { strPostErrorMessage = ex.ToString(); } } IsMono = Type.GetType("Mono.Runtime") != null; // Mono doesn't always play nice with ProfileOptimization, so it's better to just not bother with it when running under Mono if (!IsMono) { ProfileOptimization.SetProfileRoot(Utils.GetStartupPath); ProfileOptimization.StartProfile("chummerprofile"); } Stopwatch sw = Stopwatch.StartNew(); //If debugging and launched from other place (Bootstrap), launch debugger if (Environment.GetCommandLineArgs().Contains("/debug") && !Debugger.IsAttached) { Debugger.Launch(); } sw.TaskEnd("dbgchk"); //Various init stuff (that mostly "can" be removed as they serve //debugging more than function //Needs to be called before Log is setup, as it moves where log might be. FixCwd(); sw.TaskEnd("fixcwd"); AppDomain.CurrentDomain.FirstChanceException += ExceptionHeatmap.OnException; sw.TaskEnd("appdomain 2"); string strInfo = string.Format(GlobalOptions.InvariantCultureInfo, "Application Chummer5a build {0} started at {1} with command line arguments {2}", Assembly.GetExecutingAssembly().GetName().Version, DateTime.UtcNow, Environment.CommandLine); sw.TaskEnd("infogen"); sw.TaskEnd("infoprnt"); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); sw.TaskEnd("languagefreestartup"); #if !DEBUG AppDomain.CurrentDomain.UnhandledException += (o, e) => { if (e.ExceptionObject is Exception ex) { CrashHandler.WebMiniDumpHandler(ex); } //main.Hide(); //main.ShowInTaskbar = false; }; #else AppDomain.CurrentDomain.UnhandledException += (o, e) => { try { if (e.ExceptionObject is Exception myException) { myException.Data.Add("IsCrash", bool.TrueString); ExceptionTelemetry et = new ExceptionTelemetry(myException) { SeverityLevel = SeverityLevel.Critical }; //we have to enable the uploading of THIS message, so it isn't filtered out in the DropUserdataTelemetryProcessos foreach (DictionaryEntry d in myException.Data) { if (d.Key != null && d.Value != null) { et.Properties.Add(d.Key.ToString(), d.Value.ToString()); } } ChummerTelemetryClient.TrackException(myException); ChummerTelemetryClient.Flush(); } } catch (Exception exception) { Console.WriteLine(exception); } }; #endif sw.TaskEnd("Startup"); Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException); if (LanguageManager.ManagerErrorMessage.Length > 0) { // MainForm is null at the moment, so we have to show error box manually MessageBox.Show(LanguageManager.ManagerErrorMessage.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (GlobalOptions.ErrorMessage.Length > 0) { // MainForm is null at the moment, so we have to show error box manually MessageBox.Show(GlobalOptions.ErrorMessage.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (!string.IsNullOrEmpty(strPostErrorMessage)) { // MainForm is null at the moment, so we have to show error box manually MessageBox.Show(strPostErrorMessage, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { TelemetryConfiguration.Active.InstrumentationKey = "012fd080-80dc-4c10-97df-4f2cf8c805d5"; LogManager.ThrowExceptions = true; if (GlobalOptions.UseLoggingApplicationInsights > UseAILogging.OnlyMetric) { ConfigurationItemFactory.Default.Targets.RegisterDefinition( "ApplicationInsightsTarget", typeof(ApplicationInsightsTarget) ); } LogManager.ThrowExceptions = false; Log = LogManager.GetCurrentClassLogger(); if (GlobalOptions.UseLogging) { foreach (var rule in LogManager.Configuration.LoggingRules.ToList()) { //only change the loglevel, if it's off - otherwise it has been changed manually if (rule.Levels.Count == 0) { rule.EnableLoggingForLevels(LogLevel.Debug, LogLevel.Fatal); } } } if (Properties.Settings.Default.UploadClientId == Guid.Empty) { Properties.Settings.Default.UploadClientId = Guid.NewGuid(); Properties.Settings.Default.Save(); } if (GlobalOptions.UseLoggingApplicationInsights >= UseAILogging.OnlyMetric) { #if DEBUG //If you set true as DeveloperMode (see above), you can see the sending telemetry in the debugging output window in IDE. TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = true; #else TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = false; #endif TelemetryConfiguration.Active.TelemetryInitializers.Add(new CustomTelemetryInitializer()); TelemetryConfiguration.Active.TelemetryProcessorChainBuilder.Use((next) => new TranslateExceptionTelemetryProcessor(next)); var replacePath = Environment.UserName; TelemetryConfiguration.Active.TelemetryProcessorChainBuilder.Use((next) => new DropUserdataTelemetryProcessor(next, replacePath)); TelemetryConfiguration.Active.TelemetryProcessorChainBuilder.Build(); //for now lets disable live view.We may make another GlobalOption to enable it at a later stage... //var live = new LiveStreamProvider(ApplicationInsightsConfig); //live.Enable(); //Log an Event with AssemblyVersion and CultureInfo MetricIdentifier mi = new MetricIdentifier("Chummer", "Program Start", "Version", "Culture", dimension3Name: "AISetting", dimension4Name: "OSVersion"); string osversion = helpers.Application_Insights.OSVersion.GetOSInfo(); var metric = ChummerTelemetryClient.GetMetric(mi); metric.TrackValue(1, Assembly.GetExecutingAssembly().GetName().Version.ToString(), CultureInfo.CurrentUICulture.TwoLetterISOLanguageName, GlobalOptions.UseLoggingApplicationInsights.ToString(), osversion); //Log a page view: pvt = new PageViewTelemetry("frmChummerMain()") { Name = "Chummer Startup: " + Assembly.GetExecutingAssembly().GetName().Version, Id = Properties.Settings.Default.UploadClientId.ToString() }; pvt.Context.Operation.Name = "Operation Program.Main()"; pvt.Properties.Add("parameters", Environment.CommandLine); pvt.Timestamp = startTime; UploadObjectAsMetric.UploadObject(ChummerTelemetryClient, typeof(GlobalOptions)); } else { TelemetryConfiguration.Active.DisableTelemetry = true; } if (Utils.IsUnitTest) { TelemetryConfiguration.Active.DisableTelemetry = true; } Log.Info(strInfo); Log.Info(new StringBuilder("Logging options are set to ") .Append(GlobalOptions.UseLogging) .Append(" and Upload-Options are set to ") .Append(GlobalOptions.UseLoggingApplicationInsights) .Append(" (Installation-Id: ") .Append(Properties.Settings.Default.UploadClientId.ToString("D", GlobalOptions.InvariantCultureInfo)) .Append(").").ToString()); //make sure the Settings are upgraded/preserved after an upgrade //see for details: https://stackoverflow.com/questions/534261/how-do-you-keep-user-config-settings-across-different-assembly-versions-in-net/534335#534335 if (Properties.Settings.Default.UpgradeRequired) { if (UnblockPath(AppDomain.CurrentDomain.BaseDirectory)) { Properties.Settings.Default.Upgrade(); Properties.Settings.Default.UpgradeRequired = false; Properties.Settings.Default.Save(); } else { Log.Warn("Files could not be unblocked in " + AppDomain.CurrentDomain.BaseDirectory); } } } catch (Exception e) { Console.WriteLine(e); Log.Error(e); #if DEBUG throw; #endif } //load the plugins and maybe work of any command line arguments //arguments come in the form of // /plugin:Name:Parameter:Argument // /plugin:SINners:RegisterUriScheme:0 bool showMainForm = true; // Make sure the default language has been loaded before attempting to open the Main Form. LanguageManager.LoadLanguage(GlobalOptions.Language); MainForm = new frmChummerMain(); try { PluginLoader.LoadPlugins(null); } catch (ApplicationException) { showMainForm = false; } if (!Utils.IsUnitTest) { string[] strArgs = Environment.GetCommandLineArgs(); try { // Hacky, but necessary because innards of Parallel.For would end up invoking // a UI function that would wait for Parallel.For to finish, causing the program // to lock up. Task.Run() delegates Parallel.For to a new thread, preventing this. bool blnIsCompleted = Task.Run(() => { var loopResult = Parallel.For(1, strArgs.Length, i => { if (strArgs[i].Contains("/plugin")) { if (!GlobalOptions.PluginsEnabled) { string msg = "Please enable Plugins to use command-line arguments invoking specific plugin-functions!"; Log.Warn(msg); MainForm.ShowMessageBox(msg, "Plugins not enabled", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } else { string whatplugin = strArgs[i].Substring(strArgs[i].IndexOf("/plugin", StringComparison.Ordinal) + 8); //some external apps choose to add a '/' before a ':' even in the middle of an url... whatplugin = whatplugin.TrimStart(':'); int endplugin = whatplugin.IndexOf(':'); string parameter = whatplugin.Substring(endplugin + 1); whatplugin = whatplugin.Substring(0, endplugin); var plugin = PluginLoader.MyActivePlugins.FirstOrDefault(a => a.ToString() == whatplugin); if (plugin == null) { if (PluginLoader.MyPlugins.All(a => a.ToString() != whatplugin)) { string msg = new StringBuilder("Plugin ").Append(whatplugin) .AppendLine(" is not enabled in the options!") .Append("If you want to use command-line arguments, please enable this plugin and restart the program.").ToString(); Log.Warn(msg); MainForm.ShowMessageBox(msg, whatplugin + " not enabled", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } else { showMainForm &= plugin.ProcessCommandLine(parameter); } } } }); return(loopResult.IsCompleted); }).Result; if (!blnIsCompleted) { Utils.BreakIfDebug(); } } catch (Exception e) { ExceptionTelemetry ex = new ExceptionTelemetry(e) { SeverityLevel = SeverityLevel.Warning }; ChummerTelemetryClient?.TrackException(ex); Log.Warn(e); } } if (showMainForm) { MainForm.MyStartupPVT = pvt; Application.Run(MainForm); } PluginLoader?.Dispose(); Log.Info(ExceptionHeatmap.GenerateInfo()); if (GlobalOptions.UseLoggingApplicationInsights > UseAILogging.OnlyLocal && ChummerTelemetryClient != null) { ChummerTelemetryClient.Flush(); //we have to wait a bit to give it time to upload the data Console.WriteLine("Waiting a bit to flush logging data..."); Thread.Sleep(2000); } } }
static void Main() { using (GlobalChummerMutex = new Mutex(false, @"Global\" + strChummerGuid)) { IsMono = Type.GetType("Mono.Runtime") != null; // Mono doesn't always play nice with ProfileOptimization, so it's better to just not bother with it when running under Mono if (!IsMono) { ProfileOptimization.SetProfileRoot(Application.StartupPath); ProfileOptimization.StartProfile("chummerprofile"); } Stopwatch sw = Stopwatch.StartNew(); //If debuging and launched from other place (Bootstrap), launch debugger if (Environment.GetCommandLineArgs().Contains("/debug") && !Debugger.IsAttached) { Debugger.Launch(); } sw.TaskEnd("dbgchk"); //Various init stuff (that mostly "can" be removed as they serve //debugging more than function //Needs to be called before Log is setup, as it moves where log might be. FixCwd(); sw.TaskEnd("fixcwd"); //Log exceptions that is caught. Wanting to know about this cause of performance AppDomain.CurrentDomain.FirstChanceException += Log.FirstChanceException; AppDomain.CurrentDomain.FirstChanceException += ExceptionHeatmap.OnException; sw.TaskEnd("appdomain 2"); string strInfo = $"Application Chummer5a build {System.Reflection.Assembly.GetExecutingAssembly().GetName().Version} started at {DateTime.UtcNow} with command line arguments {Environment.CommandLine}"; sw.TaskEnd("infogen"); Log.Info(strInfo); sw.TaskEnd("infoprnt"); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); sw.TaskEnd("languagefreestartup"); #if !DEBUG AppDomain.CurrentDomain.UnhandledException += (o, e) => { if (e.ExceptionObject is Exception ex) { CrashHandler.WebMiniDumpHandler(ex); } //main.Hide(); //main.ShowInTaskbar = false; }; #endif sw.TaskEnd("Startup"); Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException); if (!string.IsNullOrEmpty(LanguageManager.ManagerErrorMessage)) { MessageBox.Show(LanguageManager.ManagerErrorMessage, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (!string.IsNullOrEmpty(GlobalOptions.ErrorMessage)) { MessageBox.Show(GlobalOptions.ErrorMessage, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Make sure the default language has been loaded before attempting to open the Main Form. LanguageManager.TranslateWinForm(GlobalOptions.Language, null); MainForm = new frmChummerMain(); Application.Run(MainForm); Log.Info(ExceptionHeatmap.GenerateInfo()); } }
static void Main() { PageViewTelemetry pvt = null; var startTime = DateTimeOffset.UtcNow; using (GlobalChummerMutex = new Mutex(false, @"Global\" + strChummerGuid)) { IsMono = Type.GetType("Mono.Runtime") != null; // Mono doesn't always play nice with ProfileOptimization, so it's better to just not bother with it when running under Mono if (!IsMono) { ProfileOptimization.SetProfileRoot(Utils.GetStartupPath); ProfileOptimization.StartProfile("chummerprofile"); } Stopwatch sw = Stopwatch.StartNew(); //If debuging and launched from other place (Bootstrap), launch debugger if (Environment.GetCommandLineArgs().Contains("/debug") && !Debugger.IsAttached) { Debugger.Launch(); } sw.TaskEnd("dbgchk"); //Various init stuff (that mostly "can" be removed as they serve //debugging more than function //Needs to be called before Log is setup, as it moves where log might be. FixCwd(); sw.TaskEnd("fixcwd"); AppDomain.CurrentDomain.FirstChanceException += ExceptionHeatmap.OnException; sw.TaskEnd("appdomain 2"); string strInfo = $"Application Chummer5a build {System.Reflection.Assembly.GetExecutingAssembly().GetName().Version} started at {DateTime.UtcNow} with command line arguments {Environment.CommandLine}"; sw.TaskEnd("infogen"); sw.TaskEnd("infoprnt"); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); sw.TaskEnd("languagefreestartup"); #if !DEBUG AppDomain.CurrentDomain.UnhandledException += (o, e) => { if (e.ExceptionObject is Exception ex) { CrashHandler.WebMiniDumpHandler(ex); } //main.Hide(); //main.ShowInTaskbar = false; }; #endif AppDomain.CurrentDomain.UnhandledException += (o, e) => { try { if (e.ExceptionObject is Exception myException) { TelemetryClient tc = new TelemetryClient(); tc.TrackException(myException); } } catch (Exception exception) { Console.WriteLine(exception); } }; sw.TaskEnd("Startup"); Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException); if (!string.IsNullOrEmpty(LanguageManager.ManagerErrorMessage)) { MessageBox.Show(LanguageManager.ManagerErrorMessage, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (!string.IsNullOrEmpty(GlobalOptions.ErrorMessage)) { MessageBox.Show(GlobalOptions.ErrorMessage, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { LogManager.ThrowExceptions = true; ConfigurationItemFactory.Default.Targets.RegisterDefinition( "ApplicationInsightsTarget", typeof(Microsoft.ApplicationInsights.NLogTarget.ApplicationInsightsTarget) ); LogManager.ThrowExceptions = false; Log = NLog.LogManager.GetCurrentClassLogger(); if (GlobalOptions.UseLogging) { foreach (var rule in NLog.LogManager.Configuration.LoggingRules.ToList()) { //only change the loglevel, if it's off - otherwise it has been changed manually if (rule.Levels.Count == 0) { rule.EnableLoggingForLevels(LogLevel.Debug, LogLevel.Fatal); } } } Log.Info(strInfo); if (GlobalOptions.UseLoggingApplicationInsights) { #if DEBUG //If you set true as DeveloperMode (see above), you can see the sending telemetry in the debugging output window in IDE. TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = true; #else TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = false; #endif TelemetryConfiguration.Active.TelemetryInitializers.Add(new CustomTelemetryInitializer()); TelemetryConfiguration.Active.TelemetryProcessorChainBuilder.Use((next) => new TranslateExceptionTelemetryProcessor(next)); var replacePath = Environment.UserName; TelemetryConfiguration.Active.TelemetryProcessorChainBuilder.Use((next) => new DropUserdataTelemetryProcessor(next, replacePath)); TelemetryConfiguration.Active.TelemetryProcessorChainBuilder.Build(); //for now lets disable live view. We may make another GlobalOption to enable it at a later stage... //var live = new LiveStreamProvider(ApplicationInsightsConfig); //live.Enable(); //Log an Event with AssemblyVersion and CultureInfo if (Properties.Settings.Default.UploadClientId == Guid.Empty) { Properties.Settings.Default.UploadClientId = Guid.NewGuid(); Properties.Settings.Default.Save(); } MetricIdentifier mi = new MetricIdentifier("Chummer", "Program Start", "Version", "Culture"); var metric = TelemetryClient.GetMetric(mi); metric.TrackValue(1, Assembly.GetExecutingAssembly().GetName().Version.ToString(), CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); // Log a page view: pvt = new PageViewTelemetry("frmChummerMain()") { Name = "Chummer Startup: " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version }; pvt.Id = Properties.Settings.Default.UploadClientId.ToString(); pvt.Context.Operation.Name = "Operation Program.Main()"; pvt.Properties.Add("parameters", Environment.CommandLine); pvt.Timestamp = startTime; UploadObjectAsMetric.UploadObject(TelemetryClient, typeof(GlobalOptions)); } else { TelemetryConfiguration.Active.DisableTelemetry = true; } if (Utils.IsUnitTest) { TelemetryConfiguration.Active.DisableTelemetry = true; } //make sure the Settings are upgraded/preserved after an upgrade //see for details: https://stackoverflow.com/questions/534261/how-do-you-keep-user-config-settings-across-different-assembly-versions-in-net/534335#534335 if (Properties.Settings.Default.UpgradeRequired) { if (UnblockPath(AppDomain.CurrentDomain.BaseDirectory)) { Properties.Settings.Default.Upgrade(); Properties.Settings.Default.UpgradeRequired = false; Properties.Settings.Default.Save(); } else { Log.Warn("Files could not be unblocked in " + AppDomain.CurrentDomain.BaseDirectory); } } } catch (Exception e) { Console.WriteLine(e); Log.Error(e); } // Make sure the default language has been loaded before attempting to open the Main Form. LanguageManager.TranslateWinForm(GlobalOptions.Language, null); MainForm = new frmChummerMain(false, pvt); Application.Run(MainForm); Log.Info(ExceptionHeatmap.GenerateInfo()); if (GlobalOptions.UseLoggingApplicationInsights) { if (TelemetryClient != null) { //if (pvt != null) //{ // pvt.Duration = DateTimeOffset.UtcNow - pvt.Timestamp; // ApplicationInsightsTelemetryClient.TrackPageView(pvt); //} TelemetryClient.Flush(); //we have to wait a bit to give it time to upload the data Console.WriteLine("Waiting a bit to flush logging data..."); Thread.Sleep(5000); } } } }