/// <summary> /// Shuts down the Application Insights Logging functionality /// and flushes any pending requests. /// /// This handles start and stop times and the application lifetime /// log entry that logs duration of operation. /// </summary> public static void ShutdownLogging() { if (Configuration.System.SendTelemetry && Telemetry.UseApplicationInsights && AppInsights != null) { var t = AppRunTelemetry.Telemetry; // multi-instance shutdown - ignore if (t.Properties.ContainsKey("usage")) { return; } t.Properties.Add("usage", Configuration.ApplicationUpdates.AccessCount.ToString()); t.Properties.Add("registered", UnlockKey.IsAppRegistered().ToString()); t.Properties.Add("version", GetVersion()); t.Properties.Add("dotnetversion", MarkdownMonster.Utilities.mmWindowsUtils.GetDotnetVersion()); t.Properties.Add("culture", CultureInfo.CurrentUICulture.IetfLanguageTag); t.Stop(); try { AppInsights.StopOperation(AppRunTelemetry); } catch (Exception ex) { LogLocal("Failed to Stop Telemetry Client: " + ex.GetBaseException().Message); } AppInsights.Flush(); AppInsights = null; AppRunTelemetry.Dispose(); } }
/// <summary> /// Renders markdown of the current document text into raw HTML /// </summary> /// <param name="markdown">markdown to render</param> /// <param name="renderLinksExternal">Determines whether links have a target='top' attribute</param> /// <param name="usePragmaLines">renders line numbers into html output as ID tags for editor positioning</param> /// <returns></returns> public string RenderHtml(string markdown = null, bool renderLinksExternal = false, bool usePragmaLines = false) { if (string.IsNullOrEmpty(markdown)) { markdown = CurrentText; } var parser = MarkdownParserFactory.GetParser(usePragmaLines: usePragmaLines, forceLoad: true, parserAddinId: mmApp.Configuration.MarkdownOptions.MarkdownParserName); var html = parser.Parse(markdown); if (!string.IsNullOrEmpty(html) && !UnlockKey.IsRegistered() && mmApp.Configuration.ApplicationUpdates.AccessCount > 20) { html += @" <div style=""margin-top: 30px;margin-bottom: 10px;font-size: 0.8em;border-top: 1px solid #eee;padding-top: 8px;opacity: 0.75;"" title=""This message doesn't display in the registered version of Markdown Monster.""> <img src=""https://markdownmonster.west-wind.com/favicon.png"" style=""height: 20px;float: left; margin-right: 10px;opacity: 0.75;""/> created with the free version of <a href=""https://markdownmonster.west-wind.com"" target=""top"">Markdown Monster</a> </div> "; } return(html); }
public static void Shutdown(bool errorShutdown = false) { if (Configuration.SendTelemetry && Telemetry.UseApplicationInsights && AppInsights != null) { var t = AppRunTelemetry.Telemetry; t.Properties.Add("usage", Configuration.ApplicationUpdates.AccessCount.ToString()); t.Properties.Add("registered", UnlockKey.IsRegistered().ToString()); t.Properties.Add("version", GetVersion()); t.Properties.Add("dotnetversion", ComputerInfo.GetDotnetVersion()); t.Stop(); try { AppInsights.StopOperation(AppRunTelemetry); } catch (Exception ex) { LogToLogfile("Failed to Stop Telemetry Client: " + ex.GetBaseException().Message); } AppInsights.Flush(); AppInsights = null; } else { SendTelemetry("shutdown"); } }
public static void SendTelemetry(string operation, string data = null) { var v = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location); string version = v.FileMajorPart + "." + v.FileMinorPart; var t = new Telemetry { Version = version, Registered = UnlockKey.IsRegistered(), Access = mmApp.Configuration.ApplicationUpdates.AccessCount, Operation = operation, Time = Convert.ToInt32((DateTime.UtcNow - Started).TotalSeconds), Data = data }; try { HttpUtils.JsonRequest <string>(new HttpRequestSettings() { Url = mmApp.Configuration.TelemetryUrl, HttpVerb = "POST", Content = t, Timeout = 300 }); } catch (Exception ex2) { // don't log with exception otherwise we get an endless loop Log("Unable to send telemetry: " + ex2.Message); } }
/// <summary> /// Logs messages to the standard log output for Markdown Monster: /// /// * Application Insights /// * Local Log File /// /// </summary> /// <param name="msg"></param> public static void Log(string msg, Exception ex = null, bool unhandledException = false, LogLevels logLevel = LogLevels.Error) { string version = GetVersion(); string winVersion = null; if (Telemetry.UseApplicationInsights && AppRunTelemetry?.Telemetry != null) { var secs = (int) DateTimeOffset.UtcNow.Subtract(AppRunTelemetry.Telemetry.Timestamp).TotalSeconds; if (ex != null) { AppRunTelemetry.Telemetry.Success = false; AppInsights.TrackException(ex, new Dictionary<string, string> { {"msg", msg}, {"exmsg", ex.Message}, {"exbasemsg", ex.GetBaseException().Message}, {"exsource", ex.Source}, {"extrace", ex.StackTrace}, {"severity", unhandledException ? "unhandled" : ""}, {"version", version}, {"winversion", winVersion}, {"dotnetversion", MarkdownMonster.Utilities.mmWindowsUtils.GetDotnetVersion()}, {"usage", Configuration.ApplicationUpdates.AccessCount.ToString()}, {"registered", UnlockKey.IsAppRegistered().ToString()}, {"culture", CultureInfo.CurrentCulture.IetfLanguageTag}, {"uiculture", CultureInfo.CurrentUICulture.IetfLanguageTag}, {"seconds", secs.ToString() }, {"level", ((int) logLevel).ToString() + " - " + logLevel.ToString()} }); } else { // message only var props = new Dictionary<string, string>() { {"msg", msg}, {"usage", Configuration.ApplicationUpdates.AccessCount.ToString()}, {"registered", UnlockKey.IsAppRegistered().ToString()}, {"version", GetVersion()}, {"culture", CultureInfo.CurrentCulture.IetfLanguageTag}, {"uiculture", CultureInfo.CurrentUICulture.IetfLanguageTag}, {"seconds", secs.ToString() }, {"level", ((int) logLevel).ToString() + " - " + logLevel.ToString() } }; AppInsights.TrackTrace(msg, props); } } // also log to the local error log LogLocal(msg,ex); }
/// <summary> /// Logs messages to the standard log output for Markdown Monster: /// /// * Application Insights /// * Local Log File /// /// </summary> /// <param name="msg"></param> public static void Log(string msg, Exception ex = null, bool unhandledException = false) { string version = GetVersion(); string winVersion = null; if (Telemetry.UseApplicationInsights) { if (ex != null) { AppRunTelemetry.Telemetry.Success = false; AppInsights.TrackException(ex, new Dictionary <string, string> { { "msg", msg }, { "exmsg", ex.Message }, { "exsource", ex.Source }, { "extrace", ex.StackTrace }, { "severity", unhandledException ? "unhandled" : "" }, { "version", version }, { "winversion", winVersion }, { "dotnetversion", WindowsUtils.GetDotnetVersion() }, { "usage", Configuration.ApplicationUpdates.AccessCount.ToString() }, { "registered", UnlockKey.IsRegistered().ToString() }, { "culture", CultureInfo.CurrentCulture.IetfLanguageTag }, { "uiculture", CultureInfo.CurrentUICulture.IetfLanguageTag } }); } else { // message only var props = new Dictionary <string, string>() { { "msg", msg }, { "usage", Configuration.ApplicationUpdates.AccessCount.ToString() }, { "registered", UnlockKey.IsRegistered().ToString() }, { "version", GetVersion() }, { "culture", CultureInfo.CurrentCulture.IetfLanguageTag }, { "uiculture", CultureInfo.CurrentUICulture.IetfLanguageTag } }; AppInsights.TrackTrace(msg, props); } } // also log to the local error log LogLocal(msg, ex); }
public static void Shutdown(bool errorShutdown = false) { if (Configuration.SendTelemetry && Telemetry.UseApplicationInsights && AppInsights != null) { var t = AppRunTelemetry.Telemetry; // multi-instance shutdown - ignore if (t.Properties.ContainsKey("usage")) { return; } t.Properties.Add("usage", Configuration.ApplicationUpdates.AccessCount.ToString()); t.Properties.Add("registered", UnlockKey.IsRegistered().ToString()); t.Properties.Add("version", GetVersion()); t.Properties.Add("dotnetversion", WindowsUtils.GetDotnetVersion()); t.Properties.Add("culture", CultureInfo.CurrentUICulture.IetfLanguageTag); t.Stop(); try { AppInsights.StopOperation(AppRunTelemetry); } catch (Exception ex) { LogLocal("Failed to Stop Telemetry Client: " + ex.GetBaseException().Message); } AppInsights.Flush(); AppInsights = null; AppRunTelemetry.Dispose(); } else { SendTelemetry("shutdown"); } var tempPath = Path.GetTempPath(); // Cleanup temp files File.Delete(Path.Combine(tempPath, "_MarkdownMonster_Preview.html")); FileUtils.DeleteTimedoutFiles(Path.Combine(tempPath, "mm_diff_*.*"), 1); }
protected override void OnClosing(CancelEventArgs e) { base.OnClosing(e); Hide(); bool isNewVersion = CheckForNewVersion(false, false); mmApp.Configuration.ApplicationUpdates.AccessCount++; SaveSettings(); if (!CloseAllTabs()) { Show(); e.Cancel = true; return; } if (mmApp.Configuration.UseSingleWindow) { PipeManager?.StopServer(); if (App.Mutex != null) { App.Mutex.Dispose(); } } if (!isNewVersion && mmApp.Configuration.ApplicationUpdates.AccessCount % 5 == 0 && !UnlockKey.IsRegistered()) { Hide(); var rd = new RegisterDialog(); rd.Owner = this; rd.ShowDialog(); } mmApp.SendTelemetry("shutdown"); e.Cancel = false; }
public static void SendTelemetry(string operation, string data = null) { if (!Configuration.SendTelemetry) { return; } bool isRegistered = UnlockKey.IsRegistered(); int accessCount = mmApp.Configuration.ApplicationUpdates.AccessCount; string version = GetVersion(); var t = new Telemetry { Version = version, Registered = isRegistered, Access = accessCount, Operation = operation, Time = Convert.ToInt32((DateTime.UtcNow - Started).TotalSeconds), Data = data }; try { HttpUtils.JsonRequest <string>(new HttpRequestSettings() { Url = mmApp.Configuration.TelemetryUrl, HttpVerb = "POST", Content = t, Timeout = 1000 }); } catch (Exception ex2) { // don't log with exception otherwise we get an endless loop Log("Unable to send telemetry: " + ex2.Message); } }
/// <summary> /// Starts the Application Insights logging functionality /// Note: this should be set on application startup once /// and will not fire multiple times. /// </summary> public static void InitializeLogging() { try { if (Configuration.System.SendTelemetry && Telemetry.UseApplicationInsights && AppInsights == null) { AppInsights = new TelemetryClient { InstrumentationKey = Telemetry.Key }; AppInsights.Context.Session.Id = Guid.NewGuid().ToString(); AppInsights.Context.Component.Version = GetVersion(); AppRunTelemetry = AppInsights.StartOperation <RequestTelemetry>( $"{GetVersion()} - {Configuration.ApplicationUpdates.AccessCount + 1} - {(UnlockKey.IsAppRegistered() ? "registered" : "unregistered")}"); AppRunTelemetry.Telemetry.Start(); } } catch (Exception ex) { Telemetry.UseApplicationInsights = false; LogLocal("Application Insights initialization failure: " + ex.GetBaseException().Message); } }
/// <summary> /// Logs messages to the log file /// </summary> /// <param name="msg"></param> public static void Log(string msg, Exception ex = null, bool unhandledException = false) { string version = GetVersion(); string winVersion = null; string exMsg = string.Empty; if (ex != null) { winVersion = ComputerInfo.GetWindowsVersion() + " - " + CultureInfo.CurrentUICulture.IetfLanguageTag + " - NET " + ComputerInfo.GetDotnetVersion() + " - " + (Environment.Is64BitProcess ? "64 bit" : "32 bit"); ex = ex.GetBaseException(); exMsg = $@" Markdown Monster v{version} {winVersion} --- {ex.Source} {ex.StackTrace} --------------------------- "; SendBugReport(ex, msg); } if (Telemetry.UseApplicationInsights) { if (ex != null) { AppRunTelemetry.Telemetry.Success = false; AppInsights.TrackException(ex, new Dictionary <string, string> { { "msg", msg }, { "exmsg", ex.Message }, { "exsource", ex.Source }, { "extrace", ex.StackTrace }, { "severity", unhandledException ? "unhandled" : "" }, { "version", version }, { "winversion", winVersion }, { "usage", Configuration.ApplicationUpdates.AccessCount.ToString() }, { "registered", UnlockKey.IsRegistered().ToString() } }); } else { var props = new Dictionary <string, string>() { { "msg", msg }, { "version", GetVersion() }, { "usage", Configuration.ApplicationUpdates.AccessCount.ToString() }, { "registered", UnlockKey.IsRegistered().ToString() } }; AppInsights.TrackTrace(msg, props); } } var text = msg + exMsg; LogToLogfile(text); }
/// <summary> /// Renders markdown of the current document text into raw HTML /// </summary> /// <param name="markdown">markdown to render</param> /// <param name="renderLinksExternal">Determines whether links have a target='top' attribute</param> /// <param name="usePragmaLines">renders line numbers into html output as ID tags for editor positioning</param> /// <returns></returns> public string RenderHtml(string markdown = null, bool renderLinksExternal = false, bool usePragmaLines = false) { if (string.IsNullOrEmpty(markdown)) { markdown = CurrentText; } if (string.IsNullOrEmpty(markdown)) { return(markdown); } OnBeforeDocumentRendered(ref markdown); var parser = MarkdownParserFactory.GetParser(usePragmaLines: usePragmaLines, forceLoad: true, parserAddinId: mmApp.Configuration.MarkdownOptions.MarkdownParserName); if (!string.IsNullOrEmpty(PreviewWebRootPath)) { var path = FileUtils.AddTrailingSlash(PreviewWebRootPath).Replace("\\", "/"); markdown = markdown.Replace("](~/", "](" + path); markdown = markdown.Replace("](/", "](" + path); } // allow override of RenderScriptTags if set var oldAllowScripts = mmApp.Configuration.MarkdownOptions.AllowRenderScriptTags; if (ProcessScripts) { mmApp.Configuration.MarkdownOptions.AllowRenderScriptTags = false; } var html = parser.Parse(markdown); mmApp.Configuration.MarkdownOptions.AllowRenderScriptTags = oldAllowScripts; OnDocumentRendered(ref html, ref markdown); if (!string.IsNullOrEmpty(html) && !UnlockKey.IsRegistered() && mmApp.Configuration.ApplicationUpdates.AccessCount > 20) { html += @" <div style=""margin-top: 30px;margin-bottom: 10px;font-size: 0.8em;border-top: 1px solid #eee;padding-top: 8px;cursor: pointer;"" title=""This message doesn't display in the registered version of Markdown Monster."" onclick=""window.open('https://markdownmonster.west-wind.com')""> <img src=""https://markdownmonster.west-wind.com/favicon.png"" style=""height: 20px;float: left; margin-right: 10px;""/> created with the free version of <a href=""https://markdownmonster.west-wind.com"" target=""top"">Markdown Monster</a> </div> "; } return(html); }
private void HandleCommandLineArguments(string[] commandArgs) { var arg0 = CommandArgs[0].ToLower().TrimStart('-'); if (CommandArgs[0] == "-") { arg0 = "-"; } if (Environment.CommandLine.Contains("-presentation")) { StartInPresentationMode = true; } switch (arg0) { case "version": // just display the header break; case "uninstall": _noStart = true; UninstallSettings(); ConsoleHeader(); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Markdown Monster Machine Wide Settings uninstalled."); ConsoleFooter(); break; case "reset": // load old config and backup mmApp.Configuration.Backup(); mmApp.Configuration.Reset(); // forces exit ConsoleHeader(); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Markdown Monster Settings reset to defaults."); ConsoleFooter(); break; case "setportable": ConsoleHeader(); // Note: Startup logic to handle portable startup is in AppConfiguration::FindCommonFolder try { string portableSettingsFolder = Path.Combine(InitialStartDirectory, "PortableSettings"); bool exists = Directory.Exists(portableSettingsFolder); string oldCommonFolder = mmApp.Configuration.CommonFolder; File.WriteAllText("_IsPortable", @"forces the settings to be read from .\PortableSettings rather than %appdata%"); if (!exists && Directory.Exists(oldCommonFolder) && MessageBox.Show( "Portable mode set. Do you want to copy settings from:\r\n\r\n" + oldCommonFolder + "\r\n\r\nto the PortableSettings folder?", "Markdown MonsterPortable Mode", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) { FileUtils.CopyDirectory(oldCommonFolder, portableSettingsFolder, deepCopy: true); mmApp.Configuration.CommonFolder = portableSettingsFolder; mmApp.Configuration.Read(); } mmApp.Configuration.CommonFolder = portableSettingsFolder; mmApp.Configuration.Write(); } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Unable to set portable mode: " + ex.Message); } ConsoleFooter(); break; case "unsetportable": ConsoleHeader(); try { File.Delete("_IsPortable"); mmApp.Configuration.InternalCommonFolder = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Markdown Monster"); mmApp.Configuration.CommonFolder = mmApp.Configuration.InternalCommonFolder; mmApp.Configuration.Write(); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Removed Portable settings for this installation. Use `mm SetPortable` to reenable."); } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"Unable to delete portable settings switch file\r\n_IsPortable\r\n\r\n{ex.Message}"); } break; case "register": ConsoleHeader(); if (CommandArgs.Length < 2) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Missing registration code. Please pass a registration code."); } else { if (!UnlockKey.Register(CommandArgs[1])) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Invalid registration code. Please pass a valid registration code."); } else { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Registration succeeded. Thank your for playing fair."); } } ConsoleFooter(); break; // Standard In Re-Routing case "stdin": string stdin = null; if (Console.IsInputRedirected) { using (var stream = Console.OpenStandardInput()) { byte[] buffer = new byte[1000]; // Use whatever size you want var builder = new StringBuilder(); int read = -1; while (true) { var gotInput = new AutoResetEvent(false); var inputThread = new Thread(() => { try { read = stream.Read(buffer, 0, buffer.Length); gotInput.Set(); } catch (ThreadAbortException) { Thread.ResetAbort(); } }) { IsBackground = true }; inputThread.Start(); // Timeout expired? if (!gotInput.WaitOne(100)) { inputThread.Abort(); break; } // End of stream? if (read == 0) { stdin = builder.ToString(); break; } // Got data builder.Append(Console.InputEncoding.GetString(buffer, 0, read)); } if (builder.Length > 0) { var tempFile = Path.ChangeExtension(Path.GetTempFileName(), "md"); File.WriteAllText(tempFile, builder.ToString()); CommandArgs[0] = tempFile; } else { CommandArgs[0] = null; } } } break; } }
public static void ApplicationStart() { Started = DateTime.UtcNow; if (Telemetry.UseApplicationInsights) { AppInsights = new TelemetryClient { InstrumentationKey = Telemetry.Key }; AppInsights.Context.Session.Id = Guid.NewGuid().ToString(); AppInsights.Context.Component.Version = GetVersion(); AppRunTelemetry = AppInsights.StartOperation <RequestTelemetry>($"App Run - {GetVersion()} - {Configuration.ApplicationUpdates.AccessCount + 1} - {(UnlockKey.IsRegistered() ? "registered" : "unregistered")}"); AppRunTelemetry.Telemetry.Start(); } }