├── .gitignore ├── .gitmodules ├── ExternalLibs ├── FastColoredTextBox.dll └── FastColoredTextBox.xml ├── README.md ├── RequestAnalyzer ├── App.config ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── RequestAnalyzer.csproj ├── SvclogViewer.sln ├── SvclogViewer ├── Config │ └── Configuration.cs ├── DefaultAssociationHelper.cs ├── Entities │ └── TraceEvent.cs ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ ├── Settings.settings │ └── app.manifest ├── SvcAnalyzer.cs ├── SvcAnalyzerDropper.Designer.cs ├── SvcAnalyzerDropper.cs ├── SvcAnalyzerDropper.resx ├── SvcIndexer.cs ├── SvclogViewer.csproj ├── SwitchableTextBox.Designer.cs ├── SwitchableTextBox.cs ├── app.config ├── appicon.ico ├── changes.txt ├── htmlDesc.xml └── xmlDesc.xml └── packages ├── Microsoft.AspNet.Mvc.4.0.20710.0 ├── Microsoft.AspNet.Mvc.4.0.20710.0.nupkg └── lib │ └── net40 │ ├── System.Web.Mvc.dll │ └── System.Web.Mvc.xml ├── Microsoft.AspNet.Razor.2.0.20710.0 ├── Microsoft.AspNet.Razor.2.0.20710.0.nupkg └── lib │ └── net40 │ ├── System.Web.Razor.dll │ └── System.Web.Razor.xml ├── Microsoft.AspNet.WebApi.4.0.20710.0 └── Microsoft.AspNet.WebApi.4.0.20710.0.nupkg ├── Microsoft.AspNet.WebApi.Client.4.0.20710.0 ├── Microsoft.AspNet.WebApi.Client.4.0.20710.0.nupkg └── lib │ └── net40 │ ├── System.Net.Http.Formatting.dll │ └── System.Net.Http.Formatting.xml ├── Microsoft.AspNet.WebApi.Core.4.0.20710.0 ├── Microsoft.AspNet.WebApi.Core.4.0.20710.0.nupkg ├── content │ └── web.config.transform └── lib │ └── net40 │ ├── System.Web.Http.dll │ └── System.Web.Http.xml ├── Microsoft.AspNet.WebApi.WebHost.4.0.20710.0 ├── Microsoft.AspNet.WebApi.WebHost.4.0.20710.0.nupkg └── lib │ └── net40 │ ├── System.Web.Http.WebHost.dll │ └── System.Web.Http.WebHost.xml ├── Microsoft.AspNet.WebPages.2.0.20710.0 ├── Microsoft.AspNet.WebPages.2.0.20710.0.nupkg └── lib │ └── net40 │ ├── System.Web.Helpers.dll │ ├── System.Web.Helpers.xml │ ├── System.Web.WebPages.Deployment.dll │ ├── System.Web.WebPages.Deployment.xml │ ├── System.Web.WebPages.Razor.dll │ ├── System.Web.WebPages.Razor.xml │ ├── System.Web.WebPages.dll │ └── System.Web.WebPages.xml ├── Microsoft.Net.Http.2.0.20710.0 ├── Microsoft.Net.Http.2.0.20710.0.nupkg └── lib │ ├── net40 │ ├── System.Net.Http.WebRequest.dll │ ├── System.Net.Http.WebRequest.xml │ ├── System.Net.Http.dll │ └── System.Net.Http.xml │ └── net45 │ └── _._ ├── Microsoft.Web.Infrastructure.1.0.0.0 ├── Microsoft.Web.Infrastructure.1.0.0.0.nupkg └── lib │ └── net40 │ └── Microsoft.Web.Infrastructure.dll ├── Newtonsoft.Json.4.5.6 ├── Newtonsoft.Json.4.5.6.nupkg └── lib │ └── net40 │ ├── Newtonsoft.Json.dll │ └── Newtonsoft.Json.xml ├── jQuery.1.9.1 ├── Content │ └── Scripts │ │ ├── jquery-1.9.1-vsdoc.js │ │ ├── jquery-1.9.1.js │ │ ├── jquery-1.9.1.min.js │ │ └── jquery-1.9.1.min.map ├── Tools │ ├── common.ps1 │ ├── install.ps1 │ ├── jquery-1.9.1.intellisense.js │ └── uninstall.ps1 └── jQuery.1.9.1.nupkg ├── log4net.2.0.3 ├── lib │ ├── net10-full │ │ ├── log4net.dll │ │ └── log4net.xml │ ├── net11-full │ │ ├── log4net.dll │ │ └── log4net.xml │ ├── net20-full │ │ ├── log4net.dll │ │ └── log4net.xml │ ├── net35-client │ │ ├── log4net.dll │ │ └── log4net.xml │ ├── net35-full │ │ ├── log4net.dll │ │ └── log4net.xml │ ├── net40-client │ │ ├── log4net.dll │ │ └── log4net.xml │ └── net40-full │ │ ├── log4net.dll │ │ └── log4net.xml └── log4net.2.0.3.nupkg └── repositories.config /.gitignore: -------------------------------------------------------------------------------- 1 | # Exclude some local teststuff 2 | SvclogWebViewer 3 | FastColoredTextBox 4 | *.svclog 5 | *.7z 6 | 7 | # Exclude user specific files 8 | **/*.suo 9 | **/*.user 10 | 11 | # Exclude private certificates 12 | **/*.pfx 13 | 14 | # Exclude obj and bin directories 15 | **/bin 16 | **/obj 17 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "MsCommon.ClickOnce"] 2 | path = MsCommon.ClickOnce 3 | url = https://github.com/martijns/MsCommon.ClickOnce.git 4 | -------------------------------------------------------------------------------- /ExternalLibs/FastColoredTextBox.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martijns/SvclogViewer/5a2690551778de71a7360560959e36daefc10b90/ExternalLibs/FastColoredTextBox.dll -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SvclogViewer 2 | 3 | An high-performance alternative for viewing WCF messages with SvcTraceViewer.exe. 4 | 5 | Cannot be used for other types of messages besides WCF messages. Note that this only reads the "MessageLogTraceRecord" elements from the logfile. An example configuration can be found below. 6 | 7 | ## Installation 8 | 9 | Binaries are available via a ClickOnce deployment on the following URL: 10 | http://martijn.tikkie.net/apps/SvclogViewer/SvclogViewer.application 11 | 12 | ## Main features 13 | 14 | ![screenshot](http://content.screencast.com/users/Martijn_Stolk/folders/Jing/media/956005aa-29b7-4157-8994-6b08d686ba7d/2013-11-06_2306.png) 15 | 16 | * High-performance reading of the .svclog file 17 | * Quickly reload the current .svclog file 18 | * Drag and drop your .svclog file into the application to open it 19 | * Can set itself as default handler for .svclog files 20 | * Filter messages for certain content (case-sensitive) 21 | * Auto-indent the XML content (has a minor performance impact) 22 | * Use syntax coloring (has a bigger performance impact) 23 | * Save request as... 24 | 25 | ## Example web.config configuration 26 | 27 | ``` 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | ``` 54 | 55 | Merge and adjust your configuration appropriately. 56 | 57 | ## Author 58 | 59 | Martijn Stolk (www.netripper.nl) 60 | 61 | ## License 62 | 63 | Creative Commons Attribution 3.0 Unported (CC BY 3.0) 64 | http://creativecommons.org/licenses/by/3.0/ 65 | 66 | -------------------------------------------------------------------------------- /RequestAnalyzer/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /RequestAnalyzer/Program.cs: -------------------------------------------------------------------------------- 1 | using SvclogViewer; 2 | using SvclogViewer.Entities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace RequestAnalyzer 12 | { 13 | public class Program 14 | { 15 | //static string[] filters = new[] { ">AB-011161@customer.dmz.local<", ">1033469<" }; 16 | static string[] filters = new string[] { }; 17 | 18 | [STAThread] 19 | static void Main(string[] args) 20 | { 21 | if (args.Length > 0) 22 | { 23 | foreach (var filename in args) 24 | { 25 | if (!File.Exists(filename)) 26 | { 27 | Console.WriteLine("File " + filename + " does not exist"); 28 | return; 29 | } 30 | } 31 | var analyzer = new SvcAnalyzer(); 32 | analyzer.Progress += HandleAnalyzerProgress; 33 | analyzer.Analyze(null, args); 34 | } 35 | else 36 | { 37 | Application.EnableVisualStyles(); 38 | Application.SetCompatibleTextRenderingDefault(false); 39 | Application.Run(new SvcAnalyzerDropper()); 40 | } 41 | } 42 | 43 | static int LastPercentage; 44 | private static void HandleAnalyzerProgress(object sender, AnalyzeEventArgs e) 45 | { 46 | int percentage = (int)((double)e.CurrentPosition / e.FileSize * 100); 47 | if (percentage != LastPercentage) 48 | { 49 | LastPercentage = percentage; 50 | Console.Write(string.Format("File: {0}, Mode: {1}, Progress: {2}% ({1,15} / {2})", Path.GetFileName(e.CurrentFileName), e.CurrentOperation, percentage, e.CurrentPosition, e.FileSize)); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /RequestAnalyzer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RequestAnalyzer")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("RequestAnalyzer")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d8f884f3-9eb6-4d8d-b460-9c5b69580f2d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /RequestAnalyzer/RequestAnalyzer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {D8F884F3-9EB6-4D8D-B460-9C5B69580F2D} 8 | Exe 9 | Properties 10 | RequestAnalyzer 11 | RequestAnalyzer 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | {02c83a78-48df-4f4c-b54b-e062e2db8294} 58 | SvclogViewer 59 | 60 | 61 | 62 | 69 | -------------------------------------------------------------------------------- /SvclogViewer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SvclogViewer", "SvclogViewer\SvclogViewer.csproj", "{02C83A78-48DF-4F4C-B54B-E062E2DB8294}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RequestAnalyzer", "RequestAnalyzer\RequestAnalyzer.csproj", "{D8F884F3-9EB6-4D8D-B460-9C5B69580F2D}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsCommon.ClickOnce", "MsCommon.ClickOnce\MsCommon.ClickOnce.csproj", "{28AFF2BB-79A2-46A2-9EF0-202B188AA028}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Debug|Mixed Platforms = Debug|Mixed Platforms 16 | Debug|x86 = Debug|x86 17 | Release|Any CPU = Release|Any CPU 18 | Release|Mixed Platforms = Release|Mixed Platforms 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {02C83A78-48DF-4F4C-B54B-E062E2DB8294}.Debug|Any CPU.ActiveCfg = Debug|x86 23 | {02C83A78-48DF-4F4C-B54B-E062E2DB8294}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 24 | {02C83A78-48DF-4F4C-B54B-E062E2DB8294}.Debug|Mixed Platforms.Build.0 = Debug|x86 25 | {02C83A78-48DF-4F4C-B54B-E062E2DB8294}.Debug|x86.ActiveCfg = Debug|x86 26 | {02C83A78-48DF-4F4C-B54B-E062E2DB8294}.Debug|x86.Build.0 = Debug|x86 27 | {02C83A78-48DF-4F4C-B54B-E062E2DB8294}.Release|Any CPU.ActiveCfg = Release|x86 28 | {02C83A78-48DF-4F4C-B54B-E062E2DB8294}.Release|Mixed Platforms.ActiveCfg = Release|x86 29 | {02C83A78-48DF-4F4C-B54B-E062E2DB8294}.Release|Mixed Platforms.Build.0 = Release|x86 30 | {02C83A78-48DF-4F4C-B54B-E062E2DB8294}.Release|x86.ActiveCfg = Release|x86 31 | {02C83A78-48DF-4F4C-B54B-E062E2DB8294}.Release|x86.Build.0 = Release|x86 32 | {D8F884F3-9EB6-4D8D-B460-9C5B69580F2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {D8F884F3-9EB6-4D8D-B460-9C5B69580F2D}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {D8F884F3-9EB6-4D8D-B460-9C5B69580F2D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 35 | {D8F884F3-9EB6-4D8D-B460-9C5B69580F2D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 36 | {D8F884F3-9EB6-4D8D-B460-9C5B69580F2D}.Debug|x86.ActiveCfg = Debug|Any CPU 37 | {D8F884F3-9EB6-4D8D-B460-9C5B69580F2D}.Debug|x86.Build.0 = Debug|Any CPU 38 | {D8F884F3-9EB6-4D8D-B460-9C5B69580F2D}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {D8F884F3-9EB6-4D8D-B460-9C5B69580F2D}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {D8F884F3-9EB6-4D8D-B460-9C5B69580F2D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 41 | {D8F884F3-9EB6-4D8D-B460-9C5B69580F2D}.Release|Mixed Platforms.Build.0 = Release|Any CPU 42 | {D8F884F3-9EB6-4D8D-B460-9C5B69580F2D}.Release|x86.ActiveCfg = Release|Any CPU 43 | {D8F884F3-9EB6-4D8D-B460-9C5B69580F2D}.Release|x86.Build.0 = Release|Any CPU 44 | {28AFF2BB-79A2-46A2-9EF0-202B188AA028}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 45 | {28AFF2BB-79A2-46A2-9EF0-202B188AA028}.Debug|Any CPU.Build.0 = Debug|Any CPU 46 | {28AFF2BB-79A2-46A2-9EF0-202B188AA028}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 47 | {28AFF2BB-79A2-46A2-9EF0-202B188AA028}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 48 | {28AFF2BB-79A2-46A2-9EF0-202B188AA028}.Debug|x86.ActiveCfg = Debug|Any CPU 49 | {28AFF2BB-79A2-46A2-9EF0-202B188AA028}.Debug|x86.Build.0 = Debug|Any CPU 50 | {28AFF2BB-79A2-46A2-9EF0-202B188AA028}.Release|Any CPU.ActiveCfg = Release|Any CPU 51 | {28AFF2BB-79A2-46A2-9EF0-202B188AA028}.Release|Any CPU.Build.0 = Release|Any CPU 52 | {28AFF2BB-79A2-46A2-9EF0-202B188AA028}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 53 | {28AFF2BB-79A2-46A2-9EF0-202B188AA028}.Release|Mixed Platforms.Build.0 = Release|Any CPU 54 | {28AFF2BB-79A2-46A2-9EF0-202B188AA028}.Release|x86.ActiveCfg = Release|Any CPU 55 | {28AFF2BB-79A2-46A2-9EF0-202B188AA028}.Release|x86.Build.0 = Release|Any CPU 56 | EndGlobalSection 57 | GlobalSection(SolutionProperties) = preSolution 58 | HideSolutionNode = FALSE 59 | EndGlobalSection 60 | EndGlobal 61 | -------------------------------------------------------------------------------- /SvclogViewer/Config/Configuration.cs: -------------------------------------------------------------------------------- 1 | using MsCommon.ClickOnce; 2 | using System; 3 | using System.Xml.Serialization; 4 | 5 | namespace SvclogViewer.Config 6 | { 7 | [Serializable] 8 | public class Configuration : AppConfiguration 9 | { 10 | public Configuration() 11 | { 12 | } 13 | 14 | [XmlElement] 15 | public bool AutoXmlFormatEnabled { get; set; } 16 | 17 | [XmlElement] 18 | public string LastSelectedSource { get; set; } 19 | 20 | [XmlElement] 21 | public bool HasRefusedSetAsDefault { get; set; } 22 | 23 | [XmlElement] 24 | public bool UseSyntaxColoring { get; set; } 25 | 26 | [XmlElement] 27 | public bool UseAutoUrlDecode { get; set; } 28 | 29 | [XmlElement] 30 | public bool UseAutoHtmlDecode { get; set; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SvclogViewer/DefaultAssociationHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Deployment.Application; 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Security.Principal; 10 | using System.Text; 11 | using System.Windows.Forms; 12 | 13 | namespace SvclogViewer 14 | { 15 | public static class DefaultAssociationHelper 16 | { 17 | public static bool EqualsIgnoreCase(this object source, string target) 18 | { 19 | if (!(source is string)) 20 | throw new ArgumentException("source must be of type string", "source"); 21 | string src = source as string; 22 | if (src != null && target != null) 23 | return src.ToLower().Equals(target.ToLower()); 24 | return false; 25 | } 26 | 27 | public static bool IsDefaultProgram() 28 | { 29 | try 30 | { 31 | var key = Registry.ClassesRoot.OpenSubKey(".svclog"); 32 | if (key == null) 33 | return false; 34 | var value = key.GetValue(""); 35 | if (value == null || !(value is string) || !value.EqualsIgnoreCase("Tikkie.SvcLogViewer")) 36 | return false; 37 | 38 | //key = Registry.ClassesRoot.OpenSubKey("Tikkie.SvcLogViewer"); 39 | //if (key == null) 40 | // return false; 41 | //value = key.GetValue(""); 42 | //if (value == null || !(value is string) || !value.Equals("Tikkie.SvcLogViewer")) 43 | // return false; 44 | 45 | //string associationcmd = GetFileAssociationCommandString(); 46 | //key = Registry.ClassesRoot.OpenSubKey("Tikkie.SvcLogViewer\\shell\\Open\\command"); 47 | //if (key == null) 48 | // return false; 49 | //value = key.GetValue(""); 50 | //if (value == null || !(value is string) || !((string)value).Contains(associationcmd)) 51 | // return false; 52 | 53 | key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Classes\\.svclog"); 54 | if (key != null) 55 | { 56 | value = key.GetValue(""); 57 | if (value != null && value is string && !value.EqualsIgnoreCase("") && !value.EqualsIgnoreCase("Tikkie.SvcLogViewer")) 58 | return false; 59 | } 60 | 61 | key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Classes\\.svclog"); 62 | if (key == null) 63 | return false; 64 | value = key.GetValue(""); 65 | if (value != null && value is string && !value.EqualsIgnoreCase("") && !value.EqualsIgnoreCase("Tikkie.SvcLogViewer")) 66 | return false; 67 | 68 | key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.svclog\\UserChoice"); 69 | if (key != null) 70 | { 71 | value = key.GetValue("ProgId"); 72 | if (value != null && !value.EqualsIgnoreCase("Tikkie.SvcLogViewer")) 73 | return false; 74 | } 75 | 76 | return true; 77 | } 78 | catch (Exception ex) 79 | { 80 | } 81 | return false; 82 | } 83 | 84 | public static bool PresentMakeDefaultQuestion(IWin32Window parent) 85 | { 86 | var result = MessageBox.Show(parent, "This application is not the default application to handle .svclog files. Do you want to make this application the default?\r\n\r\nIf you choose 'no', you can later make this application the default via the menu.\r\n", "Default file association", MessageBoxButtons.YesNo); 87 | return result == DialogResult.Yes; 88 | } 89 | 90 | public static bool MakeDefault(IWin32Window parent) 91 | { 92 | if (IsAdministrator()) 93 | { 94 | return MakeDefaultInternal(parent); 95 | } 96 | else 97 | { 98 | string myexecutable = Assembly.GetEntryAssembly().Location; // For process.start we need the actual .exe 99 | Process p = new Process(); 100 | p.StartInfo = new ProcessStartInfo() 101 | { 102 | FileName = myexecutable + " ", 103 | Arguments = "MakeDefault", 104 | Verb = "runas" 105 | }; 106 | if (!p.Start()) 107 | { 108 | MessageBox.Show(parent, "Error spawning a process as administrator in order to make this application the default..."); 109 | return false; 110 | } 111 | p.WaitForExit(); 112 | if (p.ExitCode != 101) 113 | { 114 | MessageBox.Show(parent, "Spawned a process as administrator to make the application default, but somehow failed."); 115 | return false; 116 | } 117 | return true; 118 | } 119 | } 120 | 121 | public static bool MakeDefaultInternal(IWin32Window parent) 122 | { 123 | try 124 | { 125 | var key = Registry.ClassesRoot.CreateSubKey(".svclog"); 126 | key.SetValue("", "Tikkie.SvcLogViewer"); 127 | //var key2 = Registry.ClassesRoot.CreateSubKey("Tikkie.SvcLogViewer"); 128 | //key2.SetValue("", "Tikkie.SvcLogViewer"); 129 | //var key3 = Registry.ClassesRoot.CreateSubKey("Tikkie.SvcLogViewer\\shell\\Open\\command"); 130 | //key3.SetValue("", GetFileAssociationCommandString()); 131 | //if (Registry.LocalMachine.OpenSubKey("SOFTWARE\\Classes\\.svclog") != null) 132 | Registry.LocalMachine.DeleteSubKeyTree("SOFTWARE\\Classes\\.svclog", false); 133 | key = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Classes\\.svclog"); 134 | key.SetValue("", "Tikkie.SvcLogViewer"); 135 | using (RegistryKey rkey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.svclog", RegistryKeyPermissionCheck.ReadWriteSubTree, System.Security.AccessControl.RegistryRights.Delete)) 136 | { 137 | if (rkey != null) 138 | rkey.DeleteSubKey("UserChoice", false); 139 | } 140 | return true; 141 | } 142 | catch (Exception ex) 143 | { 144 | MessageBox.Show(parent, "Failed to set this application as the default startup applicaton:\r\n" + ex); 145 | return false; 146 | } 147 | } 148 | 149 | public static bool IsAdministrator() 150 | { 151 | WindowsIdentity identity = WindowsIdentity.GetCurrent(); 152 | WindowsPrincipal principal = new WindowsPrincipal(identity); 153 | return principal.IsInRole(WindowsBuiltInRole.Administrator); 154 | } 155 | 156 | public static string GetApplicationPath() 157 | { 158 | return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Programs), 159 | "Tikkie", 160 | "SvcLogViewer.appref-ms"); 161 | //if (ApplicationDeployment.IsNetworkDeployed) 162 | //{ 163 | // return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Programs), 164 | // "Tikkie", 165 | // "SvcLogViewer.appref-ms"); 166 | //} 167 | //else 168 | //{ 169 | // return Assembly.GetEntryAssembly().Location; 170 | //} 171 | } 172 | 173 | //public static string GetFileAssociationCommandString() 174 | //{ 175 | // string myexecutable = GetApplicationPath(); 176 | // string cmd = "\"cmd\" \"/c\" \"" + myexecutable + "\"" + " \"%1\" \"%1\""; // Somehow the first %1 isn't actually passed as parameter 177 | // return cmd; 178 | //} 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /SvclogViewer/Entities/TraceEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace SvclogViewer.Entities 7 | { 8 | public class TraceEvent 9 | { 10 | public long PositionStart { get; set; } 11 | public long PositionEnd { get; set; } 12 | public DateTime TimeCreated { get; set; } 13 | public string Method { get; set; } 14 | public string Source { get; set; } 15 | public Guid ActivityID { get; set; } 16 | public string To { get; set; } 17 | 18 | public bool ContainsPosition(long position) 19 | { 20 | return position >= PositionStart && position <= PositionEnd; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SvclogViewer/MainForm.Designer.cs: -------------------------------------------------------------------------------- 1 | using FastColoredTextBoxNS; 2 | namespace SvclogViewer 3 | { 4 | partial class MainForm 5 | { 6 | /// 7 | /// Required designer variable. 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// Clean up any resources being used. 13 | /// 14 | /// true if managed resources should be disposed; otherwise, false. 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Windows Form Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); 33 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); 34 | this.statusStrip1 = new System.Windows.Forms.StatusStrip(); 35 | this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel(); 36 | this.lblStatus = new System.Windows.Forms.ToolStripStatusLabel(); 37 | this.progressBar = new System.Windows.Forms.ToolStripProgressBar(); 38 | this.lblFilename = new System.Windows.Forms.ToolStripStatusLabel(); 39 | this.menuStrip1 = new System.Windows.Forms.MenuStrip(); 40 | this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 41 | this.btnFileOpen = new System.Windows.Forms.ToolStripMenuItem(); 42 | this.saveRequestAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 43 | this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); 44 | this.closeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 45 | this.reloadFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 46 | this.extrasToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 47 | this.setAppAsDefaultForsvclogFilesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 48 | this.startsvclogAnalyzerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 49 | this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 50 | this.changelogToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 51 | this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 52 | this.splitLeftRight = new System.Windows.Forms.SplitContainer(); 53 | this.splitFilterResult = new System.Windows.Forms.SplitContainer(); 54 | this.label1 = new System.Windows.Forms.Label(); 55 | this.cmbSouce = new System.Windows.Forms.ComboBox(); 56 | this.button5 = new System.Windows.Forms.Button(); 57 | this.button4 = new System.Windows.Forms.Button(); 58 | this.txtFilter = new System.Windows.Forms.TextBox(); 59 | this.dataGridView1 = new System.Windows.Forms.DataGridView(); 60 | this.Datetime = new System.Windows.Forms.DataGridViewTextBoxColumn(); 61 | this.Size = new System.Windows.Forms.DataGridViewTextBoxColumn(); 62 | this.splitMessageButtons = new System.Windows.Forms.SplitContainer(); 63 | this.panel1 = new System.Windows.Forms.Panel(); 64 | this.cbAutoHtmlDecode = new System.Windows.Forms.CheckBox(); 65 | this.cbAutoUrlDecode = new System.Windows.Forms.CheckBox(); 66 | this.btnDecodeBinary = new System.Windows.Forms.Button(); 67 | this.checkSyntaxColoring = new System.Windows.Forms.CheckBox(); 68 | this.checkAutoFormat = new System.Windows.Forms.CheckBox(); 69 | this.button2 = new System.Windows.Forms.Button(); 70 | this.button1 = new System.Windows.Forms.Button(); 71 | this.textBox1 = new SvclogViewer.SwitchableTextBox(); 72 | this.submitFeedbackToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 73 | this.statusStrip1.SuspendLayout(); 74 | this.menuStrip1.SuspendLayout(); 75 | ((System.ComponentModel.ISupportInitialize)(this.splitLeftRight)).BeginInit(); 76 | this.splitLeftRight.Panel1.SuspendLayout(); 77 | this.splitLeftRight.Panel2.SuspendLayout(); 78 | this.splitLeftRight.SuspendLayout(); 79 | ((System.ComponentModel.ISupportInitialize)(this.splitFilterResult)).BeginInit(); 80 | this.splitFilterResult.Panel1.SuspendLayout(); 81 | this.splitFilterResult.Panel2.SuspendLayout(); 82 | this.splitFilterResult.SuspendLayout(); 83 | ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); 84 | ((System.ComponentModel.ISupportInitialize)(this.splitMessageButtons)).BeginInit(); 85 | this.splitMessageButtons.Panel1.SuspendLayout(); 86 | this.splitMessageButtons.Panel2.SuspendLayout(); 87 | this.splitMessageButtons.SuspendLayout(); 88 | this.panel1.SuspendLayout(); 89 | this.SuspendLayout(); 90 | // 91 | // statusStrip1 92 | // 93 | this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 94 | this.toolStripStatusLabel1, 95 | this.lblStatus, 96 | this.progressBar, 97 | this.lblFilename}); 98 | this.statusStrip1.Location = new System.Drawing.Point(0, 644); 99 | this.statusStrip1.Name = "statusStrip1"; 100 | this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 10, 0); 101 | this.statusStrip1.Size = new System.Drawing.Size(1362, 22); 102 | this.statusStrip1.TabIndex = 0; 103 | this.statusStrip1.Text = "statusStrip1"; 104 | // 105 | // toolStripStatusLabel1 106 | // 107 | this.toolStripStatusLabel1.Name = "toolStripStatusLabel1"; 108 | this.toolStripStatusLabel1.Size = new System.Drawing.Size(42, 17); 109 | this.toolStripStatusLabel1.Text = "Status:"; 110 | // 111 | // lblStatus 112 | // 113 | this.lblStatus.Name = "lblStatus"; 114 | this.lblStatus.Size = new System.Drawing.Size(52, 17); 115 | this.lblStatus.Text = "lblStatus"; 116 | // 117 | // progressBar 118 | // 119 | this.progressBar.Name = "progressBar"; 120 | this.progressBar.Size = new System.Drawing.Size(150, 16); 121 | this.progressBar.Step = 1; 122 | // 123 | // lblFilename 124 | // 125 | this.lblFilename.Name = "lblFilename"; 126 | this.lblFilename.Size = new System.Drawing.Size(68, 17); 127 | this.lblFilename.Text = "lblFilename"; 128 | // 129 | // menuStrip1 130 | // 131 | this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 132 | this.fileToolStripMenuItem, 133 | this.reloadFileToolStripMenuItem, 134 | this.extrasToolStripMenuItem, 135 | this.helpToolStripMenuItem}); 136 | this.menuStrip1.Location = new System.Drawing.Point(0, 0); 137 | this.menuStrip1.Name = "menuStrip1"; 138 | this.menuStrip1.Padding = new System.Windows.Forms.Padding(4, 2, 0, 2); 139 | this.menuStrip1.Size = new System.Drawing.Size(1362, 24); 140 | this.menuStrip1.TabIndex = 1; 141 | this.menuStrip1.Text = "menuStrip1"; 142 | // 143 | // fileToolStripMenuItem 144 | // 145 | this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 146 | this.btnFileOpen, 147 | this.saveRequestAsToolStripMenuItem, 148 | this.toolStripSeparator2, 149 | this.closeToolStripMenuItem}); 150 | this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; 151 | this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); 152 | this.fileToolStripMenuItem.Text = "File"; 153 | // 154 | // btnFileOpen 155 | // 156 | this.btnFileOpen.Name = "btnFileOpen"; 157 | this.btnFileOpen.Size = new System.Drawing.Size(163, 22); 158 | this.btnFileOpen.Text = "Open..."; 159 | this.btnFileOpen.Click += new System.EventHandler(this.HandleFileOpen); 160 | // 161 | // saveRequestAsToolStripMenuItem 162 | // 163 | this.saveRequestAsToolStripMenuItem.Name = "saveRequestAsToolStripMenuItem"; 164 | this.saveRequestAsToolStripMenuItem.Size = new System.Drawing.Size(163, 22); 165 | this.saveRequestAsToolStripMenuItem.Text = "Save request as..."; 166 | this.saveRequestAsToolStripMenuItem.Click += new System.EventHandler(this.HandleSaveRequestAsClicked); 167 | // 168 | // toolStripSeparator2 169 | // 170 | this.toolStripSeparator2.Name = "toolStripSeparator2"; 171 | this.toolStripSeparator2.Size = new System.Drawing.Size(160, 6); 172 | // 173 | // closeToolStripMenuItem 174 | // 175 | this.closeToolStripMenuItem.Name = "closeToolStripMenuItem"; 176 | this.closeToolStripMenuItem.Size = new System.Drawing.Size(163, 22); 177 | this.closeToolStripMenuItem.Text = "Close"; 178 | this.closeToolStripMenuItem.Click += new System.EventHandler(this.HandleClose); 179 | // 180 | // reloadFileToolStripMenuItem 181 | // 182 | this.reloadFileToolStripMenuItem.Name = "reloadFileToolStripMenuItem"; 183 | this.reloadFileToolStripMenuItem.Size = new System.Drawing.Size(74, 20); 184 | this.reloadFileToolStripMenuItem.Text = "Reload file"; 185 | this.reloadFileToolStripMenuItem.Click += new System.EventHandler(this.HandleReloadFile); 186 | // 187 | // extrasToolStripMenuItem 188 | // 189 | this.extrasToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 190 | this.setAppAsDefaultForsvclogFilesToolStripMenuItem, 191 | this.startsvclogAnalyzerToolStripMenuItem}); 192 | this.extrasToolStripMenuItem.Name = "extrasToolStripMenuItem"; 193 | this.extrasToolStripMenuItem.Size = new System.Drawing.Size(49, 20); 194 | this.extrasToolStripMenuItem.Text = "Extras"; 195 | // 196 | // setAppAsDefaultForsvclogFilesToolStripMenuItem 197 | // 198 | this.setAppAsDefaultForsvclogFilesToolStripMenuItem.Name = "setAppAsDefaultForsvclogFilesToolStripMenuItem"; 199 | this.setAppAsDefaultForsvclogFilesToolStripMenuItem.Size = new System.Drawing.Size(258, 22); 200 | this.setAppAsDefaultForsvclogFilesToolStripMenuItem.Text = "Set app as default for .svclog files..."; 201 | this.setAppAsDefaultForsvclogFilesToolStripMenuItem.Click += new System.EventHandler(this.HandleSetAsDefaultClick); 202 | // 203 | // startsvclogAnalyzerToolStripMenuItem 204 | // 205 | this.startsvclogAnalyzerToolStripMenuItem.Name = "startsvclogAnalyzerToolStripMenuItem"; 206 | this.startsvclogAnalyzerToolStripMenuItem.Size = new System.Drawing.Size(258, 22); 207 | this.startsvclogAnalyzerToolStripMenuItem.Text = "Start .svclog analyzer..."; 208 | this.startsvclogAnalyzerToolStripMenuItem.Click += new System.EventHandler(this.HandleStartAnalyzerClicked); 209 | // 210 | // helpToolStripMenuItem 211 | // 212 | this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 213 | this.changelogToolStripMenuItem, 214 | this.submitFeedbackToolStripMenuItem, 215 | this.aboutToolStripMenuItem}); 216 | this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; 217 | this.helpToolStripMenuItem.Size = new System.Drawing.Size(44, 20); 218 | this.helpToolStripMenuItem.Text = "Help"; 219 | // 220 | // changelogToolStripMenuItem 221 | // 222 | this.changelogToolStripMenuItem.Name = "changelogToolStripMenuItem"; 223 | this.changelogToolStripMenuItem.Size = new System.Drawing.Size(172, 22); 224 | this.changelogToolStripMenuItem.Text = "Changelog..."; 225 | this.changelogToolStripMenuItem.Click += new System.EventHandler(this.HandleChangelogClicked); 226 | // 227 | // aboutToolStripMenuItem 228 | // 229 | this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; 230 | this.aboutToolStripMenuItem.Size = new System.Drawing.Size(172, 22); 231 | this.aboutToolStripMenuItem.Text = "About..."; 232 | this.aboutToolStripMenuItem.Click += new System.EventHandler(this.HandleAbout); 233 | // 234 | // splitLeftRight 235 | // 236 | this.splitLeftRight.Dock = System.Windows.Forms.DockStyle.Fill; 237 | this.splitLeftRight.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; 238 | this.splitLeftRight.Location = new System.Drawing.Point(0, 24); 239 | this.splitLeftRight.Margin = new System.Windows.Forms.Padding(2); 240 | this.splitLeftRight.Name = "splitLeftRight"; 241 | // 242 | // splitLeftRight.Panel1 243 | // 244 | this.splitLeftRight.Panel1.Controls.Add(this.splitFilterResult); 245 | // 246 | // splitLeftRight.Panel2 247 | // 248 | this.splitLeftRight.Panel2.Controls.Add(this.splitMessageButtons); 249 | this.splitLeftRight.Size = new System.Drawing.Size(1362, 620); 250 | this.splitLeftRight.SplitterDistance = 310; 251 | this.splitLeftRight.SplitterWidth = 3; 252 | this.splitLeftRight.TabIndex = 2; 253 | this.splitLeftRight.SplitterMoved += new System.Windows.Forms.SplitterEventHandler(this.HandleSplitResize); 254 | // 255 | // splitFilterResult 256 | // 257 | this.splitFilterResult.Dock = System.Windows.Forms.DockStyle.Fill; 258 | this.splitFilterResult.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; 259 | this.splitFilterResult.IsSplitterFixed = true; 260 | this.splitFilterResult.Location = new System.Drawing.Point(0, 0); 261 | this.splitFilterResult.Margin = new System.Windows.Forms.Padding(2); 262 | this.splitFilterResult.Name = "splitFilterResult"; 263 | this.splitFilterResult.Orientation = System.Windows.Forms.Orientation.Horizontal; 264 | // 265 | // splitFilterResult.Panel1 266 | // 267 | this.splitFilterResult.Panel1.Controls.Add(this.label1); 268 | this.splitFilterResult.Panel1.Controls.Add(this.cmbSouce); 269 | this.splitFilterResult.Panel1.Controls.Add(this.button5); 270 | this.splitFilterResult.Panel1.Controls.Add(this.button4); 271 | this.splitFilterResult.Panel1.Controls.Add(this.txtFilter); 272 | // 273 | // splitFilterResult.Panel2 274 | // 275 | this.splitFilterResult.Panel2.Controls.Add(this.dataGridView1); 276 | this.splitFilterResult.Size = new System.Drawing.Size(310, 620); 277 | this.splitFilterResult.SplitterDistance = 70; 278 | this.splitFilterResult.SplitterWidth = 3; 279 | this.splitFilterResult.TabIndex = 1; 280 | // 281 | // label1 282 | // 283 | this.label1.AutoSize = true; 284 | this.label1.Location = new System.Drawing.Point(5, 32); 285 | this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); 286 | this.label1.Name = "label1"; 287 | this.label1.Size = new System.Drawing.Size(44, 13); 288 | this.label1.TabIndex = 4; 289 | this.label1.Text = "Source:"; 290 | // 291 | // cmbSouce 292 | // 293 | this.cmbSouce.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 294 | this.cmbSouce.FormattingEnabled = true; 295 | this.cmbSouce.Location = new System.Drawing.Point(52, 31); 296 | this.cmbSouce.Margin = new System.Windows.Forms.Padding(2); 297 | this.cmbSouce.Name = "cmbSouce"; 298 | this.cmbSouce.Size = new System.Drawing.Size(179, 21); 299 | this.cmbSouce.TabIndex = 3; 300 | this.cmbSouce.SelectionChangeCommitted += new System.EventHandler(this.HandleSourceChanged); 301 | // 302 | // button5 303 | // 304 | this.button5.Location = new System.Drawing.Point(194, 2); 305 | this.button5.Margin = new System.Windows.Forms.Padding(2); 306 | this.button5.Name = "button5"; 307 | this.button5.Size = new System.Drawing.Size(39, 24); 308 | this.button5.TabIndex = 2; 309 | this.button5.Text = "Clear"; 310 | this.button5.UseVisualStyleBackColor = true; 311 | this.button5.Click += new System.EventHandler(this.HandleFilterClear); 312 | // 313 | // button4 314 | // 315 | this.button4.Location = new System.Drawing.Point(151, 2); 316 | this.button4.Margin = new System.Windows.Forms.Padding(2); 317 | this.button4.Name = "button4"; 318 | this.button4.Size = new System.Drawing.Size(38, 24); 319 | this.button4.TabIndex = 1; 320 | this.button4.Text = "Filter"; 321 | this.button4.UseVisualStyleBackColor = true; 322 | this.button4.Click += new System.EventHandler(this.HandleFilterClick); 323 | // 324 | // txtFilter 325 | // 326 | this.txtFilter.Location = new System.Drawing.Point(2, 6); 327 | this.txtFilter.Margin = new System.Windows.Forms.Padding(2); 328 | this.txtFilter.Name = "txtFilter"; 329 | this.txtFilter.Size = new System.Drawing.Size(145, 20); 330 | this.txtFilter.TabIndex = 0; 331 | this.txtFilter.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HandleFilterKeyUp); 332 | // 333 | // dataGridView1 334 | // 335 | this.dataGridView1.AllowUserToAddRows = false; 336 | this.dataGridView1.AllowUserToDeleteRows = false; 337 | this.dataGridView1.AllowUserToResizeRows = false; 338 | this.dataGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill; 339 | this.dataGridView1.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells; 340 | this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; 341 | this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { 342 | this.Datetime, 343 | this.Size}); 344 | this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill; 345 | this.dataGridView1.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; 346 | this.dataGridView1.Location = new System.Drawing.Point(0, 0); 347 | this.dataGridView1.Margin = new System.Windows.Forms.Padding(2); 348 | this.dataGridView1.MultiSelect = false; 349 | this.dataGridView1.Name = "dataGridView1"; 350 | this.dataGridView1.ReadOnly = true; 351 | this.dataGridView1.RowHeadersVisible = false; 352 | this.dataGridView1.RowTemplate.Height = 24; 353 | this.dataGridView1.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; 354 | this.dataGridView1.Size = new System.Drawing.Size(310, 547); 355 | this.dataGridView1.TabIndex = 0; 356 | this.dataGridView1.VirtualMode = true; 357 | this.dataGridView1.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.HandleCellFormatting); 358 | this.dataGridView1.CellValueNeeded += new System.Windows.Forms.DataGridViewCellValueEventHandler(this.HandleCellValueNeeded); 359 | this.dataGridView1.SelectionChanged += new System.EventHandler(this.HandleGridSelectionChanged); 360 | // 361 | // Datetime 362 | // 363 | this.Datetime.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.None; 364 | dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True; 365 | this.Datetime.DefaultCellStyle = dataGridViewCellStyle1; 366 | this.Datetime.HeaderText = "Datetime"; 367 | this.Datetime.MinimumWidth = 50; 368 | this.Datetime.Name = "Datetime"; 369 | this.Datetime.ReadOnly = true; 370 | this.Datetime.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; 371 | this.Datetime.Width = 215; 372 | // 373 | // Size 374 | // 375 | this.Size.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.None; 376 | this.Size.HeaderText = "Size (kb)"; 377 | this.Size.MinimumWidth = 70; 378 | this.Size.Name = "Size"; 379 | this.Size.ReadOnly = true; 380 | this.Size.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; 381 | this.Size.Width = 70; 382 | // 383 | // splitMessageButtons 384 | // 385 | this.splitMessageButtons.Dock = System.Windows.Forms.DockStyle.Fill; 386 | this.splitMessageButtons.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; 387 | this.splitMessageButtons.IsSplitterFixed = true; 388 | this.splitMessageButtons.Location = new System.Drawing.Point(0, 0); 389 | this.splitMessageButtons.Margin = new System.Windows.Forms.Padding(2); 390 | this.splitMessageButtons.Name = "splitMessageButtons"; 391 | this.splitMessageButtons.Orientation = System.Windows.Forms.Orientation.Horizontal; 392 | // 393 | // splitMessageButtons.Panel1 394 | // 395 | this.splitMessageButtons.Panel1.Controls.Add(this.panel1); 396 | // 397 | // splitMessageButtons.Panel2 398 | // 399 | this.splitMessageButtons.Panel2.Controls.Add(this.textBox1); 400 | this.splitMessageButtons.Size = new System.Drawing.Size(1049, 620); 401 | this.splitMessageButtons.SplitterDistance = 35; 402 | this.splitMessageButtons.SplitterWidth = 3; 403 | this.splitMessageButtons.TabIndex = 2; 404 | // 405 | // panel1 406 | // 407 | this.panel1.Controls.Add(this.cbAutoHtmlDecode); 408 | this.panel1.Controls.Add(this.cbAutoUrlDecode); 409 | this.panel1.Controls.Add(this.btnDecodeBinary); 410 | this.panel1.Controls.Add(this.checkSyntaxColoring); 411 | this.panel1.Controls.Add(this.checkAutoFormat); 412 | this.panel1.Controls.Add(this.button2); 413 | this.panel1.Controls.Add(this.button1); 414 | this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; 415 | this.panel1.Location = new System.Drawing.Point(0, 0); 416 | this.panel1.Margin = new System.Windows.Forms.Padding(2); 417 | this.panel1.Name = "panel1"; 418 | this.panel1.Size = new System.Drawing.Size(1049, 35); 419 | this.panel1.TabIndex = 1; 420 | // 421 | // cbAutoHtmlDecode 422 | // 423 | this.cbAutoHtmlDecode.AutoSize = true; 424 | this.cbAutoHtmlDecode.Location = new System.Drawing.Point(719, 6); 425 | this.cbAutoHtmlDecode.Name = "cbAutoHtmlDecode"; 426 | this.cbAutoHtmlDecode.Size = new System.Drawing.Size(110, 17); 427 | this.cbAutoHtmlDecode.TabIndex = 7; 428 | this.cbAutoHtmlDecode.Text = "Auto HtmlDecode"; 429 | this.cbAutoHtmlDecode.UseVisualStyleBackColor = true; 430 | // 431 | // cbAutoUrlDecode 432 | // 433 | this.cbAutoUrlDecode.AutoSize = true; 434 | this.cbAutoUrlDecode.Location = new System.Drawing.Point(611, 6); 435 | this.cbAutoUrlDecode.Name = "cbAutoUrlDecode"; 436 | this.cbAutoUrlDecode.Size = new System.Drawing.Size(102, 17); 437 | this.cbAutoUrlDecode.TabIndex = 6; 438 | this.cbAutoUrlDecode.Text = "Auto UrlDecode"; 439 | this.cbAutoUrlDecode.UseVisualStyleBackColor = true; 440 | // 441 | // btnDecodeBinary 442 | // 443 | this.btnDecodeBinary.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 444 | this.btnDecodeBinary.Location = new System.Drawing.Point(834, 2); 445 | this.btnDecodeBinary.Margin = new System.Windows.Forms.Padding(2); 446 | this.btnDecodeBinary.Name = "btnDecodeBinary"; 447 | this.btnDecodeBinary.Size = new System.Drawing.Size(125, 24); 448 | this.btnDecodeBinary.TabIndex = 5; 449 | this.btnDecodeBinary.Text = "Decode Binary"; 450 | this.btnDecodeBinary.UseVisualStyleBackColor = true; 451 | this.btnDecodeBinary.Click += new System.EventHandler(this.HandleDecodeBinaryClicked); 452 | // 453 | // checkSyntaxColoring 454 | // 455 | this.checkSyntaxColoring.AutoSize = true; 456 | this.checkSyntaxColoring.Location = new System.Drawing.Point(487, 6); 457 | this.checkSyntaxColoring.Name = "checkSyntaxColoring"; 458 | this.checkSyntaxColoring.Size = new System.Drawing.Size(118, 17); 459 | this.checkSyntaxColoring.TabIndex = 4; 460 | this.checkSyntaxColoring.Text = "Use syntax coloring"; 461 | this.checkSyntaxColoring.UseVisualStyleBackColor = true; 462 | // 463 | // checkAutoFormat 464 | // 465 | this.checkAutoFormat.AutoSize = true; 466 | this.checkAutoFormat.Location = new System.Drawing.Point(376, 6); 467 | this.checkAutoFormat.Name = "checkAutoFormat"; 468 | this.checkAutoFormat.Size = new System.Drawing.Size(105, 17); 469 | this.checkAutoFormat.TabIndex = 3; 470 | this.checkAutoFormat.Text = "Auto-format XML"; 471 | this.checkAutoFormat.UseVisualStyleBackColor = true; 472 | // 473 | // button2 474 | // 475 | this.button2.Location = new System.Drawing.Point(189, 2); 476 | this.button2.Margin = new System.Windows.Forms.Padding(2); 477 | this.button2.Name = "button2"; 478 | this.button2.Size = new System.Drawing.Size(182, 24); 479 | this.button2.TabIndex = 1; 480 | this.button2.Text = "Copy soapenv to clipboard"; 481 | this.button2.UseVisualStyleBackColor = true; 482 | this.button2.Click += new System.EventHandler(this.HandleCopySoapenvToClipboard); 483 | // 484 | // button1 485 | // 486 | this.button1.Location = new System.Drawing.Point(46, 2); 487 | this.button1.Margin = new System.Windows.Forms.Padding(2); 488 | this.button1.Name = "button1"; 489 | this.button1.Size = new System.Drawing.Size(138, 24); 490 | this.button1.TabIndex = 0; 491 | this.button1.Text = "Copy to clipboard"; 492 | this.button1.UseVisualStyleBackColor = true; 493 | this.button1.Click += new System.EventHandler(this.HandleCopyToClipboard); 494 | // 495 | // textBox1 496 | // 497 | this.textBox1.Dock = System.Windows.Forms.DockStyle.Fill; 498 | this.textBox1.EnableSyntaxColoring = false; 499 | this.textBox1.Location = new System.Drawing.Point(0, 0); 500 | this.textBox1.Margin = new System.Windows.Forms.Padding(2); 501 | this.textBox1.Name = "textBox1"; 502 | this.textBox1.Size = new System.Drawing.Size(1049, 582); 503 | this.textBox1.TabIndex = 0; 504 | // 505 | // submitFeedbackToolStripMenuItem 506 | // 507 | this.submitFeedbackToolStripMenuItem.Name = "submitFeedbackToolStripMenuItem"; 508 | this.submitFeedbackToolStripMenuItem.Size = new System.Drawing.Size(172, 22); 509 | this.submitFeedbackToolStripMenuItem.Text = "Submit feedback..."; 510 | this.submitFeedbackToolStripMenuItem.Click += new System.EventHandler(this.HandleSubmitFeedbackClicked); 511 | // 512 | // MainForm 513 | // 514 | this.AllowDrop = true; 515 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 516 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 517 | this.ClientSize = new System.Drawing.Size(1362, 666); 518 | this.Controls.Add(this.splitLeftRight); 519 | this.Controls.Add(this.statusStrip1); 520 | this.Controls.Add(this.menuStrip1); 521 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 522 | this.MainMenuStrip = this.menuStrip1; 523 | this.Margin = new System.Windows.Forms.Padding(2); 524 | this.Name = "MainForm"; 525 | this.Text = "SvclogViewer"; 526 | this.DragDrop += new System.Windows.Forms.DragEventHandler(this.HandleDragDrop); 527 | this.DragEnter += new System.Windows.Forms.DragEventHandler(this.HandleDragEnter); 528 | this.statusStrip1.ResumeLayout(false); 529 | this.statusStrip1.PerformLayout(); 530 | this.menuStrip1.ResumeLayout(false); 531 | this.menuStrip1.PerformLayout(); 532 | this.splitLeftRight.Panel1.ResumeLayout(false); 533 | this.splitLeftRight.Panel2.ResumeLayout(false); 534 | ((System.ComponentModel.ISupportInitialize)(this.splitLeftRight)).EndInit(); 535 | this.splitLeftRight.ResumeLayout(false); 536 | this.splitFilterResult.Panel1.ResumeLayout(false); 537 | this.splitFilterResult.Panel1.PerformLayout(); 538 | this.splitFilterResult.Panel2.ResumeLayout(false); 539 | ((System.ComponentModel.ISupportInitialize)(this.splitFilterResult)).EndInit(); 540 | this.splitFilterResult.ResumeLayout(false); 541 | ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); 542 | this.splitMessageButtons.Panel1.ResumeLayout(false); 543 | this.splitMessageButtons.Panel2.ResumeLayout(false); 544 | ((System.ComponentModel.ISupportInitialize)(this.splitMessageButtons)).EndInit(); 545 | this.splitMessageButtons.ResumeLayout(false); 546 | this.panel1.ResumeLayout(false); 547 | this.panel1.PerformLayout(); 548 | this.ResumeLayout(false); 549 | this.PerformLayout(); 550 | 551 | } 552 | 553 | #endregion 554 | 555 | private System.Windows.Forms.StatusStrip statusStrip1; 556 | private System.Windows.Forms.MenuStrip menuStrip1; 557 | private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; 558 | private System.Windows.Forms.ToolStripMenuItem btnFileOpen; 559 | private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; 560 | private System.Windows.Forms.SplitContainer splitLeftRight; 561 | private System.Windows.Forms.DataGridView dataGridView1; 562 | private SwitchableTextBox textBox1; 563 | private System.Windows.Forms.Panel panel1; 564 | private System.Windows.Forms.Button button2; 565 | private System.Windows.Forms.Button button1; 566 | private System.Windows.Forms.SplitContainer splitMessageButtons; 567 | private System.Windows.Forms.SplitContainer splitFilterResult; 568 | private System.Windows.Forms.Button button4; 569 | private System.Windows.Forms.TextBox txtFilter; 570 | private System.Windows.Forms.Button button5; 571 | private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1; 572 | private System.Windows.Forms.ToolStripStatusLabel lblStatus; 573 | private System.Windows.Forms.ToolStripProgressBar progressBar; 574 | private System.Windows.Forms.CheckBox checkAutoFormat; 575 | private System.Windows.Forms.DataGridViewTextBoxColumn Datetime; 576 | private System.Windows.Forms.DataGridViewTextBoxColumn Size; 577 | private System.Windows.Forms.ToolStripStatusLabel lblFilename; 578 | private System.Windows.Forms.ToolStripMenuItem reloadFileToolStripMenuItem; 579 | private System.Windows.Forms.Label label1; 580 | private System.Windows.Forms.ComboBox cmbSouce; 581 | private System.Windows.Forms.ToolStripMenuItem closeToolStripMenuItem; 582 | private System.Windows.Forms.ToolStripMenuItem saveRequestAsToolStripMenuItem; 583 | private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; 584 | private System.Windows.Forms.ToolStripMenuItem extrasToolStripMenuItem; 585 | private System.Windows.Forms.ToolStripMenuItem setAppAsDefaultForsvclogFilesToolStripMenuItem; 586 | private System.Windows.Forms.CheckBox checkSyntaxColoring; 587 | private System.Windows.Forms.ToolStripMenuItem changelogToolStripMenuItem; 588 | private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; 589 | private System.Windows.Forms.Button btnDecodeBinary; 590 | private System.Windows.Forms.ToolStripMenuItem startsvclogAnalyzerToolStripMenuItem; 591 | private System.Windows.Forms.CheckBox cbAutoHtmlDecode; 592 | private System.Windows.Forms.CheckBox cbAutoUrlDecode; 593 | private System.Windows.Forms.ToolStripMenuItem submitFeedbackToolStripMenuItem; 594 | } 595 | } 596 | 597 | -------------------------------------------------------------------------------- /SvclogViewer/MainForm.cs: -------------------------------------------------------------------------------- 1 | using MsCommon.ClickOnce; 2 | using SvclogViewer.Config; 3 | using SvclogViewer.Entities; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Data; 7 | using System.Drawing; 8 | using System.Globalization; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Reflection; 12 | using System.Text; 13 | using System.Text.RegularExpressions; 14 | using System.Web; 15 | using System.Windows.Forms; 16 | using System.Xml.Linq; 17 | 18 | namespace SvclogViewer 19 | { 20 | public partial class MainForm : Form 21 | { 22 | private SvcIndexer indexer = new SvcIndexer(); 23 | private StreamReader reader = null; 24 | private List events = new List(); 25 | private List filteredEvents = null; 26 | private TraceEvent[] _currentVisibleTraceEvents; // for virtual mode 27 | private long lastSelectedEventOffset = -1; 28 | private string loadfileonstartup; 29 | 30 | public MainForm(string file) 31 | { 32 | loadfileonstartup = file; 33 | InitializeComponent(); 34 | Text = "SvclogViewer v" + AppVersion.GetVersion(); 35 | AppVersion.CheckForUpdateAsync(); 36 | Shown += HandleMainFormShown; 37 | FormClosing += HandleMainFormClosing; 38 | DisableInput(); 39 | lblStatus.Text = "starting..."; 40 | lblFilename.Text = ""; 41 | indexer.Progress += HandleIndexerProgress; 42 | progressBar.Minimum = 0; 43 | progressBar.Maximum = 100; 44 | progressBar.Step = 1; 45 | checkAutoFormat.CheckedChanged += HandleAutoFormatCheckedChanged; 46 | checkAutoFormat.Checked = Configuration.Instance.AutoXmlFormatEnabled; 47 | checkSyntaxColoring.CheckedChanged += HandleSyntaxColoringCheckedChanged; 48 | checkSyntaxColoring.Checked = Configuration.Instance.UseSyntaxColoring; 49 | cbAutoUrlDecode.CheckedChanged += HandleAutoUrlDecodeChanged; 50 | cbAutoUrlDecode.Checked = Configuration.Instance.UseAutoUrlDecode; 51 | cbAutoHtmlDecode.CheckedChanged += HandleAutoHtmlDecodeChanged; 52 | cbAutoHtmlDecode.Checked = Configuration.Instance.UseAutoHtmlDecode; 53 | cmbSouce.Items.Add("Any"); 54 | cmbSouce.SelectedIndex = 0; 55 | HandleSplitResize(this, new SplitterEventArgs(0, 0, 0, 0)); 56 | 57 | typeof(DataGridView).InvokeMember( 58 | "DoubleBuffered", 59 | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, 60 | null, 61 | dataGridView1, 62 | new object[] { true }); 63 | } 64 | 65 | private void HandleAutoHtmlDecodeChanged(object sender, EventArgs e) 66 | { 67 | Configuration.Instance.UseAutoHtmlDecode = cbAutoHtmlDecode.Checked; 68 | if (dataGridView1.CurrentCell != null) 69 | HandleGridSelectionChanged(this, EventArgs.Empty); 70 | } 71 | 72 | private void HandleAutoUrlDecodeChanged(object sender, EventArgs e) 73 | { 74 | Configuration.Instance.UseAutoUrlDecode = cbAutoUrlDecode.Checked; 75 | if (dataGridView1.CurrentCell != null) 76 | HandleGridSelectionChanged(this, EventArgs.Empty); 77 | } 78 | 79 | void HandleSyntaxColoringCheckedChanged(object sender, EventArgs e) 80 | { 81 | Configuration.Instance.UseSyntaxColoring = checkSyntaxColoring.Checked; 82 | textBox1.EnableSyntaxColoring = checkSyntaxColoring.Checked; 83 | } 84 | 85 | void HandleAutoFormatCheckedChanged(object sender, EventArgs e) 86 | { 87 | Configuration.Instance.AutoXmlFormatEnabled = checkAutoFormat.Checked; 88 | if (dataGridView1.CurrentCell != null) 89 | HandleGridSelectionChanged(this, EventArgs.Empty); 90 | } 91 | 92 | void HandleMainFormClosing(object sender, FormClosingEventArgs e) 93 | { 94 | Configuration.Instance.Save(); 95 | } 96 | 97 | void HandleIndexerProgress(object sender, ProgressEventArgs e) 98 | { 99 | int percentage = (int)((double)e.CurrentPosition / e.FileSize * 100); 100 | if (percentage != progressBar.Value) 101 | { 102 | progressBar.Value = percentage; 103 | lblStatus.Text = "loaded " + e.CurrentPosition + " of " + e.FileSize + " bytes"; 104 | Application.DoEvents(); // dirty hack for not having to program async 105 | } 106 | } 107 | 108 | void HandleMainFormShown(object sender, EventArgs e) 109 | { 110 | lblStatus.Text = "startup complete"; 111 | if (loadfileonstartup != null) 112 | LoadFile(loadfileonstartup); 113 | 114 | if (!Configuration.Instance.HasRefusedSetAsDefault) 115 | CheckDefault(); 116 | } 117 | 118 | private void CheckDefault() 119 | { 120 | if (!DefaultAssociationHelper.IsDefaultProgram()) 121 | { 122 | if (DefaultAssociationHelper.PresentMakeDefaultQuestion(this)) 123 | { 124 | Configuration.Instance.HasRefusedSetAsDefault = false; 125 | DefaultAssociationHelper.MakeDefault(this); 126 | } 127 | else 128 | { 129 | Configuration.Instance.HasRefusedSetAsDefault = true; 130 | } 131 | } 132 | } 133 | 134 | private void LoadFile(string filename) 135 | { 136 | DisableInput(); 137 | 138 | // Close old reader 139 | if (reader != null) 140 | { 141 | reader.Close(); 142 | reader.Dispose(); 143 | } 144 | 145 | // Empty datagrid 146 | _currentVisibleTraceEvents = null; 147 | dataGridView1.Rows.Clear(); 148 | 149 | // Open and index new file 150 | var filestream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete, 4096, FileOptions.RandomAccess); 151 | reader = new StreamReader(filestream, Encoding.ASCII); 152 | events = indexer.Index(reader); 153 | 154 | // Fill the source box 155 | cmbSouce.Items.Clear(); 156 | cmbSouce.Items.Add("Any"); 157 | int selectedIndex = 0; 158 | int currentIndex = 0; 159 | foreach (string source in events.Select(e => e.Source).Distinct()) 160 | { 161 | currentIndex++; 162 | cmbSouce.Items.Add(source); 163 | if (source == Configuration.Instance.LastSelectedSource) 164 | selectedIndex = currentIndex; 165 | } 166 | cmbSouce.SelectedIndex = selectedIndex; 167 | 168 | // Add indexes to grid 169 | filteredEvents = null; 170 | RefreshEventList(); 171 | EnableInput(); 172 | lblStatus.Text = "file loaded"; 173 | lblFilename.Text = filename; 174 | Text = "SvclogViewer - " + Path.GetFileName(filename); 175 | } 176 | 177 | private Color GetColor(Guid guid) 178 | { 179 | Color c = Color.FromArgb(guid.GetHashCode()); 180 | c = Color.FromArgb(255, c.R % 128 + 127, c.G % 128 + 127, c.B % 128 + 127); 181 | return c; 182 | } 183 | 184 | private void HandleFileOpen(object sender, EventArgs e) 185 | { 186 | var dialog = new OpenFileDialog(); 187 | dialog.CheckFileExists = true; 188 | dialog.Filter = "Svclog (*.svclog)|*.svclog|All files (*.*)|*.*"; 189 | dialog.Multiselect = false; 190 | dialog.ReadOnlyChecked = true; 191 | var result = dialog.ShowDialog(this); 192 | if (result == DialogResult.Cancel) 193 | return; 194 | LoadFile(dialog.FileName); 195 | } 196 | 197 | private void HandleChangelogClicked(object sender, EventArgs e) 198 | { 199 | AppVersion.DisplayChanges(); 200 | } 201 | 202 | private void HandleAbout(object sender, EventArgs e) 203 | { 204 | AppVersion.DisplayAbout(); 205 | } 206 | 207 | private void HandleGridSelectionChanged(object sender, EventArgs e) 208 | { 209 | if (reader == null) 210 | return; 211 | if (dataGridView1.CurrentCell == null) 212 | return; 213 | TraceEvent evt = GetTraceEvent(dataGridView1.CurrentCell.RowIndex); 214 | if (evt == null) 215 | return; 216 | if (reader.BaseStream == null) 217 | return; 218 | 219 | long dataLength = evt.PositionEnd - evt.PositionStart; 220 | reader.BaseStream.Position = evt.PositionStart; 221 | reader.DiscardBufferedData(); 222 | char[] chars = new char[dataLength]; 223 | reader.ReadBlock(chars, 0, chars.Length); 224 | string str = new string(chars); 225 | 226 | if (checkAutoFormat.Checked) 227 | FormatXML(str); 228 | else 229 | textBox1.Text = str; 230 | 231 | if (Configuration.Instance.UseAutoUrlDecode) 232 | UrlDecodeXML(); 233 | 234 | if (Configuration.Instance.UseAutoHtmlDecode) 235 | HtmlDecodeXML(); 236 | 237 | bool containsBinary = GetBinary(str) != null; 238 | btnDecodeBinary.Visible = containsBinary; 239 | btnDecodeBinary.Enabled = containsBinary; 240 | } 241 | 242 | private void FormatXML(string txtToFormat) 243 | { 244 | if (string.IsNullOrWhiteSpace(txtToFormat)) 245 | return; 246 | textBox1.Text = XDocument.Parse(txtToFormat).ToString(); 247 | } 248 | 249 | private void UrlDecodeXML() 250 | { 251 | textBox1.Text = HttpUtility.UrlDecode(textBox1.Text); 252 | } 253 | 254 | private void HtmlDecodeXML() 255 | { 256 | textBox1.Text = HttpUtility.HtmlDecode(textBox1.Text); 257 | } 258 | 259 | private void HandleFormatXML(object sender, EventArgs e) 260 | { 261 | FormatXML(textBox1.Text); 262 | } 263 | 264 | private void HandleCopyToClipboard(object sender, EventArgs e) 265 | { 266 | Clipboard.SetText(textBox1.Text, TextDataFormat.Text); 267 | } 268 | 269 | private void HandleCopySoapenvToClipboard(object sender, EventArgs e) 270 | { 271 | string text = textBox1.Text; 272 | 273 | try 274 | { 275 | int nsPos = text.IndexOf("http://schemas.xmlsoap.org/soap/envelope/", StringComparison.InvariantCultureIgnoreCase); 276 | int openingPos = text.LastIndexOf('<', nsPos); 277 | int openingSpacePos = text.IndexOf(" ", openingPos); 278 | string openingStr = text.Substring(openingPos, openingSpacePos - openingPos); 279 | string closingStr = openingStr.Replace("<", "", closingStartPos); 282 | text = text.Substring(openingPos, closingEndPos - openingPos + 1); 283 | Clipboard.SetText(text, TextDataFormat.Text); 284 | textBox1.Text = text; 285 | } 286 | catch (Exception) 287 | { 288 | MessageBox.Show("Error trying to extract the soap envelope or copying it to the clipboard.\r\n\r\nNote that UrlDecode and HtmlDecode will make the XML invalid and cause this feature to fail."); 289 | } 290 | } 291 | 292 | private void HandleFilterClick(object sender, EventArgs e) 293 | { 294 | if (reader == null) 295 | return; 296 | 297 | if (txtFilter.Text.Length < 5) 298 | { 299 | DialogResult res = MessageBox.Show(this, "Filtering can take a long time if your search string is too small. Are you sure you want to continue?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); 300 | if (res == DialogResult.No) 301 | return; 302 | } 303 | DisableInput(); 304 | dataGridView1.Rows.Clear(); 305 | List occurrences = indexer.FindOccurrences(reader, txtFilter.Text); 306 | var results = (from evt in events 307 | from o in occurrences 308 | where evt.PositionStart <= o && evt.PositionEnd >= o 309 | select evt); 310 | filteredEvents = results.Distinct().ToList(); 311 | RefreshEventList(); 312 | EnableInput(); 313 | lblStatus.Text = "done filtering"; 314 | } 315 | 316 | private void HandleFilterKeyUp(object sender, KeyEventArgs e) 317 | { 318 | if (e.KeyValue == 13) 319 | { 320 | HandleFilterClick(sender, e); 321 | } 322 | } 323 | 324 | private void HandleFilterClear(object sender, EventArgs e) 325 | { 326 | DisableInput(); 327 | filteredEvents = null; 328 | RefreshEventList(); 329 | EnableInput(); 330 | } 331 | 332 | private void RefreshEventList() 333 | { 334 | dataGridView1.Rows.Clear(); 335 | List visibleEvents = new List(); 336 | string selectedSource = (string)cmbSouce.Items[cmbSouce.SelectedIndex]; 337 | foreach (var evt in filteredEvents ?? events) 338 | { 339 | if (selectedSource != "Any" && selectedSource != evt.Source) 340 | continue; 341 | visibleEvents.Add(evt); 342 | } 343 | _currentVisibleTraceEvents = visibleEvents.ToArray(); 344 | 345 | // Columns have a fixed width for performance 346 | dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None; 347 | 348 | // Rows have a fixed height for performance, calculate once 349 | dataGridView1.VirtualMode = false; 350 | dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells; 351 | dataGridView1.Rows.Add("dummy\r\ndummy", ""); 352 | int calculatedheight = dataGridView1.Rows[0].Height; 353 | dataGridView1.Rows.Clear(); 354 | dataGridView1.VirtualMode = true; 355 | dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None; 356 | dataGridView1.RowTemplate.Height = calculatedheight; 357 | 358 | // Update the rowcount, performance hit! Make sure the rows are cleared beforehand 359 | dataGridView1.RowCount = _currentVisibleTraceEvents.Length; 360 | 361 | // Re-select the correct row, if found 362 | int selectedrow = Array.FindIndex(_currentVisibleTraceEvents, t => t.PositionStart == lastSelectedEventOffset); 363 | if (selectedrow >= 0) 364 | { 365 | dataGridView1.CurrentCell = null; 366 | dataGridView1.CurrentCell = dataGridView1.Rows[selectedrow].Cells[0]; 367 | } 368 | 369 | // Refresh the currently visible rows, to update content and background colors 370 | dataGridView1.Invalidate(); 371 | } 372 | 373 | private void HandleDragEnter(object sender, DragEventArgs e) 374 | { 375 | var data = e.Data.GetData("FileNameW"); 376 | if (data != null && data is string[]) 377 | { 378 | string[] filenames = data as string[]; 379 | if (filenames.Length == 0) 380 | return; 381 | string filename = filenames.First(); 382 | if (File.Exists(filename)) 383 | e.Effect = DragDropEffects.Copy; 384 | } 385 | } 386 | 387 | private void HandleDragDrop(object sender, DragEventArgs e) 388 | { 389 | var data = e.Data.GetData("FileNameW"); 390 | if (data != null && data is string[]) 391 | { 392 | string[] filenames = data as string[]; 393 | if (filenames.Length == 0) 394 | return; 395 | string filename = filenames.First(); 396 | LoadFile(filename); 397 | } 398 | } 399 | 400 | private void EnableInput() 401 | { 402 | splitLeftRight.Enabled = true; 403 | dataGridView1.ScrollBars = ScrollBars.Vertical; 404 | DataGridViewRow selectedRow = dataGridView1.Rows.Cast().Where(r => r.Selected).FirstOrDefault(); 405 | if (selectedRow != null && !selectedRow.Displayed) 406 | { 407 | if (selectedRow.Index > 2) 408 | dataGridView1.FirstDisplayedScrollingRowIndex = selectedRow.Index - 2; 409 | else 410 | dataGridView1.FirstDisplayedScrollingRowIndex = selectedRow.Index; 411 | } 412 | } 413 | 414 | private void DisableInput() 415 | { 416 | if (dataGridView1.SelectedRows.Count > 0) 417 | { 418 | TraceEvent evt = GetTraceEvent(dataGridView1.CurrentCell.RowIndex); 419 | if (evt != null) 420 | lastSelectedEventOffset = evt.PositionStart; 421 | } 422 | splitLeftRight.Enabled = false; 423 | dataGridView1.ScrollBars = ScrollBars.None; 424 | } 425 | 426 | private void HandleReloadFile(object sender, EventArgs e) 427 | { 428 | if (reader != null) 429 | { 430 | var filestream = reader.BaseStream as FileStream; 431 | if (filestream != null) 432 | { 433 | if (File.Exists(filestream.Name)) 434 | { 435 | LoadFile(filestream.Name); 436 | } 437 | else 438 | { 439 | MessageBox.Show(this, "File '" + filestream.Name + "' no longer exists.", "Oops?"); 440 | } 441 | } 442 | } 443 | } 444 | 445 | private void HandleSourceChanged(object sender, EventArgs e) 446 | { 447 | DisableInput(); 448 | Configuration.Instance.LastSelectedSource = (string)cmbSouce.Items[cmbSouce.SelectedIndex]; 449 | RefreshEventList(); 450 | EnableInput(); 451 | } 452 | 453 | private void HandleClose(object sender, EventArgs e) 454 | { 455 | Close(); 456 | } 457 | 458 | private void HandleSaveRequestAsClicked(object sender, EventArgs e) 459 | { 460 | SaveFileDialog dialog = new SaveFileDialog(); 461 | dialog.Filter = "xml files (*.xml)|*.xml|All files (*.*)|*.*"; 462 | if (dialog.ShowDialog() == DialogResult.OK) 463 | { 464 | using (Stream s = File.Open(dialog.FileName, FileMode.CreateNew)) 465 | { 466 | using (StreamWriter sw = new StreamWriter(s)) 467 | { 468 | sw.Write(textBox1.Text); 469 | } 470 | } 471 | } 472 | } 473 | 474 | private void HandleSetAsDefaultClick(object sender, EventArgs e) 475 | { 476 | if (DefaultAssociationHelper.IsDefaultProgram()) 477 | { 478 | MessageBox.Show(this, "Already set as default application to handle .svclog files..."); 479 | } 480 | else 481 | { 482 | CheckDefault(); 483 | } 484 | } 485 | 486 | private TraceEvent GetTraceEvent(int rowindex) 487 | { 488 | if (_currentVisibleTraceEvents == null) 489 | return null; 490 | 491 | if (rowindex < 0 || rowindex >= _currentVisibleTraceEvents.Length) 492 | return null; 493 | 494 | return _currentVisibleTraceEvents[rowindex]; 495 | 496 | } 497 | 498 | private void HandleCellValueNeeded(object sender, DataGridViewCellValueEventArgs e) 499 | { 500 | TraceEvent evt = GetTraceEvent(e.RowIndex); 501 | if (evt == null) 502 | return; 503 | 504 | switch (e.ColumnIndex) 505 | { 506 | case 0: 507 | e.Value = evt.TimeCreated.ToString("yyyy'-'MM'-'dd HH':'mm':'ss.fffffff") + "\r\n" + evt.Method; 508 | break; 509 | case 1: 510 | e.Value = ((evt.PositionEnd - evt.PositionStart) / 1000.0).ToString("0.0", CultureInfo.GetCultureInfo("nl-NL")); 511 | break; 512 | default: 513 | e.Value = string.Empty; 514 | break; 515 | } 516 | } 517 | 518 | private void HandleCellFormatting(object sender, DataGridViewCellFormattingEventArgs e) 519 | { 520 | TraceEvent evt = GetTraceEvent(e.RowIndex); 521 | if (evt == null) 522 | return; 523 | 524 | Color color = GetColor(evt.ActivityID); 525 | if (e.CellStyle.BackColor != color) 526 | { 527 | e.CellStyle.BackColor = color; 528 | e.FormattingApplied = true; 529 | } 530 | } 531 | 532 | private string GetBinary(string str) 533 | { 534 | if (str.Contains("(.*?).*")) 535 | { 536 | string binary = Regex.Match(str, ".*(.*?).*").Groups[1].Value; 537 | if (!string.IsNullOrWhiteSpace(binary) && binary.Length % 4 == 0) 538 | { 539 | try 540 | { 541 | byte[] data = Convert.FromBase64String(binary); 542 | if (data != null) 543 | return binary; 544 | } 545 | catch (Exception) 546 | { 547 | // error in base64 548 | } 549 | } 550 | } 551 | return null; 552 | } 553 | 554 | private void HandleDecodeBinaryClicked(object sender, EventArgs e) 555 | { 556 | string binary = GetBinary(textBox1.Text); 557 | if (binary == null) 558 | return; 559 | 560 | byte[] data = Convert.FromBase64String(binary); 561 | string decodedString = Encoding.UTF8.GetString(data); 562 | 563 | if (checkAutoFormat.Checked) 564 | FormatXML(decodedString); 565 | else 566 | textBox1.Text = decodedString; 567 | 568 | if (Configuration.Instance.UseAutoUrlDecode) 569 | UrlDecodeXML(); 570 | 571 | if (Configuration.Instance.UseAutoHtmlDecode) 572 | HtmlDecodeXML(); 573 | 574 | btnDecodeBinary.Enabled = false; 575 | } 576 | 577 | private void HandleStartAnalyzerClicked(object sender, EventArgs e) 578 | { 579 | new SvcAnalyzerDropper().ShowDialog(this); 580 | } 581 | 582 | private void HandleSplitResize(object sender, SplitterEventArgs e) 583 | { 584 | // When the left/right is resized, adjust column size for the gridview on the left side 585 | var newWidth = splitLeftRight.Panel1.Width - 90; 586 | if (newWidth < 50) 587 | newWidth = 50; 588 | dataGridView1.Columns.GetFirstColumn(DataGridViewElementStates.Visible).Width = newWidth; 589 | } 590 | 591 | private void HandleSubmitFeedbackClicked(object sender, EventArgs e) 592 | { 593 | new FeedbackForm().ShowDialog(this); 594 | } 595 | } 596 | } 597 | -------------------------------------------------------------------------------- /SvclogViewer/Program.cs: -------------------------------------------------------------------------------- 1 | using MsCommon.ClickOnce; 2 | using System; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Windows.Forms; 6 | 7 | namespace SvclogViewer 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main(string[] arguments) 16 | { 17 | Action method = (args) => 18 | { 19 | // Check if this is a "MakeDefault" call 20 | if (args != null && args.Length > 0 && args[0] == "MakeDefault") 21 | { 22 | if (DefaultAssociationHelper.MakeDefaultInternal(null)) 23 | { 24 | Environment.ExitCode = 101; 25 | } 26 | return; 27 | } 28 | 29 | string file = null; 30 | if (args != null) 31 | { 32 | file = args.Where(s => File.Exists(s)).FirstOrDefault(); 33 | } 34 | 35 | Application.EnableVisualStyles(); 36 | Application.SetCompatibleTextRenderingDefault(false); 37 | Application.Run(new MainForm(file)); 38 | }; 39 | 40 | AppProgram.Start( 41 | applicationName: "SvclogViewer", 42 | authorName: "Martijn Stolk", 43 | reportBugEndpoint: "http://martijn.tikkie.net/reportbug.php", 44 | feedbackEndpoint: "http://martijn.tikkie.net/feedback.php", 45 | args: arguments, 46 | mainMethod: method); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /SvclogViewer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SvclogViewer")] 9 | [assembly: AssemblyDescription("High-performance viewer for messages within .svclog files")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Tikkie")] 12 | [assembly: AssemblyProduct("SvclogViewer")] 13 | [assembly: AssemblyCopyright("Copyright © Martijn Stolk 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a70e7c04-08a3-4b05-834e-cd96fef32476")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SvclogViewer/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace SvclogViewer.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SvclogViewer.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /SvclogViewer/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /SvclogViewer/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace SvclogViewer.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SvclogViewer/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SvclogViewer/Properties/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 52 | -------------------------------------------------------------------------------- /SvclogViewer/SvcAnalyzer.cs: -------------------------------------------------------------------------------- 1 | using SvclogViewer.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace SvclogViewer 10 | { 11 | public class AnalyzeEventArgs : EventArgs 12 | { 13 | public string CurrentFileName { get; set; } 14 | public FileAccess CurrentOperation { get; set; } 15 | public long CurrentPosition { get; set; } 16 | public long FileSize { get; set; } 17 | } 18 | 19 | public class SvcAnalyzer 20 | { 21 | public event EventHandler Progress; 22 | 23 | private string _currentFile; 24 | private FileAccess _currentOperation; 25 | 26 | public void Analyze(string[] contentFilters, params string[] files) 27 | { 28 | var indexer = new SvcIndexer(); 29 | indexer.Progress += HandleIndexerProgress; 30 | 31 | foreach (var file in files) 32 | { 33 | OnProgress(file, FileAccess.Read, 1, 0); 34 | var reader = new StreamReader(file); 35 | 36 | // Filters, empty for now. 37 | string[] filters = contentFilters ?? new string[] { }; 38 | 39 | // Read file 40 | IEnumerable events = indexer.Index(reader); 41 | List occurrences = new List(); 42 | if (filters.Length > 0) 43 | { 44 | foreach (var filter in filters) 45 | { 46 | occurrences.AddRange(indexer.FindOccurrences(reader, filter)); 47 | } 48 | } 49 | 50 | // Only use Transport 51 | events = events.Where(e => e.Source == "Transport"); 52 | 53 | string outputfile = files.First() + ".csv"; 54 | OnProgress(outputfile, FileAccess.Write, 1, 0); 55 | using (StreamWriter sw = new StreamWriter(outputfile, true)) 56 | { 57 | sw.WriteLine("Date;DurationInMs;Method;URL"); 58 | foreach (var pair in events.GroupBy(e => e.ActivityID)) 59 | { 60 | var first = pair.OrderBy(p => p.TimeCreated).First(); 61 | var last = pair.OrderBy(p => p.TimeCreated).Last(); 62 | 63 | // If there is a filter but the first/last pair do not match, skip this pair. 64 | if (filters.Length > 0 && !occurrences.Where(o => first.ContainsPosition(o) || last.ContainsPosition(o)).Any()) 65 | { 66 | continue; 67 | } 68 | 69 | var duration = last.TimeCreated - first.TimeCreated; 70 | string date = first.TimeCreated.ToString("yyyy-MM-dd HH:mm:ss.fff"); 71 | string durationInMs = first == last ? "N/A" : ((long)duration.TotalMilliseconds).ToString(); 72 | string method = first.Method; 73 | string url = first.To; 74 | sw.WriteLine(string.Format("{0};{1};{2};{3}", 75 | "\"" + date.Replace("\"", "\"\"") + "\"", 76 | "\"" + durationInMs.Replace("\"", "\"\"") + "\"", 77 | "\"" + method.Replace("\"", "\"\"") + "\"", 78 | "\"" + url.Replace("\"", "\"\"") + "\"" 79 | )); 80 | } 81 | } 82 | OnProgress(outputfile, FileAccess.Write, 1, 1); 83 | } 84 | } 85 | 86 | private void HandleIndexerProgress(object sender, ProgressEventArgs e) 87 | { 88 | OnProgress(_currentFile, _currentOperation, e.FileSize, e.CurrentPosition); 89 | } 90 | 91 | private void OnProgress(string currentFile, FileAccess currentOperation, long fileSize, long currentPosition) 92 | { 93 | _currentFile = currentFile; 94 | _currentOperation = currentOperation; 95 | var handler = Progress; 96 | if (handler != null) 97 | handler(this, new AnalyzeEventArgs 98 | { 99 | CurrentFileName = currentFile, 100 | CurrentOperation = currentOperation, 101 | FileSize = fileSize, 102 | CurrentPosition = currentPosition 103 | }); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /SvclogViewer/SvcAnalyzerDropper.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace SvclogViewer 2 | { 3 | partial class SvcAnalyzerDropper 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.label1 = new System.Windows.Forms.Label(); 32 | this.label2 = new System.Windows.Forms.Label(); 33 | this.lbStatus = new System.Windows.Forms.Label(); 34 | this.SuspendLayout(); 35 | // 36 | // label1 37 | // 38 | this.label1.AutoSize = true; 39 | this.label1.Location = new System.Drawing.Point(12, 9); 40 | this.label1.Name = "label1"; 41 | this.label1.Size = new System.Drawing.Size(563, 13); 42 | this.label1.TabIndex = 0; 43 | this.label1.Text = "Drop your .svclog files here. The result file will be generated in the same filep" + 44 | "ath, adding a \".csv\" suffix to the filename."; 45 | // 46 | // label2 47 | // 48 | this.label2.AutoSize = true; 49 | this.label2.Location = new System.Drawing.Point(13, 102); 50 | this.label2.Name = "label2"; 51 | this.label2.Size = new System.Drawing.Size(40, 13); 52 | this.label2.TabIndex = 1; 53 | this.label2.Text = "Status:"; 54 | // 55 | // lbStatus 56 | // 57 | this.lbStatus.AutoSize = true; 58 | this.lbStatus.Location = new System.Drawing.Point(60, 101); 59 | this.lbStatus.Name = "lbStatus"; 60 | this.lbStatus.Size = new System.Drawing.Size(49, 13); 61 | this.lbStatus.TabIndex = 2; 62 | this.lbStatus.Text = "waiting..."; 63 | // 64 | // SvcAnalyzerDropper 65 | // 66 | this.AllowDrop = true; 67 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 68 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 69 | this.ClientSize = new System.Drawing.Size(723, 127); 70 | this.Controls.Add(this.lbStatus); 71 | this.Controls.Add(this.label2); 72 | this.Controls.Add(this.label1); 73 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 74 | this.MaximizeBox = false; 75 | this.MinimizeBox = false; 76 | this.Name = "SvcAnalyzerDropper"; 77 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; 78 | this.Text = "Svclog Analyzer"; 79 | this.TopMost = true; 80 | this.DragDrop += new System.Windows.Forms.DragEventHandler(this.HandleDragDrop); 81 | this.DragEnter += new System.Windows.Forms.DragEventHandler(this.HandleDragEnter); 82 | this.ResumeLayout(false); 83 | this.PerformLayout(); 84 | 85 | } 86 | 87 | #endregion 88 | 89 | private System.Windows.Forms.Label label1; 90 | private System.Windows.Forms.Label label2; 91 | private System.Windows.Forms.Label lbStatus; 92 | } 93 | } -------------------------------------------------------------------------------- /SvclogViewer/SvcAnalyzerDropper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | using System.Windows.Forms; 12 | 13 | namespace SvclogViewer 14 | { 15 | public partial class SvcAnalyzerDropper : Form 16 | { 17 | public SvcAnalyzerDropper() 18 | { 19 | InitializeComponent(); 20 | } 21 | 22 | private void HandleDragEnter(object sender, DragEventArgs e) 23 | { 24 | var data = e.Data.GetData(DataFormats.FileDrop); 25 | if (data != null && data is string[]) 26 | { 27 | string[] filenames = data as string[]; 28 | if (filenames.Length == 0) 29 | return; 30 | foreach (var filename in filenames) 31 | { 32 | if (!File.Exists(filename)) 33 | return; 34 | } 35 | e.Effect = DragDropEffects.Copy; 36 | } 37 | } 38 | 39 | private void HandleDragDrop(object sender, DragEventArgs e) 40 | { 41 | var data = e.Data.GetData(DataFormats.FileDrop); 42 | if (data != null && data is string[]) 43 | { 44 | string[] filenames = data as string[]; 45 | if (filenames.Length == 0) 46 | return; 47 | new Thread(() => 48 | { 49 | var analyzer = new SvcAnalyzer(); 50 | analyzer.Progress += HandleAnalyzerProgress; 51 | analyzer.Analyze(null, filenames); 52 | UpdateLabel("Done, waiting..."); 53 | }).Start(); 54 | } 55 | } 56 | 57 | private int _lastPercentage; 58 | 59 | private void HandleAnalyzerProgress(object sender, AnalyzeEventArgs e) 60 | { 61 | int percentage = (int)((double)e.CurrentPosition / e.FileSize * 100); 62 | if (percentage != _lastPercentage) 63 | { 64 | _lastPercentage = percentage; 65 | string msg = string.Format("File: {0}, Mode: {1}, Progress: {2}% ({3} / {4})", Path.GetFileName(e.CurrentFileName), e.CurrentOperation, percentage, e.CurrentPosition, e.FileSize); 66 | UpdateLabel(msg); 67 | } 68 | } 69 | 70 | private void UpdateLabel(string msg) 71 | { 72 | if (InvokeRequired) 73 | { 74 | Invoke((Action)UpdateLabel, msg); 75 | return; 76 | } 77 | 78 | lbStatus.Text = msg; 79 | Application.DoEvents(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /SvclogViewer/SvcAnalyzerDropper.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /SvclogViewer/SvcIndexer.cs: -------------------------------------------------------------------------------- 1 | using SvclogViewer.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Text.RegularExpressions; 8 | 9 | namespace SvclogViewer 10 | { 11 | public class ProgressEventArgs : EventArgs 12 | { 13 | public long CurrentPosition { get; set; } 14 | public long FileSize { get; set; } 15 | } 16 | 17 | public class SvcIndexer 18 | { 19 | public const string RecordStart = " Progress; 23 | 24 | protected void OnProgress(long curpos, long size) 25 | { 26 | var handler = Progress; 27 | if (handler != null) 28 | handler(this, new ProgressEventArgs { CurrentPosition = curpos, FileSize = size }); 29 | } 30 | 31 | public List Index(StreamReader reader) 32 | { 33 | List events = new List(); 34 | long curPos = 0; 35 | while (true) 36 | { 37 | TraceEvent evt = new TraceEvent(); 38 | 39 | evt.PositionStart = FindStringInStream(reader, RecordStart, curPos); 40 | if (evt.PositionStart == -1) 41 | break; // No new tracerecord found 42 | ReadActivityID(reader, evt, evt.PositionStart, 300); 43 | ReadTimeAndSource(reader, evt, evt.PositionStart, 120); 44 | evt.PositionEnd = FindStringInStream(reader, RecordEnd, evt.PositionStart); 45 | if (evt.PositionEnd == -1) 46 | break; // A tracerecord was found, but the ending was not found 47 | evt.PositionEnd = evt.PositionEnd + RecordEnd.Length; 48 | evt.To = FindTo(reader, evt.PositionStart, evt.PositionEnd); 49 | evt.Method = FindMethod(reader, evt.PositionStart, evt.PositionEnd); 50 | 51 | // Start searching from the endposition again 52 | curPos = evt.PositionEnd; 53 | 54 | events.Add(evt); 55 | } 56 | 57 | OnProgress(reader.BaseStream.Length, reader.BaseStream.Length); 58 | return events; 59 | } 60 | 61 | private string FindTo(StreamReader reader, long startPos, long endPos) 62 | { 63 | long pos = FindStringInStream(reader, "", startPos, endPos); 64 | if (pos == -1) 65 | return string.Empty; 66 | reader.BaseStream.Seek(pos, SeekOrigin.Begin); 67 | reader.DiscardBufferedData(); 68 | char[] buffer = new char[4096]; 69 | int charsRead = reader.ReadBlock(buffer, 0, buffer.Length); 70 | string str = new string(buffer, 0, charsRead); 71 | Match m = Regex.Match(str, @".*?(.*?)().*", RegexOptions.IgnoreCase); 89 | if (m != null && m.Success) 90 | { 91 | string method = m.Groups[1].Value; 92 | if (method.Contains(":")) 93 | { 94 | method = method.Split(':')[1]; 95 | } 96 | return method; 97 | } 98 | return string.Empty; 99 | } 100 | 101 | public List FindOccurrences(StreamReader reader, string needle) 102 | { 103 | List occurrences = new List(); 104 | long curPos = 0; 105 | while (true) 106 | { 107 | curPos = FindStringInStream(reader, needle, curPos); 108 | if (curPos == -1) 109 | break; 110 | occurrences.Add(curPos); 111 | curPos += needle.Length; 112 | } 113 | 114 | OnProgress(reader.BaseStream.Length, reader.BaseStream.Length); 115 | return occurrences; 116 | } 117 | 118 | private void ReadTimeAndSource(StreamReader reader, TraceEvent evt, long fromPosition, long sizeToScan) 119 | { 120 | reader.BaseStream.Seek(fromPosition, SeekOrigin.Begin); 121 | reader.DiscardBufferedData(); 122 | char[] buffer = new char[sizeToScan]; 123 | int charsRead = reader.ReadBlock(buffer, 0, buffer.Length); 124 | string str = new string(buffer, 0, charsRead); 125 | Match m = Regex.Match(str, @"Time=""(.*?)"".*?Source=""(.*?)""", RegexOptions.IgnoreCase); 126 | if (m != null && m.Success) 127 | { 128 | string dt = m.Groups[1].Value; 129 | DateTime parsedDt; 130 | if (DateTime.TryParse(dt, out parsedDt)) 131 | evt.TimeCreated = parsedDt; 132 | evt.Source = m.Groups[2].Value; 133 | evt.Source = evt.Source.Replace("SendRequest", "").Replace("ReceiveReply", "").Replace("Send", "").Replace("Receive", ""); 134 | } 135 | } 136 | 137 | private void ReadActivityID(StreamReader reader, TraceEvent evt, long fromPosition, long sizeToScan) 138 | { 139 | reader.BaseStream.Seek(fromPosition - sizeToScan, SeekOrigin.Begin); 140 | reader.DiscardBufferedData(); 141 | char[] buffer = new char[sizeToScan]; 142 | int charsRead = reader.ReadBlock(buffer, 0, buffer.Length); 143 | string str = new string(buffer, 0, charsRead); 144 | Match m = Regex.Match(str, ".*?ActivityID=\"{(.*?)}.*", RegexOptions.IgnoreCase); 145 | if (m != null && m.Success) 146 | { 147 | string guid = m.Groups[1].Value; 148 | Guid parsedGuid; 149 | if (Guid.TryParse(guid, out parsedGuid)) 150 | evt.ActivityID = parsedGuid; 151 | } 152 | } 153 | 154 | private long FindStringInStream(StreamReader reader, string needle, long fromPosition, long maxPosition = -1) 155 | { 156 | reader.BaseStream.Seek(fromPosition, SeekOrigin.Begin); 157 | reader.DiscardBufferedData(); 158 | char[] buffer = new char[4096]; 159 | int charsRead; 160 | int count = 0; 161 | while ((charsRead = reader.Read(buffer, 0, buffer.Length)) > 0) 162 | { 163 | OnProgress(fromPosition, reader.BaseStream.Length); 164 | for (int c = 0; c < charsRead; c++) 165 | { 166 | // Max reached? 167 | if (maxPosition != -1 && maxPosition < fromPosition + c) 168 | return -1; 169 | 170 | // Part of our needle? 171 | if (buffer[c] == needle[count]) 172 | count++; 173 | else 174 | count = 0; 175 | 176 | // Needle complete? 177 | if (count == needle.Length) 178 | return fromPosition + (c+1) - needle.Length; 179 | } 180 | fromPosition += charsRead; 181 | } 182 | return -1; 183 | } 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /SvclogViewer/SvclogViewer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {02C83A78-48DF-4F4C-B54B-E062E2DB8294} 9 | WinExe 10 | Properties 11 | SvclogViewer 12 | SvclogViewer 13 | v4.5.2 14 | 15 | 16 | 512 17 | true 18 | ftp://martijn.tikkie.net%40ftp.pcextreme.nl/apps/SvclogViewer/ 19 | true 20 | Web 21 | true 22 | Background 23 | 7 24 | Days 25 | false 26 | false 27 | true 28 | http://martijn.tikkie.net/apps/SvclogViewer/ 29 | http://www.netripper.nl 30 | SvclogViewer 31 | Tikkie 32 | true 33 | publish.htm 34 | 71 35 | 1.0.0.%2a 36 | false 37 | true 38 | true 39 | true 40 | 41 | 42 | AnyCPU 43 | true 44 | full 45 | false 46 | bin\Debug\ 47 | DEBUG;TRACE 48 | prompt 49 | 4 50 | false 51 | 52 | 53 | x86 54 | pdbonly 55 | true 56 | bin\Release\ 57 | TRACE 58 | prompt 59 | 4 60 | false 61 | 62 | 63 | 64 | 65 | 66 | true 67 | 68 | 69 | EDB501EE2E946250AF0FDDF2260AFB75F3345A6E 70 | 71 | 72 | appicon.ico 73 | 74 | 75 | true 76 | 77 | 78 | false 79 | 80 | 81 | false 82 | 83 | 84 | 85 | 86 | 87 | 88 | OnBuildSuccess 89 | 90 | 91 | LocalIntranet 92 | 93 | 94 | Properties\app.manifest 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | False 103 | ..\ExternalLibs\FastColoredTextBox.dll 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | Form 122 | 123 | 124 | SvcAnalyzerDropper.cs 125 | 126 | 127 | Form 128 | 129 | 130 | MainForm.cs 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | UserControl 139 | 140 | 141 | SwitchableTextBox.cs 142 | 143 | 144 | SvcAnalyzerDropper.cs 145 | 146 | 147 | MainForm.cs 148 | 149 | 150 | ResXFileCodeGenerator 151 | Resources.Designer.cs 152 | Designer 153 | 154 | 155 | True 156 | Resources.resx 157 | True 158 | 159 | 160 | 161 | 162 | SettingsSingleFileGenerator 163 | Settings.Designer.cs 164 | 165 | 166 | True 167 | Settings.settings 168 | True 169 | 170 | 171 | 172 | 173 | False 174 | Microsoft .NET Framework 4 Client Profile %28x86 and x64%29 175 | true 176 | 177 | 178 | False 179 | .NET Framework 3.5 SP1 Client Profile 180 | false 181 | 182 | 183 | False 184 | .NET Framework 3.5 SP1 185 | false 186 | 187 | 188 | False 189 | Windows Installer 4.5 190 | true 191 | 192 | 193 | 194 | 195 | False 196 | SVC Log File 197 | Tikkie.SvcLogViewer 198 | appicon.ico 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | Always 207 | 208 | 209 | 210 | 211 | False 212 | 213 | 214 | 215 | 216 | Include 217 | True 218 | File 219 | 220 | 221 | False 222 | 223 | 224 | 225 | 226 | Include 227 | True 228 | File 229 | 230 | 231 | 232 | 233 | {28aff2bb-79a2-46a2-9ef0-202b188aa028} 234 | MsCommon.ClickOnce 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 249 | 250 | 251 | 252 | $(WindowsSDK80Path)bin\x86\signtool.exe 253 | $(WindowsSDK80Path)bin\x64\signtool.exe 254 | 255 | 256 | 257 | 258 | 259 | 260 | -------------------------------------------------------------------------------- /SvclogViewer/SwitchableTextBox.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace SvclogViewer 2 | { 3 | partial class SwitchableTextBox 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | components = new System.ComponentModel.Container(); 32 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 33 | } 34 | 35 | #endregion 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SvclogViewer/SwitchableTextBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | using FastColoredTextBoxNS; 10 | 11 | namespace SvclogViewer 12 | { 13 | 14 | public partial class SwitchableTextBox : UserControl 15 | { 16 | public SwitchableTextBox() 17 | { 18 | InitializeComponent(); 19 | Controls.Add(GetRegularTextBox()); 20 | } 21 | 22 | public bool EnableSyntaxColoring 23 | { 24 | get 25 | { 26 | return Controls.OfType().Any(c => c is FastColoredTextBox); 27 | } 28 | set 29 | { 30 | if (value && !EnableSyntaxColoring) 31 | { 32 | string current = Text; 33 | Controls.Clear(); 34 | Controls.Add(GetFastColoredTextBox()); 35 | Text = current; 36 | } 37 | if (!value && EnableSyntaxColoring) 38 | { 39 | string current = Text; 40 | Controls.Clear(); 41 | Controls.Add(GetRegularTextBox()); 42 | Text = current; 43 | } 44 | } 45 | } 46 | 47 | public override string Text 48 | { 49 | get 50 | { 51 | return Controls.OfType().Select(c => c.Text).FirstOrDefault(); 52 | } 53 | set 54 | { 55 | Control ctrl = Controls.OfType().FirstOrDefault(); 56 | if (ctrl != null) 57 | ctrl.Text = value; 58 | } 59 | } 60 | 61 | private FastColoredTextBox GetFastColoredTextBox() 62 | { 63 | FastColoredTextBox fctb = new FastColoredTextBox(); 64 | fctb.Dock = DockStyle.Fill; 65 | fctb.Location = new Point(0, 0); 66 | fctb.Margin = new Padding(2); 67 | fctb.Name = "FastColoredTextBox"; 68 | fctb.Multiline = true; 69 | fctb.ReadOnly = true; 70 | fctb.Size = new Size(761, 458); 71 | fctb.TabIndex = 0; 72 | fctb.WordWrap = false; 73 | //fctb.Language = Language.HTML; 74 | fctb.DescriptionFile = "xmlDesc.xml"; 75 | fctb.SyntaxHighlighter = new SyntaxHighlighter(); 76 | //fctb.Font = Control.DefaultFont; 77 | fctb.Font = new Font("Consolas", 9.0f); 78 | fctb.DefaultStyle = new TextStyle(Brushes.Black, null, FontStyle.Bold); 79 | fctb.CaretVisible = false; 80 | fctb.AutoIndent = false; 81 | fctb.AutoIndentExistingLines = false; 82 | return fctb; 83 | } 84 | 85 | private TextBox GetRegularTextBox() 86 | { 87 | TextBox tb = new TextBox(); 88 | tb.Dock = DockStyle.Fill; 89 | tb.Location = new Point(0, 0); 90 | tb.Margin = new Padding(2); 91 | tb.Name = "TextBox"; 92 | tb.Multiline = true; 93 | tb.ReadOnly = true; 94 | tb.Size = new Size(761, 458); 95 | tb.TabIndex = 0; 96 | tb.WordWrap = false; 97 | tb.ScrollBars = ScrollBars.Both; 98 | return tb; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /SvclogViewer/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /SvclogViewer/appicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martijns/SvclogViewer/5a2690551778de71a7360560959e36daefc10b90/SvclogViewer/appicon.ico -------------------------------------------------------------------------------- /SvclogViewer/changes.txt: -------------------------------------------------------------------------------- 1 | 2016-09-29: 2 | - CHG: Updated app with new code signing cert 3 | 4 | 2016-08-24: 5 | - CHG: Target changed to AnyCPU and not preferring 32-bit. Should fix out of memory issues. 6 | 7 | 2016-05-20: 8 | - NEW: Added ability to submit feedback (see menu) 9 | - CHG: Updated common library 10 | 11 | 2016-01-20: 12 | - NEW: Resize the left/right panel 13 | - NEW: Auto UrlDecode (with last selection saved in config) 14 | - NEW: Auto HtmlDecode (with last selection saved in config) 15 | 16 | 2015-10-08: 17 | - CHG: Moved clickonce-specific code to a reusable library. 18 | - NEW: Svclog Analyzer via Extra menu. Parses .svclog and creates a .csv with a list of calls and how long they took. 19 | 20 | 2015-02-11: 21 | - NEW: Support for xxxBASE64DATAxxx type of messages 22 | 23 | 2014-02-19: 24 | - NEW: Virtual mode is used for the gridview, increasing performance a lot 25 | 26 | 2014-02-13: 27 | - NEW: New crash dialog with the ability to upload a report to the developer. 28 | 29 | 2014-01-24: 30 | - NEW: Randomly color related messages based on their ActivityID 31 | 32 | 2013-11-10: 33 | - FIX: Update mechanism. Automatically downloads the update now and applies it on the next start. Still provides the user with a choice to restart now or later. 34 | - NEW: Ability to view changelog within the application. 35 | 36 | 2013-11-07 37 | - FIX: File association in Explorer wasn't always fixed 38 | 39 | 2013-11-06 40 | - NEW: Added a checkbox to enable syntax coloring, which replaces the textbox with the FastColoredTextBox by Pavel Torgashov (https://github.com/PavelTorgashov/FastColoredTextBox) 41 | - DEL: Button to format once has been removed, user feedback indicated it was never used. 42 | 43 | 2013-03-14 44 | - NEW: Keep currently selected message when filtering, clearing the filter or reloading the file 45 | - NEW: Scroll to selected message on reload/filter/clear when not displayed 46 | 47 | 2013-01-17 48 | - NEW: Persisted configuration (only 'format xml' checkbox for now) 49 | - NEW: Parse and select displayed message source 50 | - NEW: Show currently loaded file in title and status 51 | 52 | 2012-12-19 v0.2 53 | - FIX: Crash when multiple instances were opened 54 | - FIX: Allow files to be modified while reading 55 | - NEW: Button to reload files 56 | - NEW: Copy to clipboard 57 | - NEW: Filter requests on a string literal (case-sensitive) 58 | 59 | 2012-12-03 v0.1 60 | - NEW: Fast indexing 61 | - NEW: Show indexing progress 62 | - NEW: Copy to clipboard 63 | - NEW: Extract soapenv 64 | - NEW: Format XML 65 | -------------------------------------------------------------------------------- /SvclogViewer/htmlDesc.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |