├── .gitignore
├── README.md
├── license.md
└── src
├── Log2Window.sln
├── Log2Window
├── AboutForm.Designer.cs
├── AboutForm.cs
├── AboutForm.resx
├── App.config
├── Config
│ └── log4net.config
├── ICSharpCodeExtension
│ └── Actions
│ │ └── CaretActionsExtension.cs
├── Linq
│ └── Linq.cs
├── Log
│ ├── ILogManager.cs
│ ├── ILogMessageNotifiable.cs
│ ├── ILoggerView.cs
│ ├── LogLevel.cs
│ ├── LogLevelInfo.cs
│ ├── LogLevels.cs
│ ├── LogManager.cs
│ ├── LogMessage.cs
│ ├── LogMessageField.cs
│ ├── LogMessageItem.cs
│ ├── LogUtils.cs
│ └── LoggerItem.cs
├── Log2Window.csproj
├── MainForm.Designer.cs
├── MainForm.cs
├── MainForm.resx
├── MyCategoryList.cs
├── MyList.cs
├── NListsMerger.cs
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ ├── Settings.settings
│ └── app.manifest
├── Receiver
│ ├── BaseReceiver.cs
│ ├── CsvFileReceiver.cs
│ ├── DebugMonitor.cs
│ ├── EventLogReceiver.cs
│ ├── FileReceiver.cs
│ ├── IReceiver.cs
│ ├── MsmqReceiver.cs
│ ├── ReceiverFactory.cs
│ ├── ReceiverUtils.cs
│ ├── RemotingReceiver.cs
│ ├── SLPolicyServerReceiver.cs
│ ├── TcpReceiver.cs
│ ├── UdpReceiver.cs
│ └── WinDebugReceiver.cs
├── Settings
│ ├── FieldType.cs
│ ├── LayoutSettings.cs
│ ├── ReceiversForm.Designer.cs
│ ├── ReceiversForm.cs
│ ├── ReceiversForm.resx
│ ├── SettingsForm.Designer.cs
│ ├── SettingsForm.cs
│ ├── SettingsForm.resx
│ ├── SourceFileLocation.cs
│ └── UserSettings.cs
├── UI
│ ├── AutoWaitCursor.cs
│ ├── ControlExtenders
│ │ ├── DockExtender.cs
│ │ ├── Floaty.cs
│ │ └── Overlay.cs
│ ├── FlickerFreeListView.cs
│ ├── ToolStripControl.cs
│ ├── TreeViewLoggerView.cs
│ ├── TreeViewWithoutDoubleClick.cs
│ └── WindowRestorer.cs
├── Utils.cs
└── res
│ ├── Excel.ico
│ ├── Go16.png
│ ├── Pause16.png
│ ├── back16.png
│ ├── backward16.png
│ ├── burn16.png
│ ├── cd16.png
│ ├── close16.png
│ ├── collapse_all.png
│ ├── configure16.png
│ ├── delete16.png
│ ├── deletefile16.png
│ ├── documentsorcopy16.png
│ ├── eventLog.png
│ ├── find16.png
│ ├── forward16.png
│ ├── gotoapp16.png
│ ├── infoabout16.png
│ ├── movefile16.png
│ ├── next16.png
│ ├── pin.png
│ ├── receive.png
│ ├── saveas16.png
│ ├── unselect.png
│ ├── window16.png
│ ├── windowb.ico
│ ├── zoomin16.png
│ └── zoomout16.png
├── TestLog4net
├── App.config
├── Config
│ └── log4net.config
├── MsmqAppender.cs
├── MyXmlLayoutSchemaLog4j.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── TcpAppender.cs
└── TestLog4net.csproj
├── TestNLog
├── NLog.config
├── Program.cs
├── TestNLog.csproj
└── app.config
└── script_Publish.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | [Bb]in/
2 | [Oo]bj/
3 | [Ww]orking*/
4 | Build/runbuild.txt
5 | Doc/doc.shfbproj_*
6 | TestResults/
7 | AppPackages/
8 | *.suo
9 | *.user
10 | *.userprefs
11 | _ReSharper.*
12 | *.ReSharper.user
13 | *.resharper.user
14 | project.lock.json
15 | *.xproj
16 | .vs/
17 | *.props
18 | *.targets
19 |
20 | #NuGet
21 | packages
22 | !packages/repositories.config
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Log2Window
2 | Log2Window is a log message viewer for log4net, nlog, eventLog, log4j and log4cxx, which has strongly extreme stability and very good performance. It can process millions of log messages less than a second.
3 |
--------------------------------------------------------------------------------
/license.md:
--------------------------------------------------------------------------------
1 | BSD Copyright (c) 2007
2 | Copyright Rémy Baudet,
3 | Copyright Alanthinker,
4 | All rights reserved
5 |
6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9 |
10 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
11 |
12 | Neither the name of Log2Window nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15 |
--------------------------------------------------------------------------------
/src/Log2Window.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestNLog", "TestNLog\TestNLog.csproj", "{7C4E8E11-81E3-4297-A4D9-6F6DB90C8EF7}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Log2Window", "Log2Window\Log2Window.csproj", "{EE81C506-55E4-417E-B1D6-09453F89C7CD}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestLog4net", "TestLog4net\TestLog4net.csproj", "{29A745D4-5A2F-4170-A0F1-54C77F151892}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | CodeAnalysisDebug|Any CPU = CodeAnalysisDebug|Any CPU
15 | Debug|Any CPU = Debug|Any CPU
16 | Release|Any CPU = Release|Any CPU
17 | EndGlobalSection
18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
19 | {7C4E8E11-81E3-4297-A4D9-6F6DB90C8EF7}.CodeAnalysisDebug|Any CPU.ActiveCfg = Debug|Any CPU
20 | {7C4E8E11-81E3-4297-A4D9-6F6DB90C8EF7}.CodeAnalysisDebug|Any CPU.Build.0 = Debug|Any CPU
21 | {7C4E8E11-81E3-4297-A4D9-6F6DB90C8EF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
22 | {7C4E8E11-81E3-4297-A4D9-6F6DB90C8EF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {EE81C506-55E4-417E-B1D6-09453F89C7CD}.CodeAnalysisDebug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {EE81C506-55E4-417E-B1D6-09453F89C7CD}.CodeAnalysisDebug|Any CPU.Build.0 = Debug|Any CPU
25 | {EE81C506-55E4-417E-B1D6-09453F89C7CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26 | {EE81C506-55E4-417E-B1D6-09453F89C7CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
27 | {EE81C506-55E4-417E-B1D6-09453F89C7CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
28 | {EE81C506-55E4-417E-B1D6-09453F89C7CD}.Release|Any CPU.Build.0 = Release|Any CPU
29 | {29A745D4-5A2F-4170-A0F1-54C77F151892}.CodeAnalysisDebug|Any CPU.ActiveCfg = Debug|Any CPU
30 | {29A745D4-5A2F-4170-A0F1-54C77F151892}.CodeAnalysisDebug|Any CPU.Build.0 = Debug|Any CPU
31 | {29A745D4-5A2F-4170-A0F1-54C77F151892}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
32 | {29A745D4-5A2F-4170-A0F1-54C77F151892}.Debug|Any CPU.Build.0 = Debug|Any CPU
33 | {29A745D4-5A2F-4170-A0F1-54C77F151892}.Release|Any CPU.ActiveCfg = Release|Any CPU
34 | {29A745D4-5A2F-4170-A0F1-54C77F151892}.Release|Any CPU.Build.0 = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(SolutionProperties) = preSolution
37 | HideSolutionNode = FALSE
38 | EndGlobalSection
39 | EndGlobal
40 |
--------------------------------------------------------------------------------
/src/Log2Window/AboutForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Log2Window
2 | {
3 | partial class AboutForm
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 | protected override void Dispose(bool disposing)
14 | {
15 | if (disposing && (components != null))
16 | {
17 | components.Dispose();
18 | }
19 | base.Dispose(disposing);
20 | }
21 |
22 | #region Windows Form Designer generated code
23 |
24 | ///
25 | /// Required method for Designer support - do not modify
26 | /// the contents of this method with the code editor.
27 | ///
28 | private void InitializeComponent()
29 | {
30 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutForm));
31 | this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
32 | this.logoPictureBox = new System.Windows.Forms.PictureBox();
33 | this.flowLayoutPanel3 = new System.Windows.Forms.FlowLayoutPanel();
34 | this.labelProductName = new System.Windows.Forms.Label();
35 | this.labelVersion = new System.Windows.Forms.Label();
36 | this.labelCompileTime = new System.Windows.Forms.Label();
37 | this.labelLink = new System.Windows.Forms.LinkLabel();
38 | this.textBoxDescription = new System.Windows.Forms.TextBox();
39 | this.okButton = new System.Windows.Forms.Button();
40 | this.labelEmail = new System.Windows.Forms.Label();
41 | this.flowLayoutPanel1.SuspendLayout();
42 | ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit();
43 | this.flowLayoutPanel3.SuspendLayout();
44 | this.SuspendLayout();
45 | //
46 | // flowLayoutPanel1
47 | //
48 | this.flowLayoutPanel1.Controls.Add(this.logoPictureBox);
49 | this.flowLayoutPanel1.Controls.Add(this.flowLayoutPanel3);
50 | this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
51 | this.flowLayoutPanel1.Location = new System.Drawing.Point(9, 9);
52 | this.flowLayoutPanel1.Name = "flowLayoutPanel1";
53 | this.flowLayoutPanel1.Size = new System.Drawing.Size(475, 448);
54 | this.flowLayoutPanel1.TabIndex = 1;
55 | //
56 | // logoPictureBox
57 | //
58 | this.logoPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("logoPictureBox.Image")));
59 | this.logoPictureBox.Location = new System.Drawing.Point(3, 3);
60 | this.logoPictureBox.Name = "logoPictureBox";
61 | this.logoPictureBox.Size = new System.Drawing.Size(125, 271);
62 | this.logoPictureBox.TabIndex = 14;
63 | this.logoPictureBox.TabStop = false;
64 | //
65 | // flowLayoutPanel3
66 | //
67 | this.flowLayoutPanel3.Controls.Add(this.labelProductName);
68 | this.flowLayoutPanel3.Controls.Add(this.labelVersion);
69 | this.flowLayoutPanel3.Controls.Add(this.labelCompileTime);
70 | this.flowLayoutPanel3.Controls.Add(this.labelEmail);
71 | this.flowLayoutPanel3.Controls.Add(this.labelLink);
72 | this.flowLayoutPanel3.Controls.Add(this.textBoxDescription);
73 | this.flowLayoutPanel3.Controls.Add(this.okButton);
74 | this.flowLayoutPanel3.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
75 | this.flowLayoutPanel3.Location = new System.Drawing.Point(134, 3);
76 | this.flowLayoutPanel3.Name = "flowLayoutPanel3";
77 | this.flowLayoutPanel3.Size = new System.Drawing.Size(334, 442);
78 | this.flowLayoutPanel3.TabIndex = 1;
79 | //
80 | // labelProductName
81 | //
82 | this.labelProductName.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
83 | this.labelProductName.ForeColor = System.Drawing.SystemColors.HotTrack;
84 | this.labelProductName.Location = new System.Drawing.Point(5, 5);
85 | this.labelProductName.Margin = new System.Windows.Forms.Padding(5);
86 | this.labelProductName.Name = "labelProductName";
87 | this.labelProductName.Size = new System.Drawing.Size(200, 30);
88 | this.labelProductName.TabIndex = 25;
89 | this.labelProductName.Text = "Product Name";
90 | this.labelProductName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
91 | //
92 | // labelVersion
93 | //
94 | this.labelVersion.AutoSize = true;
95 | this.labelVersion.Location = new System.Drawing.Point(5, 45);
96 | this.labelVersion.Margin = new System.Windows.Forms.Padding(5);
97 | this.labelVersion.MaximumSize = new System.Drawing.Size(0, 17);
98 | this.labelVersion.Name = "labelVersion";
99 | this.labelVersion.Size = new System.Drawing.Size(42, 13);
100 | this.labelVersion.TabIndex = 24;
101 | this.labelVersion.Text = "Version";
102 | this.labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
103 | //
104 | // labelCompileTime
105 | //
106 | this.labelCompileTime.AutoSize = true;
107 | this.labelCompileTime.Location = new System.Drawing.Point(5, 68);
108 | this.labelCompileTime.Margin = new System.Windows.Forms.Padding(5);
109 | this.labelCompileTime.MaximumSize = new System.Drawing.Size(0, 17);
110 | this.labelCompileTime.Name = "labelCompileTime";
111 | this.labelCompileTime.Size = new System.Drawing.Size(89, 13);
112 | this.labelCompileTime.TabIndex = 31;
113 | this.labelCompileTime.Text = "labelCompileTime";
114 | this.labelCompileTime.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
115 | //
116 | // labelLink
117 | //
118 | this.labelLink.AutoSize = true;
119 | this.labelLink.Location = new System.Drawing.Point(5, 114);
120 | this.labelLink.Margin = new System.Windows.Forms.Padding(5);
121 | this.labelLink.MaximumSize = new System.Drawing.Size(0, 17);
122 | this.labelLink.Name = "labelLink";
123 | this.labelLink.Size = new System.Drawing.Size(220, 13);
124 | this.labelLink.TabIndex = 28;
125 | this.labelLink.TabStop = true;
126 | this.labelLink.Text = "https://github.com/alanthinker/Log2Window";
127 | this.labelLink.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
128 | this.labelLink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.labelLink_LinkClicked);
129 | //
130 | // textBoxDescription
131 | //
132 | this.textBoxDescription.AcceptsReturn = true;
133 | this.textBoxDescription.Location = new System.Drawing.Point(5, 137);
134 | this.textBoxDescription.Margin = new System.Windows.Forms.Padding(5);
135 | this.textBoxDescription.Multiline = true;
136 | this.textBoxDescription.Name = "textBoxDescription";
137 | this.textBoxDescription.ReadOnly = true;
138 | this.textBoxDescription.ScrollBars = System.Windows.Forms.ScrollBars.Both;
139 | this.textBoxDescription.Size = new System.Drawing.Size(318, 237);
140 | this.textBoxDescription.TabIndex = 29;
141 | this.textBoxDescription.TabStop = false;
142 | this.textBoxDescription.Text = "Description";
143 | //
144 | // okButton
145 | //
146 | this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
147 | this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
148 | this.okButton.Location = new System.Drawing.Point(243, 389);
149 | this.okButton.Margin = new System.Windows.Forms.Padding(10);
150 | this.okButton.Name = "okButton";
151 | this.okButton.Size = new System.Drawing.Size(75, 20);
152 | this.okButton.TabIndex = 30;
153 | this.okButton.Text = "&OK";
154 | //
155 | // labelEmail
156 | //
157 | this.labelEmail.AutoSize = true;
158 | this.labelEmail.Location = new System.Drawing.Point(5, 91);
159 | this.labelEmail.Margin = new System.Windows.Forms.Padding(5);
160 | this.labelEmail.MaximumSize = new System.Drawing.Size(0, 17);
161 | this.labelEmail.Name = "labelEmail";
162 | this.labelEmail.Size = new System.Drawing.Size(111, 13);
163 | this.labelEmail.TabIndex = 32;
164 | this.labelEmail.Text = "alanthinker@126.com";
165 | this.labelEmail.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
166 | //
167 | // AboutForm
168 | //
169 | this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
170 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
171 | this.ClientSize = new System.Drawing.Size(493, 466);
172 | this.Controls.Add(this.flowLayoutPanel1);
173 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
174 | this.MaximizeBox = false;
175 | this.MinimizeBox = false;
176 | this.Name = "AboutForm";
177 | this.Padding = new System.Windows.Forms.Padding(9);
178 | this.ShowIcon = false;
179 | this.ShowInTaskbar = false;
180 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
181 | this.Text = "About Log2Window";
182 | this.flowLayoutPanel1.ResumeLayout(false);
183 | ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit();
184 | this.flowLayoutPanel3.ResumeLayout(false);
185 | this.flowLayoutPanel3.PerformLayout();
186 | this.ResumeLayout(false);
187 |
188 | }
189 |
190 | #endregion
191 |
192 | private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
193 | private System.Windows.Forms.PictureBox logoPictureBox;
194 | private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel3;
195 | private System.Windows.Forms.Label labelProductName;
196 | private System.Windows.Forms.Label labelVersion;
197 | private System.Windows.Forms.LinkLabel labelLink;
198 | private System.Windows.Forms.TextBox textBoxDescription;
199 | private System.Windows.Forms.Button okButton;
200 | private System.Windows.Forms.Label labelCompileTime;
201 | private System.Windows.Forms.Label labelEmail;
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/src/Log2Window/AboutForm.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/AboutForm.cs
--------------------------------------------------------------------------------
/src/Log2Window/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Log2Window/Config/log4net.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
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 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/src/Log2Window/ICSharpCodeExtension/Actions/CaretActionsExtension.cs:
--------------------------------------------------------------------------------
1 | using ICSharpCode.TextEditor;
2 | using ICSharpCode.TextEditor.Actions;
3 |
4 | namespace Log2Window.ICSharpCodeExtension.Actions
5 | {
6 | public class GotoLineNumber : AbstractEditAction
7 | {
8 | private readonly int _line;
9 |
10 | public GotoLineNumber(int line)
11 | {
12 | _line = line;
13 | }
14 |
15 | public override void Execute(TextArea textArea)
16 | {
17 | TextLocation position = textArea.Caret.Position;
18 | position.Line = _line;
19 |
20 | textArea.Caret.Position = position;
21 | textArea.SelectionManager.ClearSelection();
22 | textArea.SetDesiredColumn();
23 |
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Log2Window/Linq/Linq.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | #if !HASLINQ
4 |
5 | namespace System.Linq
6 | {
7 | ///
8 | /// This class replaces standars LINQ to Objects libraries (to be able to run on vanilla .NET 2.0 Framework)
9 | /// Methods are added on need-to-use basis
10 | ///
11 | internal static class Enumerable
12 | {
13 | public static IEnumerable Select(this IEnumerable source, Func selector)
14 | {
15 | if (source == null)
16 | throw new ArgumentNullException("source");
17 |
18 | if (selector == null)
19 | throw new ArgumentNullException("selector");
20 |
21 | foreach (var i in source)
22 | yield return selector(i);
23 | }
24 |
25 | public static int Min(this IEnumerable source)
26 | {
27 | if (source == null)
28 | throw new ArgumentNullException("source");
29 |
30 | var min = 0;
31 | var hasElements = false;
32 |
33 | foreach (var i in source)
34 | {
35 | if (hasElements)
36 | {
37 | if (i < min)
38 | min = i;
39 | }
40 | else
41 | {
42 | min = i;
43 | hasElements = true;
44 | }
45 | }
46 |
47 | if (!hasElements)
48 | throw new ArgumentException("source");
49 |
50 | return min;
51 | }
52 |
53 | public static int Max(this IEnumerable source)
54 | {
55 | if (source == null)
56 | throw new ArgumentNullException("source");
57 |
58 | var max = 0;
59 | var hasElements = false;
60 |
61 | foreach (var i in source)
62 | {
63 | if (hasElements)
64 | {
65 | if (i > max)
66 | max = i;
67 | }
68 | else
69 | {
70 | max = i;
71 | hasElements = true;
72 | }
73 | }
74 |
75 | if (!hasElements)
76 | throw new ArgumentException("source");
77 |
78 | return max;
79 | }
80 |
81 | public static int Min(this IEnumerable source, Func extractor)
82 | {
83 | return source.Select(extractor).Min();
84 | }
85 |
86 | public static int Max(this IEnumerable source, Func extractor)
87 | {
88 | return source.Select(extractor).Max();
89 | }
90 | }
91 | }
92 |
93 | namespace System
94 | {
95 | public delegate TResult Func(TParam param);
96 | }
97 |
98 | namespace System.Runtime.CompilerServices
99 | {
100 | public class ExtensionAttribute : Attribute { }
101 | }
102 |
103 | #endif
104 |
--------------------------------------------------------------------------------
/src/Log2Window/Log/ILogManager.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Windows.Forms;
3 |
4 |
5 | namespace Log2Window.Log
6 | {
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/src/Log2Window/Log/ILogMessageNotifiable.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Log2Window.Log
3 | {
4 | ///
5 | /// This interface must be implemented to be notified when new log message arrives.
6 | ///
7 | public interface ILogMessageNotifiable
8 | {
9 | ///
10 | /// Call this method when a new log message is arrived.
11 | ///
12 | /// The message to log.
13 | void Notify(LogMessage logMsg);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Log2Window/Log/ILoggerView.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Drawing;
5 |
6 | namespace Log2Window.Log
7 | {
8 | ///
9 | /// Defines methods for allowing a LoggerItem to be shown in the UI.
10 | ///
11 | public interface ILoggerView
12 | {
13 | ///
14 | /// Clears this view and all child views.
15 | ///
16 | void Clear();
17 |
18 | ///
19 | /// Adds the new logger view as a child of the current view and returns the new view.
20 | ///
21 | /// The text to initialize the view with.
22 | /// The logger that this instance is a view of.
23 | ///
24 | ILoggerView AddNew(string text, LoggerItem logger);
25 |
26 | ///
27 | /// Removes the logger view associated to the given text.
28 | ///
29 | void Remove(string text);
30 |
31 | void Sync();
32 |
33 |
34 | ///
35 | /// Gets or sets the text of the view. The text is what is shown to the user.
36 | ///
37 | /// The text.
38 | string Text { get; set; }
39 |
40 | ///
41 | /// Gets or sets a value indicating whether this is enabled.
42 | ///
43 | /// true if enabled; otherwise, false.
44 | bool Enabled { get; set; }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Log2Window/Log/LogLevel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Log2Window.Log
4 | {
5 | [Serializable]
6 | public enum LogLevel
7 | {
8 | None = -1,
9 | Trace = 0,
10 | Debug = 1,
11 | Info = 2,
12 | Warn = 3,
13 | Error = 4,
14 | Fatal = 5,
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Log2Window/Log/LogLevelInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 |
4 | namespace Log2Window.Log
5 | {
6 | [Serializable]
7 | public class LogLevelInfo
8 | {
9 | public LogLevel Level;
10 | public string Name;
11 | public Color Color;
12 | public int Value;
13 | public int RangeMin;
14 | public int RangeMax;
15 |
16 |
17 | public LogLevelInfo(LogLevel level, Color color)
18 | {
19 | Level = level;
20 | Name = level.ToString();
21 | Color = color;
22 | RangeMax = RangeMin = 0;
23 | }
24 |
25 | public LogLevelInfo(LogLevel level, string name, Color color, int value, int rangeMin, int rangeMax)
26 | {
27 | Level = level;
28 | Name = name;
29 | Color = color;
30 | Value = value;
31 | RangeMin = rangeMin;
32 | RangeMax = rangeMax;
33 | }
34 |
35 | public override bool Equals(object obj)
36 | {
37 | if (obj is LogLevelInfo)
38 | return ((obj as LogLevelInfo) == this);
39 | return base.Equals(obj);
40 | }
41 |
42 | public override int GetHashCode()
43 | {
44 | return Value.GetHashCode();
45 | }
46 |
47 | public static bool operator ==(LogLevelInfo first, LogLevelInfo second)
48 | {
49 | if (((object)first == null) || ((object)second == null))
50 | return (((object)first == null) && ((object)second == null));
51 | return (first.Value == second.Value);
52 | }
53 |
54 | public static bool operator !=(LogLevelInfo first, LogLevelInfo second)
55 | {
56 | if (((object)first == null) || ((object)second == null))
57 | return !(((object)first == null) && ((object)second == null));
58 | return first.Value != second.Value;
59 | }
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/Log2Window/Log/LogLevels.cs:
--------------------------------------------------------------------------------
1 | using Log2Window.Settings;
2 | using System;
3 | using System.Drawing;
4 |
5 | namespace Log2Window.Log
6 | {
7 | public sealed class LogLevels
8 | {
9 | private static LogLevels _instance;
10 |
11 | public readonly LogLevelInfo InvalidLogLevel;
12 | public readonly LogLevelInfo[] LogLevelInfos;
13 |
14 | internal static LogLevels Instance
15 | {
16 | get
17 | {
18 | if (_instance == null)
19 | _instance = new LogLevels();
20 | return _instance;
21 | }
22 | }
23 |
24 | internal LogLevelInfo this[int level]
25 | {
26 | get
27 | {
28 | if ((level < (int)LogLevel.Trace) || (level > (int)LogLevel.Fatal))
29 | return InvalidLogLevel;
30 | return LogLevelInfos[level];
31 | }
32 | }
33 |
34 | internal LogLevelInfo this[LogLevel logLevel]
35 | {
36 | get
37 | {
38 | int level = (int)logLevel;
39 | if ((level < (int)LogLevel.Trace) || (level > (int)LogLevel.Fatal))
40 | return InvalidLogLevel;
41 | return LogLevelInfos[level];
42 | }
43 | }
44 |
45 | internal LogLevelInfo this[string level]
46 | {
47 | get
48 | {
49 | foreach (LogLevelInfo info in LogLevelInfos)
50 | {
51 | if (info.Name.Equals(level, StringComparison.InvariantCultureIgnoreCase))
52 | return info;
53 | }
54 | return InvalidLogLevel;
55 | }
56 | }
57 |
58 | private LogLevels()
59 | {
60 | InvalidLogLevel = new LogLevelInfo(LogLevel.None, Color.IndianRed);
61 |
62 | LogLevelInfos = new LogLevelInfo[]
63 | {
64 | new LogLevelInfo(LogLevel.Trace, "Trace", UserSettings.DefaultTraceLevelColor, 10000, 0, 10000),
65 | new LogLevelInfo(LogLevel.Debug, "Debug", UserSettings.DefaultDebugLevelColor, 30000, 10001, 30000),
66 | new LogLevelInfo(LogLevel.Info, "Info", UserSettings.DefaultInfoLevelColor, 40000, 30001, 40000),
67 | new LogLevelInfo(LogLevel.Warn, "Warn", UserSettings.DefaultWarnLevelColor, 60000, 40001, 60000),
68 | new LogLevelInfo(LogLevel.Error, "Error", UserSettings.DefaultErrorLevelColor, 70000, 60001, 70000),
69 | new LogLevelInfo(LogLevel.Fatal, "Fatal", UserSettings.DefaultFatalLevelColor, 110000, 70001, 110000),
70 | };
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Log2Window/Log/LogManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Windows.Forms;
5 |
6 |
7 | namespace Log2Window.Log
8 | {
9 | public class LogManager
10 | {
11 | private static LogManager _instance;
12 |
13 | //_allLogMessageItems and _dataSource must use this locker.
14 | public readonly object dataLocker = new object();
15 | //_allLogMessageItems may be reassigned, so cannot use as a locker.
16 | public MyCategoryList _allLogMessageItems = new MyCategoryList(new List { LogLevel.Fatal, LogLevel.Error, LogLevel.Warn, LogLevel.Info, LogLevel.Debug, LogLevel.Trace });
17 | public MyList _dataSource = new MyList();
18 |
19 | private LoggerItem _rootLoggerItem;
20 | private Dictionary _fullPathLoggers;
21 | public ListView _logListView;
22 | internal ulong manulSelectedArrivedId;
23 |
24 | public bool IsDelay { get; set; }
25 |
26 | private LogManager()
27 | {
28 |
29 | }
30 |
31 | internal static LogManager Instance
32 | {
33 | get
34 | {
35 | if (_instance == null)
36 | _instance = new LogManager();
37 | return _instance;
38 | }
39 | }
40 |
41 | internal LoggerItem RootLoggerItem
42 | {
43 | get { return _rootLoggerItem; }
44 | set { _rootLoggerItem = value; }
45 | }
46 |
47 | public bool PauseRefreshNewMessages { get; set; }
48 |
49 | public void Initialize(ILoggerView loggerView, ListView logListView)
50 | {
51 | _logListView = logListView;
52 | // Root Logger
53 | _rootLoggerItem = LoggerItem.CreateRootLoggerItem("Root", loggerView, logListView);
54 |
55 | // Quick Access Logger Collection
56 | _fullPathLoggers = new Dictionary();
57 | }
58 |
59 | public void ClearAll()
60 | {
61 | ClearLogMessages();
62 | RootLoggerItem.ClearAll();
63 | _fullPathLoggers.Clear();
64 | }
65 |
66 | public void ClearLogMessages()
67 | {
68 | lock (dataLocker)
69 | {
70 | _allLogMessageItems.Clear();
71 | _dataSource.Clear();
72 | MainForm.Instance.ReBindListViewFromAllLogMessageItems();
73 |
74 | GC.Collect();
75 | }
76 | }
77 |
78 | public void DeactivateLogger()
79 | {
80 | RootLoggerItem.Enabled = false;
81 | }
82 |
83 | public void ProcessLogMessage(LogMessage logMsg)
84 | {
85 | // Check 1st in the global LoggerPath/Logger dictionary
86 | LoggerItem logger;
87 | logMsg.CheckNull();
88 |
89 | // Search by thread need compare ThreadName. So need trim.
90 | logMsg.ThreadName = logMsg.ThreadName?.Trim();
91 |
92 | if (!_fullPathLoggers.TryGetValue(logMsg.LoggerName, out logger))
93 | {
94 | // Not found, create one
95 | logger = RootLoggerItem.GetOrCreateLogger(logMsg.LoggerName);
96 | }
97 | if (logger == null)
98 | throw new Exception("No Logger for this Log Message.");
99 |
100 | var item = logger.AddLogMessage(logMsg);
101 |
102 | lock (LogManager.Instance.dataLocker)
103 | {
104 | _allLogMessageItems.Enqueue(item, item.Message.Level.Level);
105 | if (item.Enabled && !LogManager.Instance.PauseRefreshNewMessages)
106 | {
107 | _dataSource.Enqueue(item);
108 | }
109 |
110 | // 只在 TryEnsureVisibleForSuitableItems 函数中调用 DequeueMoreThanMaxCount, 防止新增消息的时候, 影响listview的index指向的实际行.
111 | //DequeueMoreThanMaxCount();
112 | }
113 |
114 | }
115 |
116 | public long DequeueMoreThanMaxCount()
117 | {
118 | long removedCount=0;
119 | var maxCount = Settings.UserSettings.Instance.MessageCycleCountForEachLevel;
120 | if (maxCount > 0)
121 | {
122 | removedCount = _allLogMessageItems.DequeueSmart(maxCount);
123 | if (removedCount > 0)
124 | {
125 | if (!LogManager.Instance.PauseRefreshNewMessages
126 | )
127 | {
128 | MainForm.Instance.ReBindListViewFromAllLogMessageItems(false);
129 | }
130 | }
131 | }
132 | GC.Collect();
133 | return removedCount;
134 | }
135 |
136 | public void allLogMessageItems_to_dataSource()
137 | {
138 | this._dataSource.Clear();
139 | var temp = new MyCategoryList(new List { LogLevel.Fatal, LogLevel.Error, LogLevel.Warn, LogLevel.Info, LogLevel.Debug, LogLevel.Trace });
140 | foreach (var item in this._allLogMessageItems)
141 | {
142 | item.Enabled = item.Parent.IsItemToBeEnabled(item);
143 | if (item.Enabled)
144 | {
145 | temp.Enqueue(item, item.Message.Level.Level);
146 | }
147 | }
148 |
149 |
150 | var listList = temp.ToListList();
151 | var t0 = DateTime.Now;
152 | this._dataSource = new NListsMerger().MergeNLists(listList);
153 | var t1 = DateTime.Now;
154 | Trace.WriteLine("ts=" + (t1 - t0));
155 | }
156 |
157 | public void SearchByTextAndThread(string text,string thread)
158 | {
159 | _rootLoggerItem.SearchByTextAndThread(text, thread);
160 | }
161 |
162 |
163 | public void UpdateLogLevel()
164 | {
165 | if (RootLoggerItem == null)
166 | return;
167 |
168 | RootLoggerItem.UpdateLogLevel();
169 | }
170 |
171 | public void SetRootLoggerName(string name)
172 | {
173 | RootLoggerItem.Name = name;
174 | }
175 |
176 | internal bool inSetSelectedIndicesByCode;
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/src/Log2Window/Log/LogMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows.Forms;
5 | using Log2Window.Settings;
6 | using System.Diagnostics;
7 |
8 | namespace Log2Window.Log
9 | {
10 | public class LogMessage
11 | {
12 | ///
13 | /// The Line Number of the Log Message
14 | ///
15 | public ulong SequenceNr;
16 |
17 | ///
18 | /// Logger Name.
19 | ///
20 | public string LoggerName;
21 |
22 | ///
23 | /// Root Logger Name.
24 | ///
25 | public string RootLoggerName;
26 |
27 | ///
28 | /// Log Level.
29 | ///
30 | public LogLevelInfo Level;
31 |
32 | ///
33 | /// Log Message.
34 | ///
35 | public string Message;
36 |
37 | ///
38 | /// Thread Name.
39 | ///
40 | public string ThreadName;
41 |
42 | ///
43 | /// Time Stamp.
44 | ///
45 | public DateTime TimeStamp;
46 |
47 | ///
48 | /// Properties collection.
49 | ///
50 | public Dictionary Properties = new Dictionary();
51 |
52 | ///
53 | /// An exception message to associate to this message.
54 | ///
55 | public string ExceptionString;
56 |
57 | ///
58 | /// The CallSite Class
59 | ///
60 | public string CallSiteClass;
61 |
62 |
63 | ///
64 | /// The CallSite Method in which the Log is made
65 | ///
66 | public string CallSiteMethod;
67 |
68 | ///
69 | /// The Name of the Source File
70 | ///
71 | public string SourceFileName;
72 |
73 | ///
74 | /// The Line of the Source File
75 | ///
76 | public uint? SourceFileLineNr;
77 |
78 | //Only allowed set ArrivedId in constructor.
79 | public readonly ulong ArrivedId;
80 |
81 | public LogMessage()
82 | {
83 | ArrivedId = IdCreator.GetNextId();
84 | }
85 |
86 | public void CheckNull()
87 | {
88 | if (string.IsNullOrEmpty(LoggerName))
89 | LoggerName = "Unknown";
90 | if (string.IsNullOrEmpty(RootLoggerName))
91 | RootLoggerName = "Unknown";
92 | if (string.IsNullOrEmpty(Message))
93 | Message = "Unknown";
94 | if (string.IsNullOrEmpty(ThreadName))
95 | ThreadName = string.Empty;
96 | if (string.IsNullOrEmpty(ExceptionString))
97 | ExceptionString = string.Empty;
98 | if (string.IsNullOrEmpty(ExceptionString))
99 | ExceptionString = string.Empty;
100 | if (string.IsNullOrEmpty(CallSiteClass))
101 | CallSiteClass = string.Empty;
102 | if (string.IsNullOrEmpty(CallSiteMethod))
103 | CallSiteMethod = string.Empty;
104 | if (string.IsNullOrEmpty(SourceFileName))
105 | SourceFileName = string.Empty;
106 | if (Level == null)
107 | Level = LogLevels.Instance[(LogLevel.Error)];
108 | }
109 |
110 | public override string ToString()
111 | {
112 | var sb = new StringBuilder();
113 | foreach (var fieldType in UserSettings.Instance.ColumnConfiguration)
114 | {
115 | sb.Append(GetInformation(fieldType));
116 | sb.Append("\t");
117 | }
118 | return sb.ToString();
119 | }
120 |
121 | private string GetInformation(FieldType fieldType)
122 | {
123 | string result = string.Empty;
124 | switch (fieldType.Field)
125 | {
126 | case LogMessageField.SequenceNr:
127 | result = SequenceNr.ToString();
128 | break;
129 | case LogMessageField.ArrivedId:
130 | result = ArrivedId.ToString();
131 | break;
132 | case LogMessageField.LoggerName:
133 | result = LoggerName;
134 | break;
135 | case LogMessageField.RootLoggerName:
136 | result = RootLoggerName;
137 | break;
138 | case LogMessageField.Level:
139 | result = Level.Level.ToString();
140 | break;
141 | case LogMessageField.Message:
142 | result = Message;
143 | break;
144 | case LogMessageField.ThreadName:
145 | result = ThreadName;
146 | break;
147 | case LogMessageField.TimeStamp:
148 | result = TimeStamp.ToString(UserSettings.Instance.TimeStampFormatString);
149 | break;
150 | case LogMessageField.Exception:
151 | result = ExceptionString;
152 | break;
153 | case LogMessageField.CallSiteClass:
154 | result = CallSiteClass;
155 | break;
156 | case LogMessageField.CallSiteMethod:
157 | result = CallSiteMethod;
158 | break;
159 | case LogMessageField.SourceFileName:
160 | result = SourceFileName;
161 | break;
162 | case LogMessageField.SourceFileLineNr:
163 | result = SourceFileLineNr.ToString();
164 | break;
165 | case LogMessageField.Properties:
166 | {
167 | StringBuilder sb = new StringBuilder();
168 |
169 | foreach (var property in Properties)
170 | {
171 | sb.Append(property.Key + ": ");
172 | sb.AppendLine(property.Value);
173 | }
174 | result = sb.ToString();
175 | }
176 |
177 | break;
178 | }
179 | return result;
180 | }
181 |
182 | internal void GetMessageDetails(RichTextBox logDetailTextBox, RichTextBox tbMessage)
183 | {
184 | logDetailTextBox.Clear();
185 | foreach (var fieldType in UserSettings.Instance.MessageDetailConfiguration)
186 | {
187 | //var info = GetInformation(fieldType).Replace(@"\", @"\\").Replace("{", @"\{").Replace("}", @"\}");
188 | //sb.Append(@"\b " + fieldType.Field + @": \b0 ");
189 | //if (info.Length > 40)
190 | // sb.Append(@" \line ");
191 | //sb.Append(info + @" \line ");
192 |
193 | var info = GetInformation(fieldType);
194 |
195 | if (fieldType.Field == LogMessageField.Message)
196 | {
197 | //Utils.log.Debug(info);
198 | tbMessage.Text = info;
199 |
200 | if (!string.IsNullOrEmpty(this.ExceptionString))
201 | {
202 | tbMessage.Text += "\n\n" + this.ExceptionString;
203 | }
204 | }
205 | else
206 | {
207 | var oldColor = logDetailTextBox.SelectionColor;
208 | logDetailTextBox.SelectionColor = System.Drawing.Color.Brown;
209 | logDetailTextBox.SelectionFont = new System.Drawing.Font(logDetailTextBox.SelectionFont, System.Drawing.FontStyle.Bold);
210 | logDetailTextBox.AppendText(fieldType.Field + ": ");
211 | logDetailTextBox.SelectionFont = new System.Drawing.Font(logDetailTextBox.SelectionFont, System.Drawing.FontStyle.Regular);
212 | logDetailTextBox.SelectionColor = oldColor;
213 | if (info.Length > 40)
214 | logDetailTextBox.AppendText("\n");
215 | logDetailTextBox.AppendText(info + "\n");
216 | }
217 | }
218 | }
219 | }
220 | }
221 |
--------------------------------------------------------------------------------
/src/Log2Window/Log/LogMessageField.cs:
--------------------------------------------------------------------------------
1 | namespace Log2Window.Log
2 | {
3 | public enum LogMessageField
4 | {
5 | ArrivedId,
6 | SequenceNr,
7 | RootLoggerName,
8 | LoggerName,
9 | Level,
10 | Message,
11 | ThreadName,
12 | TimeStamp,
13 | Exception,
14 | CallSiteClass,
15 | CallSiteMethod,
16 | SourceFileName,
17 | SourceFileLineNr,
18 | Properties
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Log2Window/Log/LogMessageItem.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using Log2Window.Settings;
3 | using System;
4 | using System.Drawing;
5 | using System.Windows.Forms;
6 | using System.Collections;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 |
10 | namespace Log2Window.Log
11 | {
12 | public static class IdCreator
13 | {
14 | private static readonly object idLocker = new object();
15 |
16 | private static ulong id = 1;
17 | public static ulong GetNextId()
18 | {
19 | lock (idLocker)
20 | {
21 | return id++;
22 | }
23 | }
24 | }
25 |
26 | ///
27 | /// Describes a Log Message.
28 | /// TODO: Make it disposable to dereference Item?
29 | ///
30 | public class LogMessageItem : IComparable
31 | {
32 | ///
33 | /// Logger Item Parent.
34 | ///
35 | public LoggerItem Parent;
36 |
37 | /////
38 | ///// The item before this one, allow to retrieve the order of arrival (time is not reliable here).
39 | ///// The previous item is not necessary a sibling in the logger tree, only in the message list view.
40 | /////
41 | //public LogMessageItem Previous;
42 |
43 | // public long ArrivedId;
44 |
45 | /////
46 | ///// The associated List View Item.
47 | /////
48 | //public ListViewItem Item;
49 |
50 | ///
51 | /// Log Message.
52 | ///
53 | public LogMessage Message;
54 |
55 | ///
56 | /// Indicates if this Log Message Item is enable.
57 | /// When disabled the List View Item is not in the Log List View.
58 | ///
59 | public bool Enabled = true;
60 |
61 | public LogMessageItem(LoggerItem parent, LogMessage logMsg)
62 | {
63 | Parent = parent;
64 | Message = logMsg;
65 | }
66 |
67 | public static ListViewItem CreateListViewItem(LogMessage logMsg)
68 | {
69 | Utils.log.Debug("CreateListViewItem " + logMsg.ArrivedId);
70 | // Create List View Item
71 | var items = new ListViewItem.ListViewSubItem[UserSettings.Instance.ColumnConfiguration.Length];
72 | string toolTip = string.Empty;
73 |
74 | //Add all the Standard Fields to the ListViewItem
75 | for (int i = 0; i < UserSettings.Instance.ColumnConfiguration.Length; i++)
76 | {
77 | items[i] = new ListViewItem.ListViewSubItem();
78 |
79 | switch (UserSettings.Instance.ColumnConfiguration[i].Field)
80 | {
81 | case LogMessageField.SequenceNr:
82 | items[i].Text = logMsg.SequenceNr.ToString();
83 | break;
84 | case LogMessageField.ArrivedId:
85 | items[i].Text = logMsg.ArrivedId.ToString();
86 | break;
87 | case LogMessageField.LoggerName:
88 | items[i].Text = logMsg.LoggerName;
89 | break;
90 | case LogMessageField.RootLoggerName:
91 | items[i].Text = logMsg.RootLoggerName;
92 | break;
93 | case LogMessageField.Level:
94 | items[i].Text = logMsg.Level.Name;
95 | break;
96 | case LogMessageField.Message:
97 | StringBuilder sbMsg = new StringBuilder(logMsg.Message);
98 | if (!string.IsNullOrEmpty(logMsg.ExceptionString))
99 | {
100 | sbMsg.Append(" " + logMsg.ExceptionString);
101 | }
102 | sbMsg.Replace("\r\n", " ");
103 | sbMsg.Replace("\n", " ");
104 | var msg = sbMsg.ToString();
105 | items[i].Text = msg;
106 | toolTip = msg;
107 | break;
108 | case LogMessageField.ThreadName:
109 | items[i].Text = logMsg.ThreadName;
110 | break;
111 | case LogMessageField.TimeStamp:
112 | items[i].Text = logMsg.TimeStamp.ToString(UserSettings.Instance.TimeStampFormatString);
113 | break;
114 | case LogMessageField.Exception:
115 | string exception = logMsg.ExceptionString.Replace("\r\n", " ");
116 | exception = exception.Replace("\n", " ");
117 | items[i].Text = exception;
118 | break;
119 | case LogMessageField.CallSiteClass:
120 | items[i].Text = logMsg.CallSiteClass;
121 | break;
122 | case LogMessageField.CallSiteMethod:
123 | items[i].Text = logMsg.CallSiteMethod;
124 | break;
125 | case LogMessageField.SourceFileName:
126 | items[i].Text = logMsg.SourceFileName;
127 | break;
128 | case LogMessageField.SourceFileLineNr:
129 | items[i].Text = logMsg.SourceFileLineNr.ToString();
130 | break;
131 | case LogMessageField.Properties:
132 | break;
133 | }
134 | }
135 |
136 | //Add all the Properties in the Message to the ListViewItem
137 | foreach (var property in logMsg.Properties)
138 | {
139 | string propertyKey = property.Key;
140 | if (UserSettings.Instance.ColumnProperties.ContainsKey(propertyKey))
141 | {
142 | int propertyColumnNumber = UserSettings.Instance.ColumnProperties[propertyKey];
143 | if (propertyColumnNumber < items.Length)
144 | {
145 | items[propertyColumnNumber].Text = property.Value;
146 | }
147 | }
148 | }
149 |
150 | var Item = new ListViewItem(items, 0) { ToolTipText = toolTip, ForeColor = logMsg.Level.Color };//, Tag = this };
151 | return Item;
152 | }
153 |
154 | internal bool IsLevelInRange()
155 | {
156 | return (Message.Level.RangeMax >= UserSettings.Instance.LogLevelInfo.RangeMax);
157 | }
158 |
159 | //internal void HighlightSearchedText(bool hasText, string str)
160 | //{
161 | // if (hasText && HasSearchedText(str))
162 | // Item.BackColor = Color.LightYellow;
163 | // else
164 | // Item.BackColor = Color.Transparent;
165 | //}
166 |
167 | internal bool HasSearchedText(string str)
168 | {
169 | return (Message.Message.IndexOf(str, StringComparison.InvariantCultureIgnoreCase) >= 0);
170 | }
171 |
172 | internal bool IsThreadMatch(string[] threads)
173 | {
174 | return threads.Contains(Message.ThreadName);
175 | }
176 |
177 | internal void GetMessageDetails(RichTextBox logDetailTextBox, RichTextBox tbMessage)
178 | {
179 | Message.GetMessageDetails(logDetailTextBox, tbMessage);
180 | }
181 |
182 | public int CompareTo(LogMessageItem other)
183 | {
184 | return this.Message.ArrivedId.CompareTo(other.Message.ArrivedId);
185 | }
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/src/Log2Window/Log/LogUtils.cs:
--------------------------------------------------------------------------------
1 | namespace Log2Window.Log
2 | {
3 | public static class LogUtils
4 | {
5 | public static bool IsInRange(int val, int min, int max)
6 | {
7 | return (val >= min) && (val <= max);
8 | }
9 |
10 | public static LogLevelInfo GetLogLevelInfo(int level)
11 | {
12 | foreach (LogLevelInfo info in LogLevels.Instance.LogLevelInfos)
13 | {
14 | if (IsInRange(level, info.RangeMin, info.RangeMax))
15 | return info;
16 | }
17 |
18 | return LogLevels.Instance.InvalidLogLevel;
19 | }
20 |
21 | public static LogLevelInfo GetLogLevelInfo(LogLevel level)
22 | {
23 | foreach (LogLevelInfo info in LogLevels.Instance.LogLevelInfos)
24 | {
25 | if (level == info.Level)
26 | return info;
27 | }
28 |
29 | return LogLevels.Instance.InvalidLogLevel;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Log2Window/MainForm.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/MainForm.cs
--------------------------------------------------------------------------------
/src/Log2Window/MyCategoryList.cs:
--------------------------------------------------------------------------------
1 | using ICSharpCode.TextEditor.Actions;
2 | using Log2Window.Log;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace Log2Window
10 | {
11 | public class MyCategoryList
12 | {
13 | Dictionary> _categories = new Dictionary>();
14 |
15 | public MyCategoryList(List cats)
16 | {
17 | foreach (var cat in cats)
18 | {
19 | if (!_categories.ContainsKey(cat))
20 | {
21 | _categories.Add(cat, new MyList());
22 | }
23 | }
24 | }
25 |
26 | public long AllItemsCount
27 | {
28 | get
29 | {
30 | long count = 0;
31 | foreach (var pair in _categories)
32 | {
33 | count += pair.Value.Count;
34 | }
35 | return count;
36 | }
37 | }
38 |
39 | public void Enqueue(T item, CAT cat)
40 | {
41 | _categories[cat].Enqueue(item);
42 | }
43 |
44 | public void Clear()
45 | {
46 | foreach (var pair in _categories)
47 | {
48 | pair.Value.Clear();
49 | }
50 | }
51 |
52 | // 为了防止反复多次调用 DequeueSmart, 只要在每个cat的元素数量超过 110%的 catMaxItemsCount 的时候, 才执行 Dequeue,
53 | // 一旦执行, 最终元素数量被减小到 100% 以内.
54 | public long DequeueSmart(long catMaxItemsCount)
55 | {
56 | var max_110_percent = catMaxItemsCount * 1.1;
57 |
58 | long dequeuedCount = 0;
59 | foreach (var pair in _categories)
60 | {
61 | if (pair.Value.Count > max_110_percent)
62 | {
63 | while (pair.Value.Count > catMaxItemsCount)
64 | {
65 | pair.Value.Dequeue();
66 | dequeuedCount++;
67 | }
68 | }
69 | }
70 |
71 | return dequeuedCount;
72 | }
73 |
74 | public IEnumerator GetEnumerator()
75 | {
76 | foreach (var cat in _categories)
77 | {
78 | foreach (var item in cat.Value)
79 | {
80 | yield return item;
81 | }
82 | }
83 | }
84 |
85 | public List> ToListList()
86 | {
87 | List> list = new List>();
88 | foreach (var cat in _categories)
89 | {
90 | list.Add(cat.Value);
91 | }
92 | return list;
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/Log2Window/MyList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Log2Window
7 | {
8 | ///
9 | /// A collection which can support index, Enqueue, Dequeue, Peek, GetEnumerator with very good performance.
10 | /// Have both advantage of Queue and List.
11 | ///
12 | ///
13 | public class MyList
14 | {
15 | private List list = new List();
16 | private int startIndex = 0;
17 | private int endIndexAddOne = 0;//not include;
18 |
19 | private int resetCount = 1000;
20 | public long StateId { get; private set; }
21 |
22 | public T this[int index]
23 | {
24 | get
25 | {
26 | return list[index + startIndex];
27 | }
28 | }
29 |
30 | public int Count
31 | {
32 | get
33 | {
34 | return endIndexAddOne - startIndex;
35 | }
36 | }
37 |
38 | public void Enqueue(T item)
39 | {
40 | StateId++;
41 | list.Add(item);
42 | endIndexAddOne++;
43 |
44 | if (startIndex > resetCount && startIndex > endIndexAddOne / 2)
45 | {
46 | var newlist = new List(this.Count);
47 | foreach (var temp in this)
48 | {
49 | newlist.Add(temp);
50 | }
51 | list.Clear();
52 | list = newlist;
53 | startIndex = 0;
54 | endIndexAddOne = list.Count;
55 | }
56 | }
57 |
58 | public void Clear()
59 | {
60 | StateId++;
61 | list.Clear();
62 | endIndexAddOne = 0;
63 | startIndex = 0;
64 | }
65 |
66 | public IEnumerator GetEnumerator()
67 | {
68 | for (int i = startIndex; i < endIndexAddOne; i++)
69 | {
70 | yield return list[i];
71 | }
72 | }
73 |
74 | public T Peek()
75 | {
76 | return list[startIndex];
77 | }
78 |
79 | public T Dequeue()
80 | {
81 | StateId++;
82 | var item = this.Peek();
83 | startIndex++;
84 | return item;
85 | }
86 |
87 | public void Sort()
88 | {
89 | this.list.Sort(startIndex, endIndexAddOne - startIndex, Comparer.Default);
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/Log2Window/NListsMerger.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Log2Window
8 | {
9 | class NListsMerger where T : IComparable
10 | {
11 | private MyList Merge2Lists(MyList arr1, MyList arr2)
12 | {
13 | int len1 = arr1.Count;
14 | int len2 = arr2.Count;
15 |
16 | // 定义结果数组
17 | var merged = new MyList();
18 |
19 | // 定义索引位置
20 | int loc1, loc2;
21 | loc1 = loc2 = 0;
22 |
23 | // 遍历两个数组
24 | while (loc1 < len1 && loc2 < len2)
25 | {
26 | if (arr1[loc1].CompareTo(arr2[loc2]) < 0)
27 | {
28 | merged.Enqueue(arr1[loc1++]);
29 | }
30 | else
31 | {
32 | merged.Enqueue(arr2[loc2++]);
33 | }
34 | }
35 |
36 | // 拷贝较长数组余下的元素
37 | while (loc1 < len1)
38 | {
39 | merged.Enqueue(arr1[loc1++]);
40 | }
41 |
42 | while (loc2 < len2)
43 | {
44 | merged.Enqueue(arr2[loc2++]);
45 | }
46 |
47 | return merged;
48 | }
49 |
50 | public MyList MergeNLists(List> lists)
51 | {
52 | if (lists.Count == 0)
53 | {
54 | return null;
55 | }
56 | return Merge(lists, 0, lists.Count - 1);
57 | }
58 |
59 | private MyList Merge(List> lists, int lo, int hi)
60 | {
61 | if (lo == hi)
62 | {
63 | return lists[lo];
64 | }
65 | int mid = lo + (hi - lo) / 2;
66 | MyList l1 = Merge(lists, lo, mid);
67 | MyList l2 = Merge(lists, mid + 1, hi);
68 | return Merge2Lists(l1, l2);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Log2Window/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Windows.Forms;
6 |
7 |
8 | namespace Log2Window
9 | {
10 | static class Program
11 | {
12 | ///
13 | /// The main entry point for the application.
14 | ///
15 | [STAThread]
16 | static void Main(string[] args)
17 | {
18 | if (args.Length > 0)
19 | {
20 | if (args[0].ToLower() == "ClearEventLog".ToLower())
21 | {
22 | MainForm.ClearEventLog(args[1]);
23 | return;
24 | }
25 | }
26 |
27 | log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo("Config/log4net.config"));
28 | Application.ThreadException += Application_ThreadException;
29 | AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
30 |
31 |
32 | Application.EnableVisualStyles();
33 | Application.SetCompatibleTextRenderingDefault(false);
34 | Application.Run(new MainForm());
35 | }
36 |
37 | private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
38 | {
39 | Utils.log.Error("Application_ThreadException", e.Exception);
40 |
41 | //MessageBox.Show(e.Exception.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
42 | }
43 |
44 | private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
45 | {
46 | Utils.log.Error("CurrentDomain_UnhandledException", e.ExceptionObject as Exception);
47 | //MessageBox.Show(e.ExceptionObject.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/src/Log2Window/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("Log2Window")]
8 | [assembly: AssemblyDescription(@"Log2Window is a log message viewer for log4net, nlog, eventLog, log4j and log4cxx, which has strongly extreme stability and very good performance. It can process millions of log messages less than a second.")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("AlanThinker")]
11 | [assembly: AssemblyProduct("Log2Window")]
12 | [assembly: AssemblyCopyright("AlanThinker 2016")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("2881D007-28BD-4907-B4F4-09B627CE8FE4")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | //自2000年1月1日以来的天数作为内部版本号,以及自午夜以来的秒数除以2作为修订版, 注意, 必须给星号留够后面2位
32 | [assembly: AssemblyVersion("2.2.*")]
33 |
34 |
--------------------------------------------------------------------------------
/src/Log2Window/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 Log2Window.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.3.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 |
--------------------------------------------------------------------------------
/src/Log2Window/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/Log2Window/Properties/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
8 |
16 |
17 |
18 | true
19 | PerMonitorV2
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/Log2Window/Receiver/BaseReceiver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 |
4 | using Log2Window.Log;
5 | using System.Text;
6 | using System.Windows.Forms;
7 |
8 | namespace Log2Window.Receiver
9 | {
10 | [Serializable]
11 | public abstract class BaseReceiver : MarshalByRefObject, IReceiver, ICloneable
12 | {
13 | [NonSerialized]
14 | protected ILogMessageNotifiable Notifiable;
15 |
16 | [NonSerialized]
17 | private string _displayName;
18 |
19 |
20 | #region IReceiver Members
21 |
22 | public abstract string SampleClientConfig { get; }
23 |
24 | [Browsable(false)]
25 | public string DisplayName
26 | {
27 | get { return _displayName; }
28 | protected set { _displayName = value; }
29 | }
30 |
31 | string m_TextEncoding = "utf-8";
32 |
33 | [Category("Configuration")]
34 | [DisplayName("Encoding")]
35 | [DefaultValue("utf-8")]
36 | public virtual string TextEncoding
37 | {
38 | get { return m_TextEncoding; }
39 | set
40 | {
41 | try
42 | {
43 | var tempEncoding= Encoding.GetEncoding(value);
44 | this.m_TextEncoding = value;
45 | this.encodingObject = tempEncoding;
46 | }
47 | catch (Exception ex)
48 | {
49 | MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
50 | }
51 | }
52 | }
53 |
54 | private Encoding encodingObject=Encoding.UTF8;
55 | protected Encoding EncodingObject
56 | {
57 | get
58 | {
59 | return encodingObject;
60 | }
61 | }
62 |
63 |
64 | public abstract void Initialize();
65 | public abstract void Terminate();
66 |
67 | public void Attach(ILogMessageNotifiable notifiable)
68 | {
69 | Notifiable = notifiable;
70 | }
71 |
72 | public virtual void Stop()
73 | {
74 | Notifiable = null;
75 | }
76 |
77 | public abstract void Start();
78 |
79 | public object Clone()
80 | {
81 | return this.MemberwiseClone();
82 | }
83 |
84 | #endregion
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/Log2Window/Receiver/EventLogReceiver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using Log2Window.Log;
6 | using System.Collections.Generic;
7 | using System.Windows.Forms;
8 | using System.Threading;
9 |
10 | namespace Log2Window.Receiver
11 | {
12 | [Serializable]
13 | [DisplayName("Windows Event Log")]
14 | public class EventLogReceiver : BaseReceiver
15 | {
16 | [NonSerialized]
17 | private EventLog[] _eventLogs;
18 |
19 | private string _logName;
20 | private string _machineName = ".";
21 | private string _source;
22 | private bool _appendHostNameToLogger = true;
23 | private bool _showFromBeginning = true;
24 |
25 |
26 | [Category("Configuration")]
27 | [DisplayName("Event Log Name")]
28 | [Description("The name of the log on the specified computer. Such as 'Application', 'System', 'Security'. Leave empty to show all logs.(Need administrator.)")]
29 | public string LogName
30 | {
31 | get { return _logName; }
32 | set { _logName = value; }
33 | }
34 |
35 | [Category("Configuration")]
36 | [DisplayName("Machine Name")]
37 | [Description("The computer on which the log exists.")]
38 | public string MachineName
39 | {
40 | get { return _machineName; }
41 | set { _machineName = value; }
42 | }
43 |
44 | [Category("Configuration")]
45 | [DisplayName("Event Log Source")]
46 | [Description("The source of event log entries. Such as 'Windows Error Reporting'. Leave empty to show all source in the log.")]
47 | public string Source
48 | {
49 | get { return _source; }
50 | set { _source = value; }
51 | }
52 |
53 | [Category("Behavior")]
54 | [DisplayName("Append Machine Name to Logger")]
55 | [Description("Append the remote Machine Name to the Logger Name.")]
56 | public bool AppendHostNameToLogger
57 | {
58 | get { return _appendHostNameToLogger; }
59 | set { _appendHostNameToLogger = value; }
60 | }
61 |
62 | [Category("Configuration")]
63 | [DisplayName("Show from Beginning")]
64 | [Description("Show all log messages from the beginning (not just newly added log messages.)")]
65 | [DefaultValue(true)]
66 | public bool ShowFromBeginning
67 | {
68 | get { return _showFromBeginning; }
69 | set
70 | {
71 | _showFromBeginning = value;
72 | }
73 | }
74 |
75 | //[NonSerialized]
76 | //private string _baseLoggerName;
77 |
78 |
79 | #region Overrides of BaseReceiver
80 |
81 | [Browsable(false)]
82 | public override string TextEncoding
83 | {
84 | get;
85 | set;
86 | }
87 |
88 | [Browsable(false)]
89 | public override string SampleClientConfig
90 | {
91 | get
92 | {
93 | return "Use Log2Window to display the Windows Event Logs." + Environment.NewLine +
94 | "Note that the Thread column is used to display the Instance ID (Event ID).";
95 | }
96 | }
97 |
98 | public override void Initialize()
99 | {
100 | //NonSerialized field must be initilized here.
101 | _waitReadExistingEvengLogs = new ManualResetEvent(false);
102 | if (String.IsNullOrEmpty(MachineName))
103 | MachineName = ".";
104 | }
105 |
106 | public override void Start()
107 | {
108 | if (String.IsNullOrEmpty(LogName))
109 | {
110 | _eventLogs = EventLog.GetEventLogs();
111 | }
112 | else
113 | {
114 | _eventLogs = new EventLog[1];
115 | if (string.IsNullOrEmpty(Source))
116 | {
117 | _eventLogs[0] = new EventLog(LogName, MachineName);
118 | }
119 | else
120 | {
121 | _eventLogs[0] = new EventLog(LogName, MachineName, Source);
122 | }
123 | }
124 |
125 | StartListen();
126 |
127 | ReadExistingEvengLogs();
128 | }
129 |
130 | private void StartListen()
131 | {
132 | foreach (var eventLog in _eventLogs)
133 | {
134 | try
135 | {
136 | //sender is not EventLog type, use lamda expresstion to get outer eventLog variable.
137 | eventLog.EntryWritten += delegate (object sender, EntryWrittenEventArgs entryWrittenEventArgs)
138 | {
139 | // If have not finished reading existing EvengLogs, wait until it finished.
140 | _waitReadExistingEvengLogs.WaitOne();
141 |
142 | var entry = entryWrittenEventArgs.Entry;
143 | ParseEventLogEntry(eventLog, entry);
144 | };
145 |
146 | eventLog.EnableRaisingEvents = true;
147 | }
148 | catch (Exception ex)
149 | {
150 | Utils.log.Error(ex.Message, ex);
151 | System.Threading.ThreadPool.QueueUserWorkItem(delegate (object ob)
152 | {
153 | MessageBox.Show(ex.Message, "Warn", MessageBoxButtons.OK, MessageBoxIcon.Warning);
154 | });
155 | }
156 | }
157 | }
158 |
159 | [NonSerialized]
160 | ManualResetEvent _waitReadExistingEvengLogs;
161 | private void ReadExistingEvengLogs()
162 | {
163 | List> data = new List>();
164 | if (ShowFromBeginning)
165 | {
166 | foreach (var eventLog in _eventLogs)
167 | {
168 | try
169 | {
170 | foreach (EventLogEntry entry in eventLog.Entries)
171 | {
172 | if (!string.IsNullOrEmpty(this.Source))
173 | {
174 | if (entry.Source != this.Source)
175 | {
176 | continue;
177 | }
178 | }
179 | data.Add(Tuple.Create(eventLog, entry));
180 | }
181 | }
182 | catch (Exception ex)
183 | {
184 | Utils.log.Error(ex.Message, ex);
185 | }
186 |
187 | }
188 |
189 | data = data.OrderBy(x => x.Item2.TimeGenerated).ThenBy(x => x.Item2.Index).ToList();
190 |
191 | foreach (var item in data)
192 | {
193 | ParseEventLogEntry(item.Item1, item.Item2);
194 | }
195 | }
196 |
197 | _waitReadExistingEvengLogs.Set();
198 | }
199 |
200 | public override void Terminate()
201 | {
202 | foreach (var eventLog in _eventLogs)
203 | {
204 | eventLog.Dispose();
205 | }
206 |
207 | _eventLogs = null;
208 | }
209 |
210 | #endregion
211 |
212 | private void ParseEventLogEntry(EventLog eventLog, EventLogEntry entry)
213 | {
214 | LogMessage logMsg = new LogMessage();
215 | var baseName = "EventLog." + eventLog.Log;
216 | if (AppendHostNameToLogger)
217 | {
218 | baseName = "EventLog_" + (this.MachineName == "." ? "local" : this.MachineName) + "." + eventLog.Log;
219 | }
220 | logMsg.RootLoggerName = baseName;
221 | logMsg.LoggerName = String.IsNullOrEmpty(entry.Source)
222 | ? baseName
223 | : String.Format("{0}.{1}", baseName, entry.Source);
224 |
225 | logMsg.Message = entry.Message;
226 | logMsg.TimeStamp = entry.TimeGenerated;
227 | logMsg.Level = LogUtils.GetLogLevelInfo(GetLogLevel(entry.EntryType));
228 | logMsg.ThreadName = entry.InstanceId.ToString();
229 |
230 | if (!String.IsNullOrEmpty(entry.Category))
231 | logMsg.Properties.Add("Category", entry.Category);
232 | if (!String.IsNullOrEmpty(entry.UserName))
233 | logMsg.Properties.Add("User Name", entry.UserName);
234 |
235 | if (Notifiable != null)
236 | Notifiable.Notify(logMsg);
237 | }
238 |
239 | private static LogLevel GetLogLevel(EventLogEntryType entryType)
240 | {
241 | switch (entryType)
242 | {
243 | case EventLogEntryType.Warning: return LogLevel.Warn;
244 | case EventLogEntryType.FailureAudit:
245 | case EventLogEntryType.Error: return LogLevel.Error;
246 | case EventLogEntryType.SuccessAudit:
247 | case EventLogEntryType.Information: return LogLevel.Info;
248 | default:
249 | return LogLevel.None;
250 | }
251 | }
252 | }
253 | }
254 |
--------------------------------------------------------------------------------
/src/Log2Window/Receiver/FileReceiver.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/Receiver/FileReceiver.cs
--------------------------------------------------------------------------------
/src/Log2Window/Receiver/IReceiver.cs:
--------------------------------------------------------------------------------
1 | using Log2Window.Log;
2 |
3 |
4 | namespace Log2Window.Receiver
5 | {
6 | public interface IReceiver
7 | {
8 | string SampleClientConfig { get; }
9 | string DisplayName { get; }
10 |
11 | void Initialize();
12 | void Start();
13 | void Terminate();
14 |
15 | void Attach(ILogMessageNotifiable notifiable);
16 | void Stop();
17 |
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Log2Window/Receiver/MsmqReceiver.cs:
--------------------------------------------------------------------------------
1 | //using System;
2 | //using System.ComponentModel;
3 | //using System.IO;
4 | //using System.Text;
5 | //using System.Threading;
6 | //using System.Messaging;
7 |
8 | //using Log2Window.Log;
9 |
10 |
11 | //namespace Log2Window.Receiver
12 | //{
13 |
14 | // [Serializable]
15 | // [DisplayName("Windows Message Queue (MSMQ)")]
16 | // public class MsmqReceiver : BaseReceiver
17 | // {
18 | // [NonSerialized]
19 | // private MessageQueue _queue;
20 |
21 | // [NonSerialized]
22 | // private Timer _queueCreationCheckTimer;
23 |
24 | // [NonSerialized] private const int QueueCheckTimerDelayAndInterval = 5000;
25 |
26 |
27 | // private string _queueName = @".\private$\log4net";
28 |
29 | // [Category("Configuration")]
30 | // [DisplayName("Queue Name")]
31 | // [DefaultValue(@".\private$\log4net")]
32 | // [Description(@"Name of the queue to create. I.e. .\private$\log4net")]
33 | // public string QueueName
34 | // {
35 | // get { return _queueName; }
36 | // set { _queueName = value; }
37 | // }
38 |
39 | // [Category("Configuration")]
40 | // [DisplayName("Create Queue")]
41 | // [Description("Determines how to handle queue creation. If true and the queue does not exist it will be created. If false and the queue does not exist the receiver will wait for the queue to be created.")]
42 | // public bool Create { get; set; }
43 |
44 | // [Category("Configuration")]
45 | // public bool Transactional { get; set; }
46 |
47 |
48 | // private bool _bulkProcessBackedUpMessages = true;
49 |
50 | // [Category("Behavior")]
51 | // [DefaultValue(true)]
52 | // [DisplayName("Bulk Process Backed Up Messages")]
53 | // [Description("If true multiple messages in the queue are processed as one update to the log viewer. This improves the performance of the viewer")]
54 | // public bool BulkProcessBackedUpMessages
55 | // {
56 | // get { return _bulkProcessBackedUpMessages;}
57 | // set { _bulkProcessBackedUpMessages = value; }
58 | // }
59 |
60 |
61 | // [Browsable(false)]
62 | // public override string SampleClientConfig
63 | // {
64 | // get
65 | // {
66 | // return
67 | // "Configuration for NLog:" + Environment.NewLine +
68 | // "" + Environment.NewLine +
71 | // Environment.NewLine + Environment.NewLine +
72 | // "Configuration for log4net:" + Environment.NewLine +
73 | // Environment.NewLine +
74 | // "NOTE: log4net (1.2.10) does not include an MSMQ appender. The following configuration is based on the MSMQ Appender in '.\\examples\\net\\1.0\\Appenders\\SampleAppendersApp\\cs\\src' that is included in the log4net download."+
75 | // Environment.NewLine + Environment.NewLine +
76 | // "" +
77 | // Environment.NewLine +
78 | // "\t" + Environment.NewLine +
79 | // "\t" + Environment.NewLine +
80 | // "\t" + Environment.NewLine +
81 | // "";
82 | // }
83 | // }
84 |
85 |
86 | // ///
87 | // ///
88 | // ///
89 | // public override void Initialize()
90 | // {
91 | // if (!MessageQueue.Exists(QueueName))
92 | // {
93 | // if (Create)
94 | // {
95 | // MessageQueue.Create(QueueName, Transactional);
96 | // }
97 | // else
98 | // {
99 | // /*
100 | // * Start the queue check timer. Should the time be configurable?
101 | // */
102 | // _queueCreationCheckTimer = new Timer(QueueCreationCheckTimerFunction, this,
103 | // QueueCheckTimerDelayAndInterval,
104 | // QueueCheckTimerDelayAndInterval);
105 | // return;
106 | // }
107 | // }
108 |
109 | // Start();
110 | // }
111 |
112 |
113 |
114 | // ///
115 | // ///
116 | // ///
117 | // private void Start()
118 | // {
119 |
120 | // _queue = new MessageQueue(QueueName);
121 |
122 | // _queue.ReceiveCompleted += delegate(Object source, ReceiveCompletedEventArgs asyncResult)
123 | // {
124 | // try
125 | // {
126 | // // End the asynchronous receive operation.
127 | // Message m = ((MessageQueue)source).EndReceive(asyncResult.AsyncResult);
128 |
129 | // if (Notifiable != null)
130 | // {
131 | // string loggingEvent = Encoding.ASCII.GetString(((MemoryStream)m.BodyStream).ToArray());
132 | // LogMessage logMsg = ReceiverUtils.ParseLog4JXmlLogEvent(loggingEvent, "MSMQLogger");
133 | // logMsg.LoggerName = string.Format("{0}_{1}", QueueName.TrimStart('.'), logMsg.LoggerName);
134 | // logMsg.RootLoggerName = QueueName;
135 | // Notifiable.Notify(logMsg);
136 | // }
137 |
138 |
139 | // if (BulkProcessBackedUpMessages)
140 | // {
141 | // Message[] all = ((MessageQueue) source).GetAllMessages();
142 | // if (all.Length > 0)
143 | // {
144 | // int numberofmessages = all.Length > 1000 ? 1000 : all.Length;
145 |
146 | // LogMessage[] logs = new LogMessage[numberofmessages];
147 |
148 | // for (int i = 0; i < numberofmessages; i++)
149 | // {
150 | // Message thisone = ((MessageQueue) source).Receive();
151 |
152 | // string loggingEvent =
153 | // Encoding.ASCII.GetString(((MemoryStream) thisone.BodyStream).ToArray());
154 | // LogMessage logMsg = ReceiverUtils.ParseLog4JXmlLogEvent(loggingEvent, "MSMQLogger");
155 | // logMsg.LoggerName = string.Format("{0}_{1}", QueueName.TrimStart('.'), logMsg.LoggerName);
156 | // logs[i] = logMsg;
157 | // }
158 |
159 | // Notifiable.Notify(logs);
160 | // }
161 | // }
162 |
163 | // ((MessageQueue)source).BeginReceive();
164 | // }
165 | // catch (MessageQueueException ex)
166 | // {
167 | // Utils.log.Error(ex.Message, ex);
168 | // // Handle sources of MessageQueueException.
169 | // }
170 | // };
171 |
172 | // _queue.BeginReceive();
173 | // }
174 |
175 |
176 |
177 |
178 | // ///
179 | // ///
180 | // ///
181 | // public override void Terminate()
182 | // {
183 | // /*
184 | // * Are we going to have any issues if we are processing a receive complete or will
185 | // * MSMQ protect us?
186 | // */
187 | // if (_queue != null)
188 | // {
189 | // _queue.Close();
190 | // }
191 | // }
192 |
193 |
194 | // ///
195 | // ///
196 | // ///
197 | // ///
198 | // private static void QueueCreationCheckTimerFunction(object state)
199 | // {
200 | // //TODOCJH: If this timer gets called then we did not finish the job before the maximum allowable time.
201 | // //_logger.Fatal("JobMaxExecutionTimerFunction");
202 |
203 | // MsmqReceiver rcv = state as MsmqReceiver;
204 | // if ((rcv != null) && MessageQueue.Exists(rcv.QueueName))
205 | // {
206 | // rcv._queueCreationCheckTimer.Change(Timeout.Infinite, Timeout.Infinite);
207 | // rcv._queueCreationCheckTimer.Dispose();
208 | // rcv.Start();
209 | // }
210 | // }
211 | // }
212 | //}
213 |
--------------------------------------------------------------------------------
/src/Log2Window/Receiver/ReceiverFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.IO;
5 | using System.Reflection;
6 | using System.Text;
7 | using System.Xml;
8 | using System.Linq;
9 | using Log2Window.Log;
10 |
11 | namespace Log2Window.Receiver
12 | {
13 | public class ReceiverFactory
14 | {
15 | public class ReceiverInfo
16 | {
17 | public string Name;
18 | public Type Type;
19 |
20 | public override string ToString()
21 | {
22 | return Name;
23 | }
24 | }
25 |
26 | private static ReceiverFactory _instance;
27 |
28 | private readonly Dictionary _receiverTypes = new Dictionary();
29 |
30 |
31 | private static readonly string ReceiverInterfaceName = typeof(IReceiver).FullName;
32 |
33 | private ReceiverFactory()
34 | {
35 | // Get all the possible receivers by enumerating all the types implementing the interface
36 | Assembly assembly = Assembly.GetAssembly(typeof(IReceiver));
37 | Type[] types = assembly.GetTypes();
38 | foreach (Type type in types)
39 | {
40 | // Skip abstract types
41 | if (type.IsAbstract)
42 | continue;
43 |
44 | Type[] findInterfaces = type.FindInterfaces((typeObj, o) => (typeObj.ToString() == ReceiverInterfaceName), null);
45 | if (findInterfaces.Length < 1)
46 | continue;
47 |
48 | AddReceiver(type);
49 | }
50 |
51 | _receiverTypes = _receiverTypes.OrderBy(x => x.Value.Name).ToDictionary(x => x.Key, x => x.Value);
52 | }
53 |
54 | private void AddReceiver(Type type)
55 | {
56 | var info = new ReceiverInfo { Name = ReceiverUtils.GetTypeDescription(type), Type = type };
57 | _receiverTypes.Add(type.FullName, info);
58 | }
59 |
60 | public static ReceiverFactory Instance
61 | {
62 | get { return _instance ?? (_instance = new ReceiverFactory()); }
63 | }
64 |
65 | public Dictionary ReceiverTypes
66 | {
67 | get { return _receiverTypes; }
68 | }
69 |
70 | public IReceiver Create(string typeStr)
71 | {
72 | IReceiver receiver = null;
73 |
74 | ReceiverInfo info;
75 | if (_receiverTypes.TryGetValue(typeStr, out info))
76 | {
77 | receiver = Activator.CreateInstance(info.Type) as IReceiver;
78 | }
79 |
80 | return receiver;
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/Log2Window/Receiver/ReceiverUtils.cs:
--------------------------------------------------------------------------------
1 | using Log2Window.Log;
2 | using System;
3 | using System.ComponentModel;
4 | using System.IO;
5 | using System.Text;
6 | using System.Text.RegularExpressions;
7 | using System.Xml;
8 |
9 | namespace Log2Window.Receiver
10 | {
11 | public static class ReceiverUtils
12 | {
13 | static readonly DateTime s1970 = new DateTime(1970, 1, 1);
14 |
15 | public static string GetTypeDescription(Type type)
16 | {
17 | var attr = (DisplayNameAttribute)Attribute.GetCustomAttribute(type, typeof(DisplayNameAttribute), true);
18 | return attr != null ? attr.DisplayName : type.ToString();
19 | }
20 |
21 | ///
22 | /// We can share settings to improve performance
23 | ///
24 | static readonly XmlReaderSettings XmlSettings = CreateSettings();
25 |
26 | static XmlReaderSettings CreateSettings()
27 | {
28 | return new XmlReaderSettings { CloseInput = false, ValidationType = ValidationType.None };
29 | }
30 |
31 | ///
32 | /// We can share parser context to improve performance
33 | ///
34 | static readonly XmlParserContext XmlContext = CreateContext();
35 |
36 | static XmlParserContext CreateContext()
37 | {
38 | var nt = new NameTable();
39 | var nsmanager = new XmlNamespaceManager(nt);
40 | nsmanager.AddNamespace("log4j", "http://jakarta.apache.org/log4j/");
41 | nsmanager.AddNamespace("nlog", "http://nlog-project.org");
42 | return new XmlParserContext(nt, nsmanager, "elem", XmlSpace.None, Encoding.UTF8);
43 | }
44 |
45 | ///
46 | /// Parse LOG4JXml from xml stream
47 | ///
48 | public static LogMessage ParseLog4JXmlLogEvent(Stream logStream, string defaultLogger)
49 | {
50 | // In case of ungraceful disconnect
51 | // logStream is closed and XmlReader throws the exception,
52 | // which we handle in TcpReceiver
53 | using (var reader = XmlReader.Create(logStream, XmlSettings, XmlContext))
54 | return ParseLog4JXmlLogEvent(reader, defaultLogger);
55 | }
56 |
57 | // 将不可解析的特殊字符替换为空格.
58 | // https://stackoverflow.com/questions/21053138/c-sharp-hexadecimal-value-0x12-is-an-invalid-character
59 | // 注意, 原回答中, 0x26 也被替换了. 这是错误的. 只应当替换0x1F以下的字符. 因为 " 之类的是表示引号. 等等
60 | static string ReplaceHexadecimalSymbols(string txt)
61 | {
62 | string r = "[\x00-\x08\x0B\x0C\x0E-\x1F]";
63 | return Regex.Replace(txt, r, " ", RegexOptions.Compiled);
64 | }
65 |
66 | ///
67 | /// Parse LOG4JXml from string
68 | ///
69 | public static LogMessage ParseLog4JXmlLogEvent(string logEvent, string defaultLogger)
70 | {
71 | try
72 | {
73 | logEvent = ReplaceHexadecimalSymbols(logEvent);
74 | using (var reader = new XmlTextReader(logEvent, XmlNodeType.Element, XmlContext))
75 | return ParseLog4JXmlLogEvent(reader, defaultLogger);
76 | }
77 | catch (Exception ex)
78 | {
79 | Utils.log.Error("ParseLog4JXmlLogEvent: " + ex.Message + "\nraw message:\n" + logEvent, ex);
80 | return new LogMessage
81 | {
82 | // Create a simple log message with some default values
83 | LoggerName = defaultLogger,
84 | RootLoggerName = defaultLogger,
85 | ThreadName = "NA",
86 | Message = logEvent,
87 | TimeStamp = DateTime.Now,
88 | Level = LogLevels.Instance[LogLevel.Info],
89 | ExceptionString = ex.Message
90 | };
91 | }
92 | }
93 |
94 | ///
95 | /// Here we expect the log event to use the log4j schema.
96 | /// Sample:
97 | ///
98 | /// This is an Message
99 | ///
100 | ///
101 | ///
102 | ///
103 | ///
104 | ///
105 | ///
106 | ///
107 | ///
108 | /// Implementation inspired from: http://geekswithblogs.net/kobush/archive/2006/04/20/75717.aspx
109 | ///
110 | public static LogMessage ParseLog4JXmlLogEvent(XmlReader reader, string defaultLogger)
111 | {
112 | var logMsg = new LogMessage();
113 |
114 | reader.Read();
115 | if ((reader.MoveToContent() != XmlNodeType.Element) || (reader.Name != "log4j:event"))
116 | throw new Exception("The Log Event is not a valid log4j Xml block.");
117 |
118 | logMsg.LoggerName = reader.GetAttribute("logger");
119 | logMsg.Level = LogLevels.Instance[reader.GetAttribute("level")];
120 | logMsg.ThreadName = reader.GetAttribute("thread");
121 |
122 | long timeStamp;
123 | if (long.TryParse(reader.GetAttribute("timestamp"), out timeStamp))
124 | logMsg.TimeStamp = s1970.AddMilliseconds(timeStamp).ToLocalTime();
125 |
126 | int eventDepth = reader.Depth;
127 | reader.Read();
128 | while (reader.Depth > eventDepth)
129 | {
130 | if (reader.MoveToContent() == XmlNodeType.Element)
131 | {
132 | switch (reader.Name)
133 | {
134 | case "log4j:message":
135 | logMsg.Message = reader.ReadString();
136 | break;
137 |
138 | case "log4j:throwable":
139 | var exValue = reader.ReadString();
140 | logMsg.ExceptionString = exValue;
141 | break;
142 |
143 | case "log4j:locationInfo":
144 | logMsg.CallSiteClass = reader.GetAttribute("class");
145 | logMsg.CallSiteMethod = reader.GetAttribute("method");
146 | logMsg.SourceFileName = reader.GetAttribute("file");
147 | uint sourceFileLine;
148 | if (uint.TryParse(reader.GetAttribute("line"), out sourceFileLine))
149 | logMsg.SourceFileLineNr = sourceFileLine;
150 | break;
151 | case "nlog:eventSequenceNumber":
152 | ulong sequenceNumber;
153 | if (ulong.TryParse(reader.ReadString(), out sequenceNumber))
154 | logMsg.SequenceNr = sequenceNumber;
155 | break;
156 | case "nlog:locationInfo":
157 | break;
158 |
159 | case "log4j:properties":
160 | reader.Read();
161 | while (reader.MoveToContent() == XmlNodeType.Element
162 | && reader.Name == "log4j:data")
163 | {
164 | string name = reader.GetAttribute("name");
165 | string value = reader.GetAttribute("value");
166 | if (name != null && name.ToLower().Equals("exceptions"))
167 | {
168 | logMsg.ExceptionString = value;
169 | }
170 | else
171 | {
172 | logMsg.Properties[name] = value;
173 | }
174 |
175 | reader.Read();
176 | }
177 |
178 | break;
179 | }
180 | }
181 | reader.Read();
182 | }
183 |
184 | return logMsg;
185 | }
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/src/Log2Window/Receiver/RemotingReceiver.cs:
--------------------------------------------------------------------------------
1 | //using System;
2 | //using System.ComponentModel;
3 | //using System.Collections;
4 | //using System.Runtime.Remoting;
5 | //using System.Runtime.Remoting.Channels;
6 | //using System.Runtime.Remoting.Channels.Tcp;
7 | //using System.Runtime.Serialization;
8 | //using System.Runtime.Serialization.Formatters;
9 |
10 | //using log4net.Appender;
11 | //using log4net.Core;
12 |
13 | //using Log2Window.Log;
14 |
15 |
16 | //namespace Log2Window.Receiver
17 | //{
18 | // [Serializable]
19 | // [DisplayName(".NET Remoting")]
20 | // public class RemotingReceiver : BaseReceiver, RemotingAppender.IRemoteLoggingSink, ISerializable
21 | // {
22 | // private const string RemotingReceiverChannelName = "RemotingReceiverChannel";
23 |
24 | // [NonSerialized]
25 | // private IChannel _channel = null;
26 |
27 | // private string _sinkName = "LoggingSink";
28 | // private int _port = 7070;
29 | // private bool _appendHostNameToLogger = true;
30 |
31 |
32 | // [Category("Configuration")]
33 | // [DisplayName("Remote Sink Name")]
34 | // public string SinkName
35 | // {
36 | // get { return _sinkName; }
37 | // set { _sinkName = value; }
38 | // }
39 |
40 | // [Category("Configuration")]
41 | // [DisplayName("Remote TCP Port Number")]
42 | // public int Port
43 | // {
44 | // get { return _port; }
45 | // set { _port = value; }
46 | // }
47 |
48 | // [Category("Behavior")]
49 | // [DisplayName("Append Host Name to Logger")]
50 | // [Description("Append the remote Host Name to the Logger Name.")]
51 | // public bool AppendHostNameToLogger
52 | // {
53 | // get { return _appendHostNameToLogger; }
54 | // set { _appendHostNameToLogger = value; }
55 | // }
56 |
57 |
58 | // ///
59 | // /// Default ctor
60 | // ///
61 | // public RemotingReceiver() { }
62 |
63 | // #region ISerializable Members
64 |
65 | // ///
66 | // /// Constructor for Serialization
67 | // /// N.B: Explicit implementation of ISerializable to mask SecurityIdentity Property of mother class
68 | // ///
69 | // public RemotingReceiver(SerializationInfo info, StreamingContext context)
70 | // {
71 | // _sinkName = info.GetString("SinkName");
72 | // _port = info.GetInt32("Port");
73 | // }
74 |
75 | // ///
76 | // /// ISerializable method override for deserialization
77 | // /// N.B: Explicit implementation of ISerializable to mask SecurityIdentity Property of mother class
78 | // ///
79 | // public void GetObjectData(SerializationInfo info, StreamingContext context)
80 | // {
81 | // info.AddValue("SinkName", _sinkName);
82 | // info.AddValue("Port", _port);
83 | // }
84 |
85 | // #endregion
86 |
87 |
88 | // #region IReceiver Members
89 |
90 | // [Browsable(false)]
91 | // public override string SampleClientConfig
92 | // {
93 | // get
94 | // {
95 | // return
96 | // "Configuration for log4net:" + Environment.NewLine +
97 | // "" + Environment.NewLine +
98 | // " " + Environment.NewLine +
99 | // " " + Environment.NewLine +
100 | // " " + Environment.NewLine +
101 | // " " + Environment.NewLine +
102 | // " " + Environment.NewLine +
103 | // " " + Environment.NewLine +
104 | // "";
105 | // }
106 | // }
107 |
108 | // public override void Initialize()
109 | // {
110 | // // Channel already open?
111 | // _channel = ChannelServices.GetChannel(RemotingReceiverChannelName);
112 |
113 |
114 | // if (_channel == null)
115 | // {
116 | // // Allow clients to receive complete Remoting exception information
117 | // if (RemotingConfiguration.CustomErrorsEnabled(true))
118 | // RemotingConfiguration.CustomErrorsMode = CustomErrorsModes.Off;
119 |
120 | // // Create TCP Channel
121 | // try
122 | // {
123 | // BinaryClientFormatterSinkProvider clientProvider = null;
124 | // BinaryServerFormatterSinkProvider serverProvider =
125 | // new BinaryServerFormatterSinkProvider();
126 | // serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
127 |
128 | // IDictionary props = new Hashtable();
129 | // props["port"] = _port.ToString();
130 | // props["name"] = RemotingReceiverChannelName;
131 | // props["typeFilterLevel"] = TypeFilterLevel.Full;
132 | // _channel = new TcpChannel(props, clientProvider, serverProvider);
133 |
134 | // ChannelServices.RegisterChannel(_channel, false);
135 | // }
136 | // catch (Exception ex)
137 | // {
138 | // throw new Exception("Remoting TCP Channel Initialization failed", ex);
139 | // }
140 | // }
141 |
142 | // Type serverType = RemotingServices.GetServerTypeForUri(_sinkName);
143 | // if ((serverType == null) || (serverType != typeof(RemotingAppender.IRemoteLoggingSink)))
144 | // {
145 | // // Marshal Receiver
146 | // try
147 | // {
148 | // RemotingServices.Marshal(this, _sinkName, typeof(RemotingAppender.IRemoteLoggingSink));
149 | // }
150 | // catch (Exception ex)
151 | // {
152 | // throw new Exception("Remoting Marshal failed", ex);
153 | // }
154 | // }
155 | // }
156 |
157 | // public override void Terminate()
158 | // {
159 | // if (_channel != null)
160 | // ChannelServices.UnregisterChannel(_channel);
161 | // _channel = null;
162 | // }
163 |
164 | // #endregion
165 |
166 |
167 | // #region Override implementation of MarshalByRefObject
168 |
169 | // ///
170 | // /// Obtains a lifetime service object to control the lifetime
171 | // /// policy for this instance.
172 | // ///
173 | // /// null to indicate that this instance should live forever.
174 | // ///
175 | // ///
176 | // /// Obtains a lifetime service object to control the lifetime
177 | // /// policy for this instance. This object should live forever
178 | // /// therefore this implementation returns null.
179 | // ///
180 | // ///
181 | // public override object InitializeLifetimeService()
182 | // {
183 | // return null;
184 | // }
185 |
186 | // #endregion Override implementation of MarshalByRefObject
187 |
188 |
189 | // #region Implementation of IRemoteLoggingSink
190 |
191 | // public void LogEvents(LoggingEvent[] events)
192 | // {
193 | // if ((events == null) || (events.Length == 0) || (Notifiable == null))
194 | // return;
195 |
196 | // LogMessage[] logMsgs = new LogMessage[events.Length];
197 | // for (int i = 0; i < events.Length; i++)
198 | // logMsgs[i] = CreateLogMessage(events[i]);
199 |
200 | // Notifiable.Notify(logMsgs);
201 | // }
202 |
203 | // #endregion Implementation of IRemoteLoggingSink
204 |
205 |
206 | // protected LogMessage CreateLogMessage(LoggingEvent logEvent)
207 | // {
208 | // LogMessage logMsg = new LogMessage();
209 | // if (_appendHostNameToLogger && logEvent.Properties.Contains(LoggingEvent.HostNameProperty))
210 | // {
211 | // logMsg.RootLoggerName = logEvent.Properties[LoggingEvent.HostNameProperty].ToString();
212 | // logMsg.LoggerName = String.Format("[Host: {0}].{1}", logEvent.Properties[LoggingEvent.HostNameProperty],
213 | // logEvent.LoggerName);
214 | // }
215 | // else
216 | // {
217 | // logMsg.RootLoggerName = logEvent.LoggerName;
218 | // logMsg.LoggerName = logEvent.LoggerName;
219 | // }
220 |
221 | // logMsg.ThreadName = logEvent.ThreadName;
222 | // logMsg.Message = logEvent.RenderedMessage;
223 | // logMsg.TimeStamp = logEvent.TimeStamp;
224 | // logMsg.Level = LogUtils.GetLogLevelInfo(logEvent.Level.Value);
225 |
226 | // // Per LoggingEvent.ExceptionObject, the exception object is not serialized, but the exception
227 | // // text is available through LoggingEvent.GetExceptionString
228 | // logMsg.ExceptionString = logEvent.GetExceptionString();
229 |
230 | // // Copy properties as string
231 | // foreach (DictionaryEntry entry in logEvent.Properties)
232 | // {
233 | // if ((entry.Key == null) || (entry.Value == null))
234 | // continue;
235 |
236 | // logMsg.Properties.Add(entry.Key.ToString(), entry.Value.ToString());
237 | // }
238 |
239 | // return logMsg;
240 | // }
241 | // }
242 | //}
243 |
--------------------------------------------------------------------------------
/src/Log2Window/Receiver/SLPolicyServerReceiver.cs:
--------------------------------------------------------------------------------
1 | //using System;
2 | //using System.ComponentModel;
3 | //using System.Net;
4 | //using System.Net.Sockets;
5 | //using System.Text;
6 |
7 | //namespace Log2Window.Receiver
8 | //{
9 | // [Serializable]
10 | // [DisplayName("Silverlight Socket Policy")]
11 | // public class SLPolicyServerReceiver : BaseReceiver
12 | // {
13 | // [NonSerialized]
14 | // private Socket _socket;
15 |
16 | // int _portFrom = 4502;
17 | // int _portTo = 4532;
18 |
19 | // [Category("Configuration")]
20 | // [DisplayName("TCP Port From")]
21 | // [DefaultValue(4502)]
22 | // public int PortFrom
23 | // {
24 | // get { return _portFrom; }
25 | // set { _portFrom = value; }
26 | // }
27 |
28 | // [Category("Configuration")]
29 | // [DisplayName("TCP Port To")]
30 | // [DefaultValue(4532)]
31 | // public int PortTo
32 | // {
33 | // get { return _portTo; }
34 | // set { _portTo = value; }
35 | // }
36 |
37 | // #region IReceiver Members
38 |
39 | // [Browsable(false)]
40 | // public override string SampleClientConfig
41 | // {
42 | // get
43 | // {
44 | // return "This receiver allows Silverlight client to use sockets";
45 | // }
46 | // }
47 |
48 | // const string PolicyRequestString = "";
49 | // const string PolicyTemplate =
50 | // @"
51 | //
52 | //
53 | //
54 | //
55 | //
56 | //
57 | //
58 | //
59 | //
60 | //";
61 |
62 | // byte[] _policy;
63 |
64 | // public override void Initialize()
65 | // {
66 | // if (_socket != null) return;
67 |
68 | // _policy = Encoding.UTF8.GetBytes(string.Format(PolicyTemplate, _portFrom, _portTo));
69 |
70 | // _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
71 | // _socket.ExclusiveAddressUse = true;
72 | // _socket.Bind(new IPEndPoint(IPAddress.Any, 943));
73 | // _socket.Listen(100);
74 |
75 | // var args = new SocketAsyncEventArgs();
76 | // args.Completed += AcceptAsyncCompleted;
77 |
78 | // _socket.AcceptAsync(args);
79 | // }
80 |
81 | // void AcceptAsyncCompleted(object sender, SocketAsyncEventArgs e)
82 | // {
83 | // if (_socket == null) return;
84 |
85 | // var socket = e.AcceptSocket;
86 |
87 | // e.AcceptSocket = null;
88 | // _socket.AcceptAsync(e);
89 |
90 | // ProcessRequest(socket);
91 | // }
92 |
93 | // void ProcessRequest(Socket socket)
94 | // {
95 | // using (var client = new TcpClient { Client = socket, ReceiveTimeout = 5000 })
96 | // using (var s = client.GetStream())
97 | // {
98 | // var buffer = new byte[PolicyRequestString.Length];
99 | // s.Read(buffer, 0, buffer.Length);
100 | // s.Write(_policy, 0, _policy.Length);
101 | // }
102 | // }
103 |
104 | // public override void Terminate()
105 | // {
106 | // if (_socket == null) return;
107 |
108 | // _socket.Close();
109 | // _socket = null;
110 | // }
111 |
112 | // #endregion
113 | // }
114 | //}
115 |
--------------------------------------------------------------------------------
/src/Log2Window/Receiver/TcpReceiver.cs:
--------------------------------------------------------------------------------
1 | using Log2Window.Log;
2 | using System;
3 | using System.ComponentModel;
4 | using System.Diagnostics;
5 | using System.IO;
6 | using System.Net;
7 | using System.Net.Sockets;
8 | using System.Text;
9 | using System.Threading;
10 |
11 | namespace Log2Window.Receiver
12 | {
13 | [Serializable]
14 | [DisplayName("TCP (IP v4 and v6)")]
15 | public class TcpReceiver : BaseReceiver
16 | {
17 | #region Port Property
18 |
19 | int _port = 4505;
20 | [Category("Configuration")]
21 | [DisplayName("TCP Port Number")]
22 | [DefaultValue(4505)]
23 | public int Port
24 | {
25 | get { return _port; }
26 | set { _port = value; }
27 | }
28 |
29 | #endregion
30 |
31 | #region IpV6 Property
32 |
33 | bool _ipv6;
34 | [Category("Configuration")]
35 | [DisplayName("Use IPv6 Addresses")]
36 | [DefaultValue(false)]
37 | public bool IpV6
38 | {
39 | get { return _ipv6; }
40 | set { _ipv6 = value; }
41 | }
42 |
43 | private int _bufferSize = 65536;
44 | [Category("Configuration")]
45 | [DisplayName("Receive Buffer Size")]
46 | [DefaultValue(65536)]
47 | public int BufferSize
48 | {
49 | get { return _bufferSize; }
50 | set { _bufferSize = Math.Max(65536, value); }
51 | }
52 |
53 | bool _useRemoteIPAsNamespacePrefix;
54 | [Category("Configuration")]
55 | [DisplayName("Use Remote IP As Namespace Prefix.")]
56 | [DefaultValue(false)]
57 | public bool UseRemoteIPAsNamespacePrefix
58 | {
59 | get { return _useRemoteIPAsNamespacePrefix; }
60 | set { _useRemoteIPAsNamespacePrefix = value; }
61 | }
62 |
63 | #endregion
64 |
65 | #region IReceiver Members
66 |
67 | [Browsable(false)]
68 | public override string SampleClientConfig
69 | {
70 | get
71 | {
72 | return
73 | @"Configuration for NLog:
74 |
75 |
76 | Configuration for log4net:
77 | Please using AlanThinker.MyLog4net.TcpAppender.cs in the ExampleProject\TestLog4net project.
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | ".Replace("'", "\"").Replace("\n", Environment.NewLine);
92 | }
93 | }
94 |
95 | [NonSerialized]
96 | Socket _socket;
97 |
98 | public override void Initialize()
99 | {
100 | if (_socket != null) return;
101 |
102 | _socket = new Socket(_ipv6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
103 | _socket.ExclusiveAddressUse = true;
104 | _socket.Bind(new IPEndPoint(_ipv6 ? IPAddress.IPv6Any : IPAddress.Any, _port));
105 | _socket.Listen(100);
106 | _socket.ReceiveBufferSize = _bufferSize;
107 | }
108 |
109 | public override void Start()
110 | {
111 | var args = new SocketAsyncEventArgs();
112 | args.Completed += AcceptAsyncCompleted;
113 |
114 | _socket.AcceptAsync(args);
115 | }
116 |
117 | void AcceptAsyncCompleted(object sender, SocketAsyncEventArgs e)
118 | {
119 | try
120 | {
121 | if (_socket == null || e.SocketError != SocketError.Success) return;
122 |
123 | //Must start a new thread to prcess data, otherwise can only process only one connection.
124 | new Thread(ProcessReceivedData) { IsBackground = true }.Start(e.AcceptSocket);
125 |
126 | e.AcceptSocket = null;
127 | _socket.AcceptAsync(e);
128 | }
129 | catch (Exception ex)
130 | {
131 | Utils.log.Error(ex.Message, ex);
132 | }
133 | }
134 |
135 | static char[] log4jEndTag = "".ToCharArray();
136 | void ProcessReceivedData(object newSocket)
137 | {
138 | try
139 | {
140 | using (var socket = (Socket)newSocket)
141 | using (var ns = new NetworkStream(socket, FileAccess.Read, false))
142 | while (_socket != null)
143 | {
144 | using (StreamReader sr = new StreamReader(ns, this.EncodingObject))
145 | {
146 | //NetworkStream may contain multiple log4j:event, if the tcp send message very frequently.
147 | StringBuilder sb = new StringBuilder();
148 |
149 | int temp;
150 | while (_socket != null
151 | && (temp = sr.Read()) != -1)
152 | {
153 | sb.Append((char)temp);
154 | if (IsEndWith(sb, log4jEndTag))
155 | {
156 | var str = sb.ToString();
157 | LogMessage logMsg = ReceiverUtils.ParseLog4JXmlLogEvent(str, "TcpLogger");
158 | logMsg.RootLoggerName = logMsg.LoggerName;
159 | //logMsg.LoggerName = string.Format(":{1}.{0}", logMsg.LoggerName, _port);
160 |
161 | if (_useRemoteIPAsNamespacePrefix)
162 | {
163 | var ipEndPoint = socket.RemoteEndPoint as IPEndPoint;
164 | if (ipEndPoint != null)
165 | {
166 | logMsg.LoggerName = string.Format("{0}.{1}", ipEndPoint.Address.ToString().Replace('.', '_'), logMsg.LoggerName);
167 | }
168 | else
169 | {
170 | var dnsEndPoint = socket.RemoteEndPoint as DnsEndPoint;
171 | if (dnsEndPoint != null)
172 | {
173 | logMsg.LoggerName = string.Format("{0}.{1}", dnsEndPoint.Host.Replace('.', '_'), logMsg.LoggerName);
174 | }
175 | else
176 | {
177 | // rmove ':' , because same app may have different port number after it restart.
178 | var fullAddress = socket.RemoteEndPoint.ToString();
179 | var address = fullAddress.Substring(0, fullAddress.IndexOf(":"));
180 | logMsg.LoggerName = string.Format("{0}.{1}", address.Replace('.', '_'), logMsg.LoggerName);
181 | }
182 | }
183 | }
184 |
185 | if (Notifiable != null)
186 | Notifiable.Notify(logMsg);
187 |
188 | sb = new StringBuilder();
189 | }
190 |
191 | }
192 | }
193 | }
194 | }
195 | catch (IOException ex)
196 | {
197 | Utils.log.Error("ProcessReceivedData " + ex.Message);
198 | }
199 | catch (Exception ex)
200 | {
201 | Utils.log.Error(ex.Message, ex);
202 | }
203 | }
204 |
205 | private bool IsEndWith(StringBuilder sb, char[] str)
206 | {
207 | if (sb.Length < str.Length)
208 | return false;
209 |
210 | for (int i = str.Length - 1, j = sb.Length - 1; i >= 0; i--, j--)
211 | {
212 | if (str[i] != sb[j])
213 | {
214 | return false;
215 | }
216 | }
217 |
218 | return true;
219 | }
220 |
221 | public override void Terminate()
222 | {
223 | if (_socket == null) return;
224 |
225 | _socket.Close();
226 | _socket = null;
227 | }
228 |
229 | #endregion
230 | }
231 | }
232 |
--------------------------------------------------------------------------------
/src/Log2Window/Receiver/UdpReceiver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Net;
4 | using System.Net.Sockets;
5 | using System.Text;
6 | using System.Threading;
7 |
8 | using Log2Window.Log;
9 |
10 |
11 | namespace Log2Window.Receiver
12 | {
13 | [Serializable]
14 | [DisplayName("UDP (IP v4 and v6)")]
15 | public class UdpReceiver : BaseReceiver
16 | {
17 | [NonSerialized]
18 | private Thread _worker;
19 | [NonSerialized]
20 | private UdpClient _udpClient;
21 | [NonSerialized]
22 | private IPEndPoint _remoteEndPoint;
23 |
24 | private bool _ipv6;
25 | private int _port = 7071;
26 | private string _address = String.Empty;
27 | private int _bufferSize = 1310720;
28 |
29 |
30 | [Category("Configuration")]
31 | [DisplayName("UDP Port Number")]
32 | [DefaultValue(7071)]
33 | public int Port
34 | {
35 | get { return _port; }
36 | set { _port = value; }
37 | }
38 |
39 | [Category("Configuration")]
40 | [DisplayName("Use IPv6 Addresses")]
41 | [DefaultValue(false)]
42 | public bool IpV6
43 | {
44 | get { return _ipv6; }
45 | set { _ipv6 = value; }
46 | }
47 |
48 | [Category("Configuration")]
49 | [DisplayName("Multicast Group Address (Optional)")]
50 | public string Address
51 | {
52 | get { return _address; }
53 | set { _address = value; }
54 | }
55 |
56 | [Category("Configuration")]
57 | [DisplayName("Receive Buffer Size")]
58 | [DefaultValue(1310720)]
59 | public int BufferSize
60 | {
61 | get { return _bufferSize; }
62 | // UDP is not a reliable protocol. So increase the BufferSize to reduce the risk of lost packet.
63 | set { _bufferSize = Math.Max(1310720, value); }
64 | }
65 |
66 | bool _useRemoteIPAsNamespacePrefix;
67 | [Category("Configuration")]
68 | [DisplayName("Use Remote IP As Namespace Prefix.")]
69 | [DefaultValue(false)]
70 | public bool UseRemoteIPAsNamespacePrefix
71 | {
72 | get { return _useRemoteIPAsNamespacePrefix; }
73 | set { _useRemoteIPAsNamespacePrefix = value; }
74 | }
75 |
76 | #region IReceiver Members
77 |
78 | [Browsable(false)]
79 | public override string SampleClientConfig
80 | {
81 | get
82 | {
83 | return
84 | @"Notice!
85 | UDP is not a reliable protocol.
86 | So recommend using AlanThinker.MyLog4net.TcpAppender.cs in the ExampleProject\TestLog4net project.
87 |
88 | Configuration for NLog:
89 |
90 |
91 | Configuration for log4net:
92 |
93 |
94 |
95 |
96 |
97 |
98 | ".Replace("'", "\"").Replace("\n", Environment.NewLine);
99 | }
100 | }
101 |
102 | public override void Initialize()
103 | {
104 | if ((_worker != null) && _worker.IsAlive)
105 | return;
106 |
107 | // Init connexion here, before starting the thread, to know the status now
108 | _remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
109 | _udpClient = _ipv6 ? new UdpClient(_port, AddressFamily.InterNetworkV6) : new UdpClient(_port);
110 | _udpClient.Client.ReceiveBufferSize = _bufferSize;
111 | if (!String.IsNullOrEmpty(_address))
112 | _udpClient.JoinMulticastGroup(IPAddress.Parse(_address));
113 | }
114 |
115 | public override void Start()
116 | {
117 | // We need a working thread
118 | _worker = new Thread(StartUdp);
119 | _worker.IsBackground = true;
120 | _worker.Start();
121 | }
122 |
123 | public override void Terminate()
124 | {
125 | if (_udpClient != null)
126 | {
127 | _udpClient.Close();
128 | _udpClient = null;
129 |
130 | _remoteEndPoint = null;
131 | }
132 |
133 | if ((_worker != null) && _worker.IsAlive)
134 | _worker.Abort();
135 | _worker = null;
136 | }
137 |
138 | #endregion
139 |
140 | public void Clear()
141 | {
142 | }
143 |
144 | private void StartUdp()
145 | {
146 | while ((_udpClient != null) && (_remoteEndPoint != null))
147 | {
148 | try
149 | {
150 | byte[] buffer = _udpClient.Receive(ref _remoteEndPoint);
151 | string loggingEvent = this.EncodingObject.GetString(buffer);
152 |
153 | //Console.WriteLine(loggingEvent);
154 | // Console.WriteLine("Count: " + count++);
155 |
156 | if (Notifiable == null)
157 | continue;
158 |
159 | LogMessage logMsg = ReceiverUtils.ParseLog4JXmlLogEvent(loggingEvent, "UdpLogger");
160 | if (_useRemoteIPAsNamespacePrefix)
161 | {
162 | logMsg.RootLoggerName = _remoteEndPoint.Address.ToString().Replace(".", "-");
163 | logMsg.LoggerName = string.Format("{0}_{1}", _remoteEndPoint.Address.ToString().Replace(".", "-"), logMsg.LoggerName);
164 | }
165 |
166 | if (Notifiable != null)
167 | Notifiable.Notify(logMsg);
168 | }
169 | catch (ThreadAbortException ex)
170 | {
171 | Utils.log.Error("StartUdp " + ex.Message);
172 | Thread.ResetAbort();
173 | break;
174 | }
175 | catch (Exception ex)
176 | {
177 | Utils.log.Error(ex.Message, ex);
178 | return;
179 | }
180 | }
181 | }
182 |
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/src/Log2Window/Receiver/WinDebugReceiver.cs:
--------------------------------------------------------------------------------
1 | //using System;
2 | //using System.ComponentModel;
3 | //using System.Diagnostics;
4 |
5 | //using CatchOutputDbg;
6 |
7 | //using Log2Window.Log;
8 |
9 |
10 | //namespace Log2Window.Receiver
11 | //{
12 | // [Serializable]
13 | // [DisplayName("WinDebug (OutputDebugString)")]
14 | // public class WinDebugReceiver : BaseReceiver
15 | // {
16 | // #region Overrides of BaseReceiver
17 |
18 | // [Browsable(false)]
19 | // public override string SampleClientConfig
20 | // {
21 | // get { return "N/A"; }
22 | // }
23 |
24 | // public override void Initialize()
25 | // {
26 | // DebugMonitor.OnOutputDebugString += DebugMonitor_OnOutputDebugString;
27 | // DebugMonitor.Start();
28 | // }
29 |
30 | // public override void Terminate()
31 | // {
32 | // DebugMonitor.OnOutputDebugString -= DebugMonitor_OnOutputDebugString;
33 | // DebugMonitor.Stop();
34 | // }
35 |
36 | // #endregion
37 |
38 |
39 | // void DebugMonitor_OnOutputDebugString(int pid, string text)
40 | // {
41 | // // Trim ending newline (if any)
42 | // if (text.EndsWith(Environment.NewLine))
43 | // text = text.Substring(0, text.Length - Environment.NewLine.Length);
44 |
45 | // // Replace dots by "middle dots" to preserve Logger namespace
46 | // string processName = GetProcessName(pid);
47 | // processName = processName.Replace('.', '·');
48 |
49 | // LogMessage logMsg = new LogMessage();
50 | // logMsg.Message = text;
51 | // logMsg.LoggerName = processName;
52 | // logMsg.LoggerName = String.Format("{0}.{1}", processName, pid);
53 | // logMsg.Level = LogLevels.Instance[LogLevel.Debug];
54 | // logMsg.ThreadName = pid.ToString();
55 | // logMsg.TimeStamp = DateTime.Now;
56 | // Notifiable.Notify(logMsg);
57 | // }
58 |
59 | // private static string GetProcessName(int pid)
60 | // {
61 | // if (pid == -1)
62 | // return Process.GetCurrentProcess().ProcessName;
63 | // try
64 | // {
65 | // return Process.GetProcessById(pid).ProcessName;
66 | // }
67 | // catch
68 | // {
69 | // return "";
70 | // }
71 | // }
72 | // }
73 | //}
74 |
--------------------------------------------------------------------------------
/src/Log2Window/Settings/FieldType.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: Log2Window.Settings.FieldType
3 | // Assembly: Log2Window, Version=9.9.9.9, Culture=neutral, PublicKeyToken=null
4 | // MVID: 44D35A25-C349-4FB9-B272-3AC90AA136EE
5 | // Assembly location: C:\Users\rwahl\Desktop\Log2Window.exe
6 |
7 | using Log2Window.Log;
8 | using System;
9 | using System.ComponentModel;
10 |
11 | namespace Log2Window.Settings
12 | {
13 | [Serializable]
14 | public class FieldType
15 | {
16 | ///
17 | /// Gets or sets the type of field.
18 | ///
19 | ///
20 | /// The field.
21 | ///
22 | [Category("Field Configuration")]
23 | [DisplayName("Field Type")]
24 | [Description("The Type of the Field")]
25 | public LogMessageField Field { get; set; }
26 |
27 | ///
28 | /// If the Field is of type Property, specify the name of the Property
29 | ///
30 | ///
31 | /// The property.
32 | ///
33 | [Category("Field Configuration")]
34 | [DisplayName("Property")]
35 | [Description("The Name of the Property")]
36 | public string Property { get; set; }
37 |
38 | ///
39 | /// The Display / Column name of the Field
40 | ///
41 | ///
42 | /// The name of the field.
43 | ///
44 | [Category("Field Configuration")]
45 | [DisplayName("Name")]
46 | [Description("The Name of the Column")]
47 | public string Name { get; set; }
48 |
49 | public FieldType()
50 | {
51 | }
52 |
53 | public FieldType(LogMessageField field, string name, string property = null)
54 | {
55 | Field = field;
56 | Name = name;
57 | Property = property;
58 | }
59 |
60 | public override string ToString()
61 | {
62 | return String.Format("{0}, {1}",Name,Property);
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/Log2Window/Settings/LayoutSettings.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: Log2Window.Settings.LayoutSettings
3 | // Assembly: Log2Window, Version=9.9.9.9, Culture=neutral, PublicKeyToken=null
4 | // MVID: 44D35A25-C349-4FB9-B272-3AC90AA136EE
5 | // Assembly location: C:\Users\rwahl\Desktop\Log2Window.exe
6 |
7 | using System;
8 | using System.Drawing;
9 | using System.Windows.Forms;
10 |
11 | namespace Log2Window.Settings
12 | {
13 | [Serializable]
14 | public sealed class LayoutSettings
15 | {
16 | public Rectangle WindowPosition { get; set; }
17 |
18 | public FormWindowState WindowState { get; set; }
19 |
20 | public bool ShowLogDetailView { get; set; }
21 |
22 | public Size LogDetailViewSize { get; set; }
23 |
24 | public bool ShowLoggerTree { get; set; }
25 |
26 | public Size LoggerTreeSize { get; set; }
27 |
28 | public int[] LogListViewColumnsWidths { get; set; }
29 |
30 | public void Set(Rectangle position, FormWindowState state, Control detailView, Control loggerTree)
31 | {
32 | this.WindowPosition = position;
33 | this.WindowState = state;
34 | this.ShowLogDetailView = detailView.Visible;
35 | this.LogDetailViewSize = detailView.Size;
36 | this.ShowLoggerTree = loggerTree.Visible;
37 | this.LoggerTreeSize = loggerTree.Size;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Log2Window/Settings/ReceiversForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Windows.Forms;
4 |
5 | using Log2Window.Receiver;
6 |
7 |
8 | namespace Log2Window.Settings
9 | {
10 | public partial class ReceiversForm : Form
11 | {
12 | public List AddedReceivers { get; protected set; }
13 | public List RemovedReceivers { get; protected set; }
14 | public List ModifiedReceivers { get; protected set; }
15 | public IReceiver SelectedReceiver { get; protected set; }
16 |
17 | public ReceiversForm(IEnumerable receivers)
18 | {
19 | AddedReceivers = new List();
20 | RemovedReceivers = new List();
21 | ModifiedReceivers = new List();
22 |
23 | InitializeComponent();
24 | removeReceiverBtn.Visible = true;
25 | this.receiverPropertyGrid.PropertyValueChanged += ReceiverPropertyGrid_PropertyValueChanged;
26 |
27 | Font = UserSettings.Instance.DefaultFont ?? Font;
28 |
29 | // Populate Receiver Types
30 | Dictionary receiverTypes = ReceiverFactory.Instance.ReceiverTypes;
31 | foreach (KeyValuePair kvp in receiverTypes)
32 | {
33 | ToolStripItem item = null;
34 | item = addReceiverCombo.DropDownItems.Add(kvp.Value.Name);
35 |
36 | if (item != null) item.Tag = kvp.Value;
37 | }
38 |
39 | // Populate Existing Receivers
40 | foreach (IReceiver receiver in receivers)
41 | AddReceiver(receiver);
42 | }
43 |
44 | private void ReceiverPropertyGrid_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
45 | {
46 | if (!this.AddedReceivers.Contains(this.SelectedReceiver)
47 | && !this.ModifiedReceivers.Contains(this.SelectedReceiver))
48 | {
49 | this.ModifiedReceivers.Add(this.SelectedReceiver);
50 | }
51 | }
52 |
53 | private void AddReceiver(IReceiver receiver)
54 | {
55 | string displayName = String.IsNullOrEmpty(receiver.DisplayName)
56 | ? ReceiverUtils.GetTypeDescription(receiver.GetType())
57 | : receiver.DisplayName;
58 | ListViewItem lvi = receiversListView.Items.Add(displayName);
59 | lvi.Tag = receiver;
60 | lvi.Selected = true;
61 | }
62 |
63 |
64 | private void addReceiverCombo_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
65 | {
66 | ReceiverFactory.ReceiverInfo info = e.ClickedItem.Tag as ReceiverFactory.ReceiverInfo;
67 | if (info != null)
68 | {
69 | // Instantiates a new receiver based on the selected type
70 | IReceiver receiver = ReceiverFactory.Instance.Create(info.Type.FullName);
71 |
72 | AddedReceivers.Add(receiver);
73 | AddReceiver(receiver);
74 | }
75 | }
76 |
77 | private void removeReceiverBtn_Click(object sender, EventArgs e)
78 | {
79 | IReceiver receiver = GetSelectedReceiver();
80 | if (receiver == null)
81 | return;
82 |
83 | DialogResult dr = MessageBox.Show(this, "Confirm Delete?", "Confirmation", MessageBoxButtons.YesNo,
84 | MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
85 | if (dr != DialogResult.Yes)
86 | return;
87 |
88 | receiversListView.Items.Remove(GetSelectedItem());
89 |
90 | if (AddedReceivers.Find(r => r == receiver) != null)
91 | AddedReceivers.Remove(receiver);
92 | else if (ModifiedReceivers.Find(r => r == receiver) != null)
93 | ModifiedReceivers.Remove(receiver);
94 | else
95 | RemovedReceivers.Add(receiver);
96 | }
97 |
98 | private void receiversListView_SelectedIndexChanged(object sender, EventArgs e)
99 | {
100 | IReceiver receiver = GetSelectedReceiver();
101 |
102 | removeReceiverBtn.Enabled = (receiver != null);
103 | receiverPropertyGrid.SelectedObject = receiver;
104 | if (receiver != null)
105 | {
106 | sampleClientConfigTextBox.Text = receiver.SampleClientConfig;
107 | SelectedReceiver = receiver;
108 | }
109 | }
110 |
111 | private ListViewItem GetSelectedItem()
112 | {
113 | if (receiversListView.SelectedItems.Count > 0)
114 | return receiversListView.SelectedItems[0];
115 | return null;
116 | }
117 |
118 | private IReceiver GetSelectedReceiver()
119 | {
120 | if (receiversListView.SelectedItems.Count <= 0)
121 | return null;
122 |
123 | ListViewItem lvi = GetSelectedItem();
124 | return (lvi == null) ? null : lvi.Tag as IReceiver;
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/Log2Window/Settings/ReceiversForm.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 |
121 | 17, 17
122 |
123 |
124 |
125 |
126 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
127 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
128 | YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
129 | 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
130 | bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
131 | VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
132 | c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
133 | Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
134 | mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
135 | kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
136 | TgDQASA1MVpwzwAAAABJRU5ErkJggg==
137 |
138 |
139 |
140 |
141 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
142 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
143 | YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
144 | 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
145 | bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
146 | VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
147 | c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
148 | Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
149 | mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
150 | kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
151 | TgDQASA1MVpwzwAAAABJRU5ErkJggg==
152 |
153 |
154 |
--------------------------------------------------------------------------------
/src/Log2Window/Settings/SettingsForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Log2Window.Settings
2 | {
3 | partial class SettingsForm
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.cancelBtn = new System.Windows.Forms.Button();
32 | this.okBtn = new System.Windows.Forms.Button();
33 | this.settingsPropertyGrid = new System.Windows.Forms.PropertyGrid();
34 | this.SuspendLayout();
35 | //
36 | // cancelBtn
37 | //
38 | this.cancelBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
39 | this.cancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
40 | this.cancelBtn.Location = new System.Drawing.Point(473, 515);
41 | this.cancelBtn.Name = "cancelBtn";
42 | this.cancelBtn.Size = new System.Drawing.Size(75, 23);
43 | this.cancelBtn.TabIndex = 0;
44 | this.cancelBtn.Text = "Cancel";
45 | this.cancelBtn.UseVisualStyleBackColor = true;
46 | //
47 | // okBtn
48 | //
49 | this.okBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
50 | this.okBtn.DialogResult = System.Windows.Forms.DialogResult.OK;
51 | this.okBtn.Location = new System.Drawing.Point(392, 515);
52 | this.okBtn.Name = "okBtn";
53 | this.okBtn.Size = new System.Drawing.Size(75, 23);
54 | this.okBtn.TabIndex = 0;
55 | this.okBtn.Text = "OK";
56 | this.okBtn.UseVisualStyleBackColor = true;
57 | //
58 | // settingsPropertyGrid
59 | //
60 | this.settingsPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
61 | | System.Windows.Forms.AnchorStyles.Left)
62 | | System.Windows.Forms.AnchorStyles.Right)));
63 | this.settingsPropertyGrid.Location = new System.Drawing.Point(12, 12);
64 | this.settingsPropertyGrid.Name = "settingsPropertyGrid";
65 | this.settingsPropertyGrid.Size = new System.Drawing.Size(536, 497);
66 | this.settingsPropertyGrid.TabIndex = 1;
67 | this.settingsPropertyGrid.ToolbarVisible = false;
68 | //
69 | // SettingsForm
70 | //
71 | this.AcceptButton = this.okBtn;
72 | this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
73 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
74 | this.CancelButton = this.cancelBtn;
75 | this.ClientSize = new System.Drawing.Size(560, 550);
76 | this.Controls.Add(this.settingsPropertyGrid);
77 | this.Controls.Add(this.okBtn);
78 | this.Controls.Add(this.cancelBtn);
79 | this.Name = "SettingsForm";
80 | this.ShowInTaskbar = false;
81 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
82 | this.Text = "Log2Window Settings";
83 | this.ResumeLayout(false);
84 |
85 | }
86 |
87 | #endregion
88 |
89 | private System.Windows.Forms.Button cancelBtn;
90 | private System.Windows.Forms.Button okBtn;
91 | private System.Windows.Forms.PropertyGrid settingsPropertyGrid;
92 | }
93 | }
--------------------------------------------------------------------------------
/src/Log2Window/Settings/SettingsForm.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Forms;
2 |
3 |
4 | namespace Log2Window.Settings
5 | {
6 | public partial class SettingsForm : Form
7 | {
8 | public SettingsForm(UserSettings userSettings)
9 | {
10 | InitializeComponent();
11 |
12 | Font = UserSettings.Instance.DefaultFont ?? Font;
13 |
14 | // UI Settings
15 | UserSettings = userSettings;
16 | }
17 |
18 | public UserSettings UserSettings
19 | {
20 | get { return settingsPropertyGrid.SelectedObject as UserSettings; }
21 | set
22 | {
23 | settingsPropertyGrid.SelectedObject = value;
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/Log2Window/Settings/SettingsForm.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=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/src/Log2Window/Settings/SourceFileLocation.cs:
--------------------------------------------------------------------------------
1 | // Decompiled with JetBrains decompiler
2 | // Type: Log2Window.Settings.SourceFileLocation
3 | // Assembly: Log2Window, Version=9.9.9.9, Culture=neutral, PublicKeyToken=null
4 | // MVID: 44D35A25-C349-4FB9-B272-3AC90AA136EE
5 | // Assembly location: C:\Users\rwahl\Desktop\Log2Window.exe
6 |
7 | using System;
8 | using System.ComponentModel;
9 |
10 | namespace Log2Window.Settings
11 | {
12 | [Serializable]
13 | public class SourceFileLocation
14 | {
15 | [DisplayName("Log File Source Code Path")]
16 | [Description("The Base Path of the Source Code in the Log File")]
17 | [Category("Source Location Mapping")]
18 | public string LogSource { get; set; }
19 |
20 | [Description("The Base Path of the Source Code on the Local Computer")]
21 | [Category("Source Location Mapping")]
22 | [DisplayName("Local Source Code Path")]
23 | public string LocalSource { get; set; }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Log2Window/Settings/UserSettings.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/Settings/UserSettings.cs
--------------------------------------------------------------------------------
/src/Log2Window/UI/AutoWaitCursor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using System.Windows.Forms;
4 |
5 |
6 | namespace Log2Window.UI
7 | {
8 | ///
9 | /// Auto Wait Cursor utility class.
10 | /// Usage:
11 | /// using (new AutoWaitCursor())
12 | /// { ...long task... }
13 | ///
14 | public sealed class AutoWaitCursor : IDisposable
15 | {
16 | public AutoWaitCursor()
17 | {
18 | Enabled = true;
19 | }
20 |
21 | public void Dispose()
22 | {
23 | Enabled = false;
24 | }
25 |
26 | public static bool Enabled
27 | {
28 | get { return Application.UseWaitCursor; }
29 | set
30 | {
31 | if (value == Application.UseWaitCursor) return;
32 | Application.UseWaitCursor = value;
33 |
34 | var f = Form.ActiveForm;
35 | if (f != null && f.Visible && f.Handle != IntPtr.Zero) // Send WM_SETCURSOR
36 | SendMessage(f.Handle, 0x20, f.Handle, (IntPtr)1);
37 | }
38 | }
39 |
40 | [DllImport("user32.dll")]
41 | private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Log2Window/UI/ControlExtenders/DockExtender.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007 Herre Kuijpers -
2 | //
3 | // This source file(s) may be redistributed, altered and customized
4 | // by any means PROVIDING the authors name and all copyright
5 | // notices remain intact.
6 | // THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
7 | // EXPRESS OR IMPLIED. USE IT AT YOUR OWN RISK. THE AUTHOR ACCEPTS NO
8 | // LIABILITY FOR ANY DATA DAMAGE/LOSS THAT THIS PRODUCT MAY CAUSE.
9 | //-----------------------------------------------------------------------
10 | using System;
11 | using System.Collections.Generic;
12 | using System.Windows.Forms;
13 | using System.Drawing;
14 |
15 | namespace ControlExtenders
16 | {
17 | internal struct DockState
18 | {
19 | ///
20 | /// the docking control (usually a container class, e.g Panel)
21 | ///
22 | public ScrollableControl Container;
23 | ///
24 | /// handle of the container that the user can use to select and move the container
25 | ///
26 | public Control Handle;
27 |
28 | ///
29 | /// splitter that is attached to this panel for resizing.
30 | /// this is optional
31 | ///
32 | public Splitter Splitter;
33 |
34 | ///
35 | /// the parent of the container
36 | ///
37 | public Control OrgDockingParent;
38 |
39 | ///
40 | /// the base docking host that contains all docking panels
41 | ///
42 | public Control OrgDockHost;
43 |
44 | ///
45 | /// the origional docking style, stored in order to reset the state
46 | ///
47 | public DockStyle OrgDockStyle;
48 |
49 | ///
50 | /// the origional bounds of the container
51 | ///
52 | public Rectangle OrgBounds;
53 |
54 | }
55 |
56 | public sealed class DockExtender
57 | {
58 | private Control _dockHost;
59 | private Floaties _floaties;
60 |
61 | // this is the blue overlay that presents a preview how the control will be docked
62 | internal Overlay Overlay = new Overlay();
63 |
64 |
65 | public Floaties Floaties
66 | {
67 | get { return _floaties; }
68 | }
69 |
70 | public DockExtender(Control dockHost)
71 | {
72 | _dockHost = dockHost;
73 | _floaties = new Floaties();
74 | }
75 |
76 | ///
77 | /// display the container control that is either floating or docked
78 | ///
79 | ///
80 | public void Show(Control container)
81 | {
82 | IFloaty f = _floaties.Find(container);
83 | if (f != null) f.Show();
84 | }
85 |
86 | ///
87 | /// this will gracefully hide the container control
88 | /// making sure that the floating window is also closed
89 | ///
90 | ///
91 | public void Hide(Control container)
92 | {
93 | IFloaty f = _floaties.Find(container);
94 | if (f != null) f.Hide();
95 | }
96 |
97 | ///
98 | /// Attach a container control and use it as a grip hande. The container must support mouse move events.
99 | ///
100 | /// container to make dockable/floatable
101 | /// the floaty that manages the container's behaviour
102 | public IFloaty Attach(ScrollableControl container)
103 | {
104 | return Attach(container, container, null);
105 | }
106 |
107 | ///
108 | /// Attach a container and a grip handle. The handle must support mouse move events.
109 | ///
110 | /// container to make dockable/floatable
111 | /// grip handle used to drag the container
112 | /// the floaty that manages the container's behaviour
113 | public IFloaty Attach(ScrollableControl container, Control handle)
114 | {
115 | return Attach(container, handle, null);
116 | }
117 |
118 | ///
119 | /// attach this class to any dockable type of container control
120 | /// to make it dockable.
121 | /// Attach a container control and use it as a grip hande. The handle must support mouse move events.
122 | /// Supply a splitter control to allow resizing of the docked container
123 | ///
124 | /// control to be dockable
125 | /// handle to be used to track the mouse movement (e.g. caption of the container)
126 | /// splitter to resize the docked container (optional)
127 | public IFloaty Attach(ScrollableControl container, Control handle, Splitter splitter)
128 | {
129 | if (container == null) throw new ArgumentException("container cannot be null");
130 | if (handle == null) throw new ArgumentException("handle cannot be null");
131 |
132 | DockState _dockState = new DockState();
133 | _dockState.Container = container;
134 | _dockState.Handle = handle;
135 | _dockState.OrgDockHost = _dockHost;
136 | _dockState.Splitter = splitter;
137 |
138 | Floaty floaty = new Floaty(this);
139 | floaty.Attach(_dockState);
140 | _floaties.Add(floaty);
141 | return floaty;
142 | }
143 |
144 | // finds the potential dockhost control at the specified location
145 | internal Control FindDockHost(Floaty floaty , Point pt)
146 | {
147 | Control c = null;
148 | if (FormIsHit(floaty.DockState.OrgDockHost, pt))
149 | c = floaty.DockState.OrgDockHost; //assume toplevel control
150 |
151 | if (floaty.DockOnHostOnly)
152 | return c;
153 |
154 | foreach (Floaty f in Floaties)
155 | {
156 | if (f.DockState.Container.Visible && FormIsHit(f.DockState.Container, pt))
157 | {
158 | // add this line to dissallow docking inside floaties
159 | //if (f.Visible) continue;
160 |
161 | c = f.DockState.Container; // found suitable floating form
162 | break;
163 | }
164 | }
165 | return c;
166 | }
167 |
168 | // finds the potential dockhost control at the specified location
169 | internal bool FormIsHit(Control c, Point pt)
170 | {
171 | if (c == null) return false;
172 |
173 | Point pc = c.PointToClient(pt);
174 | bool hit = c.ClientRectangle.IntersectsWith(new Rectangle(pc, new Size(1, 1))); //.TopLevelControl; // this is tricky
175 | return hit;
176 | }
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/src/Log2Window/UI/ControlExtenders/Overlay.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007 Herre Kuijpers -
2 | //
3 | // This source file(s) may be redistributed, altered and customized
4 | // by any means PROVIDING the authors name and all copyright
5 | // notices remain intact.
6 | // THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
7 | // EXPRESS OR IMPLIED. USE IT AT YOUR OWN RISK. THE AUTHOR ACCEPTS NO
8 | // LIABILITY FOR ANY DATA DAMAGE/LOSS THAT THIS PRODUCT MAY CAUSE.
9 | //-----------------------------------------------------------------------
10 | using System;
11 | using System.Collections.Generic;
12 | using System.ComponentModel;
13 | using System.Text;
14 | using System.Windows.Forms;
15 |
16 | namespace ControlExtenders
17 | {
18 | ///
19 | /// this is the overlay preview control
20 | ///
21 | internal sealed class Overlay : Form
22 | {
23 | public Overlay()
24 | {
25 | InitializeComponent();
26 | }
27 |
28 | // override Dockstate.
29 | public new DockStyle Dock;
30 | public Control DockHostControl;
31 |
32 | ///
33 | /// Required designer variable.
34 | ///
35 | private IContainer components = null;
36 |
37 | ///
38 | /// Clean up any resources being used.
39 | ///
40 | /// true if managed resources should be disposed; otherwise, false.
41 | protected override void Dispose(bool disposing)
42 | {
43 | if (disposing && (components != null))
44 | {
45 | components.Dispose();
46 | }
47 | base.Dispose(disposing);
48 | }
49 |
50 | #region Windows Form Designer generated code
51 |
52 | ///
53 | /// Required method for Designer support - do not modify
54 | /// the contents of this method with the code editor.
55 | ///
56 | private void InitializeComponent()
57 | {
58 | this.SuspendLayout();
59 | //
60 | // Overlay
61 | //
62 | this.BackColor = System.Drawing.SystemColors.ActiveCaption;
63 | this.ControlBox = false;
64 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
65 | this.MaximizeBox = false;
66 | this.MinimizeBox = false;
67 | this.Name = "Overlay";
68 | this.Opacity = 0.3;
69 | this.ShowIcon = false;
70 | this.ShowInTaskbar = false;
71 | this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
72 | this.Text = "Overlay";
73 | this.ResumeLayout(false);
74 | }
75 |
76 | #endregion
77 | }
78 | }
--------------------------------------------------------------------------------
/src/Log2Window/UI/FlickerFreeListView.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Forms;
2 |
3 |
4 | namespace Log2Window.UI
5 | {
6 | class FlickerFreeListView : ListView
7 | {
8 | public FlickerFreeListView()
9 | {
10 | // Activate double buffering
11 | SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.CacheText, true);
12 |
13 | // Enable the OnNotifyMessage event so we get a chance to filter out
14 | // Windows messages before they get to the form's WndProc
15 | SetStyle(ControlStyles.EnableNotifyMessage, false);
16 | }
17 |
18 | protected override void OnNotifyMessage(Message m)
19 | {
20 | // Filter out the WM_ERASEBKGND message
21 | if (m.Msg != 0x14)
22 | {
23 | base.OnNotifyMessage(m);
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/Log2Window/UI/ToolStripControl.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Windows.Forms;
4 |
5 |
6 | namespace Log2Window.UI
7 | {
8 | public class ToolStripControl : ToolStripControlHost
9 | where T : Control, new()
10 | {
11 | public ToolStripControl() : base(new T())
12 | {
13 | }
14 |
15 | public T CoreControl
16 | {
17 | get
18 | {
19 | return Control as T;
20 | }
21 | }
22 |
23 | /*
24 | public override Size GetPreferredSize(Size constrainingSize)
25 | {
26 | // Use the default size if the text box is on the overflow menu
27 | // or is on a vertical ToolStrip.
28 | if (IsOnOverflow || Owner.Orientation == Orientation.Vertical)
29 | {
30 | return DefaultSize;
31 | }
32 |
33 | // Declare a variable to store the total available width as
34 | // it is calculated, starting with the display width of the
35 | // owning ToolStrip.
36 | Int32 width = Owner.DisplayRectangle.Width;
37 |
38 | // Subtract the width of the overflow button if it is displayed.
39 | if (Owner.OverflowButton.Visible)
40 | {
41 | width = width - Owner.OverflowButton.Width -
42 | Owner.OverflowButton.Margin.Horizontal;
43 | }
44 |
45 | // Declare a variable to maintain a count of ToolStripControl
46 | // items currently displayed in the owning ToolStrip.
47 | Int32 springBoxCount = 0;
48 |
49 | foreach (ToolStripItem item in Owner.Items)
50 | {
51 | // Ignore items on the overflow menu.
52 | if (item.IsOnOverflow) continue;
53 |
54 | if (item is ToolStripControl)
55 | {
56 | // For ToolStripControl items, increment the count and
57 | // subtract the margin width from the total available width.
58 | springBoxCount++;
59 | width -= item.Margin.Horizontal;
60 | }
61 | else
62 | {
63 | // For all other items, subtract the full width from the total
64 | // available width.
65 | width = width - item.Width - item.Margin.Horizontal;
66 | }
67 | }
68 |
69 | // If there are multiple ToolStripControl items in the owning
70 | // ToolStrip, divide the total available width between them.
71 | if (springBoxCount > 1) width /= springBoxCount;
72 |
73 | // If the available width is less than the default width, use the
74 | // default width, forcing one or more items onto the overflow menu.
75 | if (width < DefaultSize.Width) width = DefaultSize.Width;
76 |
77 | // Retrieve the preferred size from the base class, but change the
78 | // width to the calculated width.
79 | Size size = base.GetPreferredSize(constrainingSize);
80 | size.Width = width;
81 | return size;
82 | }
83 | */
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/Log2Window/UI/TreeViewLoggerView.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/UI/TreeViewLoggerView.cs
--------------------------------------------------------------------------------
/src/Log2Window/UI/TreeViewWithoutDoubleClick.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows.Forms;
6 |
7 | namespace Log2Window.UI
8 | {
9 | //fix bug of treeview with checkbox.
10 | //http://stackoverflow.com/questions/17356976/treeview-with-checkboxes-not-processing-clicks-correctly
11 | class TreeViewWithoutDoubleClick : TreeView
12 | {
13 | protected override void WndProc(ref Message m)
14 | {
15 | if (m.Msg == 0x203) // identified double click
16 | {
17 | var localPos = PointToClient(Cursor.Position);
18 | var hitTestInfo = HitTest(localPos);
19 | if (hitTestInfo.Location == TreeViewHitTestLocations.StateImage)
20 | m.Result = IntPtr.Zero;
21 | else
22 | base.WndProc(ref m);
23 | }
24 | else base.WndProc(ref m);
25 | }
26 | }
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/src/Log2Window/Utils.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/Utils.cs
--------------------------------------------------------------------------------
/src/Log2Window/res/Excel.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/Excel.ico
--------------------------------------------------------------------------------
/src/Log2Window/res/Go16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/Go16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/Pause16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/Pause16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/back16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/back16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/backward16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/backward16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/burn16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/burn16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/cd16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/cd16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/close16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/close16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/collapse_all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/collapse_all.png
--------------------------------------------------------------------------------
/src/Log2Window/res/configure16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/configure16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/delete16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/delete16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/deletefile16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/deletefile16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/documentsorcopy16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/documentsorcopy16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/eventLog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/eventLog.png
--------------------------------------------------------------------------------
/src/Log2Window/res/find16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/find16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/forward16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/forward16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/gotoapp16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/gotoapp16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/infoabout16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/infoabout16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/movefile16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/movefile16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/next16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/next16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/pin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/pin.png
--------------------------------------------------------------------------------
/src/Log2Window/res/receive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/receive.png
--------------------------------------------------------------------------------
/src/Log2Window/res/saveas16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/saveas16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/unselect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/unselect.png
--------------------------------------------------------------------------------
/src/Log2Window/res/window16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/window16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/windowb.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/windowb.ico
--------------------------------------------------------------------------------
/src/Log2Window/res/zoomin16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/zoomin16.png
--------------------------------------------------------------------------------
/src/Log2Window/res/zoomout16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/Log2Window/res/zoomout16.png
--------------------------------------------------------------------------------
/src/TestLog4net/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/TestLog4net/Config/log4net.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
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 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
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 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/src/TestLog4net/MsmqAppender.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/TestLog4net/MsmqAppender.cs
--------------------------------------------------------------------------------
/src/TestLog4net/MyXmlLayoutSchemaLog4j.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Xml;
6 | using log4net.Core;
7 | using log4net.Util;
8 |
9 | namespace AlanThinker.MyLog4net
10 | {
11 | ///
12 | /// SimpleXmlLayoutSchemaLog4j which without hostname, appdomain name, identity name, user name, ndcObj and properties.
13 | /// So have better performance.
14 | ///
15 | class MyXmlLayoutSchemaLog4j : log4net.Layout.XmlLayoutSchemaLog4j
16 | {
17 | private static readonly DateTime s_date1970 = new DateTime(1970, 1, 1);
18 |
19 | #region Some switch which can cause performance issue.
20 |
21 | public bool Show_Hostname_Appdomain_Identity_UserName { get; set; }
22 | public bool ShowNDC { get; set; }
23 | public bool ShowProperties { get; set; }
24 | //设置logName的命名空间前缀, 这样log2window收到多个来源的日志, 就可以很方便的通过前缀来区分了.
25 | public string NamespacePrefix { get; set; }
26 |
27 | #endregion
28 |
29 | protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent)
30 | {
31 | //// Translate logging events for log4j
32 |
33 | if (this.Show_Hostname_Appdomain_Identity_UserName)
34 | {
35 | // Translate hostname property
36 | if (loggingEvent.LookupProperty(LoggingEvent.HostNameProperty) != null &&
37 | loggingEvent.LookupProperty("log4jmachinename") == null)
38 | {
39 | loggingEvent.GetProperties()["log4jmachinename"] = loggingEvent.LookupProperty(LoggingEvent.HostNameProperty);
40 | }
41 |
42 | // translate appdomain name
43 | if (loggingEvent.LookupProperty("log4japp") == null &&
44 | loggingEvent.Domain != null &&
45 | loggingEvent.Domain.Length > 0)
46 | {
47 | loggingEvent.GetProperties()["log4japp"] = loggingEvent.Domain;
48 | }
49 |
50 | // translate identity name
51 | if (loggingEvent.Identity != null &&
52 | loggingEvent.Identity.Length > 0 &&
53 | loggingEvent.LookupProperty(LoggingEvent.IdentityProperty) == null)
54 | {
55 | loggingEvent.GetProperties()[LoggingEvent.IdentityProperty] = loggingEvent.Identity;
56 | }
57 |
58 | // translate user name
59 | if (loggingEvent.UserName != null &&
60 | loggingEvent.UserName.Length > 0 &&
61 | loggingEvent.LookupProperty(LoggingEvent.UserNameProperty) == null)
62 | {
63 | loggingEvent.GetProperties()[LoggingEvent.UserNameProperty] = loggingEvent.UserName;
64 | }
65 | }
66 |
67 | // Write the start element
68 | writer.WriteStartElement("log4j:event");
69 | var newLogName = loggingEvent.LoggerName;
70 | if (!string.IsNullOrEmpty(NamespacePrefix))
71 | {
72 | newLogName = NamespacePrefix + "." + newLogName;
73 | }
74 | writer.WriteAttributeString("logger", newLogName);
75 |
76 | // Calculate the timestamp as the number of milliseconds since january 1970
77 | //
78 | // We must convert the TimeStamp to UTC before performing any mathematical
79 | // operations. This allows use to take into account discontinuities
80 | // caused by daylight savings time transitions.
81 | TimeSpan timeSince1970 = loggingEvent.TimeStamp.ToUniversalTime() - s_date1970;
82 |
83 | writer.WriteAttributeString("timestamp", XmlConvert.ToString((long)timeSince1970.TotalMilliseconds));
84 | writer.WriteAttributeString("level", loggingEvent.Level.DisplayName);
85 | writer.WriteAttributeString("thread", loggingEvent.ThreadName);
86 |
87 | // Append the message text
88 | writer.WriteStartElement("log4j:message");
89 | Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage, this.InvalidCharReplacement);
90 | writer.WriteEndElement();
91 |
92 | if (this.ShowNDC)
93 | {
94 | object ndcObj = loggingEvent.LookupProperty("NDC");
95 | if (ndcObj != null)
96 | {
97 | string valueStr = loggingEvent.Repository.RendererMap.FindAndRender(ndcObj);
98 |
99 | if (valueStr != null && valueStr.Length > 0)
100 | {
101 | // Append the NDC text
102 | writer.WriteStartElement("log4j:NDC");
103 | Transform.WriteEscapedXmlString(writer, valueStr, this.InvalidCharReplacement);
104 | writer.WriteEndElement();
105 | }
106 | }
107 | }
108 |
109 | // Append the properties text
110 |
111 | if (this.ShowProperties)
112 | {
113 | PropertiesDictionary properties = loggingEvent.GetProperties();
114 | if (properties.Count > 0)
115 | {
116 | writer.WriteStartElement("log4j:properties");
117 | foreach (System.Collections.DictionaryEntry entry in properties)
118 | {
119 | writer.WriteStartElement("log4j:data");
120 | writer.WriteAttributeString("name", (string)entry.Key);
121 |
122 | // Use an ObjectRenderer to convert the object to a string
123 | string valueStr = loggingEvent.Repository.RendererMap.FindAndRender(entry.Value);
124 | writer.WriteAttributeString("value", valueStr);
125 |
126 | writer.WriteEndElement();
127 | }
128 | writer.WriteEndElement();
129 | }
130 | }
131 |
132 | string exceptionStr = loggingEvent.GetExceptionString();
133 | if (exceptionStr != null && exceptionStr.Length > 0)
134 | {
135 | // Append the stack trace line
136 | writer.WriteStartElement("log4j:throwable");
137 | Transform.WriteEscapedXmlString(writer, exceptionStr, this.InvalidCharReplacement);
138 | writer.WriteEndElement();
139 | }
140 |
141 | if (LocationInfo)
142 | {
143 | LocationInfo locationInfo = loggingEvent.LocationInformation;
144 |
145 | writer.WriteStartElement("log4j:locationInfo");
146 | writer.WriteAttributeString("class", locationInfo.ClassName);
147 | writer.WriteAttributeString("method", locationInfo.MethodName);
148 | writer.WriteAttributeString("file", locationInfo.FileName);
149 | writer.WriteAttributeString("line", locationInfo.LineNumber);
150 | writer.WriteEndElement();
151 | }
152 |
153 | writer.WriteEndElement();
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/src/TestLog4net/Program.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanthinker/Log2Window/f40235b8979b92d8438f768d870f8e7645e4a6bb/src/TestLog4net/Program.cs
--------------------------------------------------------------------------------
/src/TestLog4net/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("Test")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Test")]
13 | [assembly: AssemblyCopyright("")]
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("7bf73781-a136-488c-8984-a3b60d361846")]
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 | [assembly: AssemblyVersion("1.0.0.0")]
33 | [assembly: AssemblyFileVersion("1.0.0.0")]
34 |
--------------------------------------------------------------------------------
/src/TestLog4net/TestLog4net.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 9.0.30729
7 | 2.0
8 | {29A745D4-5A2F-4170-A0F1-54C77F151892}
9 | Exe
10 | Properties
11 | Test
12 | Test
13 | .
14 | https://tfs.codeplex.com/tfs/tfs04
15 | {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
16 |
17 |
18 | 3.5
19 |
20 |
21 | v4.5.1
22 | publish\
23 | true
24 | Disk
25 | false
26 | Foreground
27 | 7
28 | Days
29 | false
30 | false
31 | true
32 | 0
33 | 1.0.0.%2a
34 | false
35 | false
36 | true
37 |
38 |
39 |
40 | true
41 | full
42 | false
43 | bin\Debug\
44 | TRACE;DEBUG
45 | prompt
46 | 4
47 | AllRules.ruleset
48 | true
49 | false
50 |
51 |
52 | pdbonly
53 | true
54 | bin\Release\
55 | TRACE
56 | prompt
57 | 4
58 | AllRules.ruleset
59 | false
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | Designer
77 |
78 |
79 | Always
80 | Designer
81 |
82 |
83 |
84 |
85 | False
86 | .NET Framework 3.5 SP1 Client Profile
87 | false
88 |
89 |
90 | False
91 | .NET Framework 3.5 SP1
92 | true
93 |
94 |
95 | False
96 | Windows Installer 3.1
97 | true
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | 2.0.10
106 |
107 |
108 |
109 |
116 |
--------------------------------------------------------------------------------
/src/TestNLog/NLog.config:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/TestNLog/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using NLog;
3 | using TestNLog.Company.Product.BusinessLogic;
4 | using TestNLog.Company.Product.ServiceTester;
5 | namespace TestNLog
6 | {
7 | class Program
8 | {
9 | static readonly Logger _log = LogManager.GetCurrentClassLogger();
10 |
11 | static void Main(string[] args)
12 | {
13 | ////if (!EventLog.SourceExists("log4net"))
14 | ////{
15 | //// //An event log source should not be created and immediately used.
16 | //// //There is a latency time to enable the source, it should be created
17 | //// //prior to executing the application that uses the source.
18 | //// //Execute this sample a second time to use the new source.
19 | //// EventLog.CreateEventSource("log4net", "Application");
20 | ////}
21 |
22 | ConsoleKeyInfo key = new ConsoleKeyInfo();
23 | while (key.Key != ConsoleKey.X)
24 | {
25 |
26 | DoLog(key.KeyChar);
27 |
28 |
29 | DoWinDebug();
30 | key = Console.ReadKey();
31 | }
32 | }
33 |
34 | static void DoWinDebug()
35 | {
36 | //Console.WriteLine("Begin Doing WinDebug!");
37 | //System.Diagnostics.Debug.WriteLine("This is a call to System.Diagnostics.Debug");
38 | //System.Diagnostics.Trace.WriteLine("This is a call to System.Diagnostics.Trace");
39 | //Console.WriteLine("End Doing WinDebug!");
40 | }
41 |
42 | static void DoLog(char keyChar)
43 | {
44 | Console.WriteLine("\nBegin Doing Log!");
45 | Console.WriteLine(DateTime.Now);
46 | if (Char.ToLower(keyChar) == 'b')
47 | {
48 | for (int i = 0; i < 10000; i++)
49 | {
50 | _log.Info(i);
51 | }
52 | }
53 | else if (keyChar >= '1' && keyChar <= '9')
54 | {
55 | _log.Info(keyChar);
56 | }
57 | else if (Char.ToLower(keyChar) == 'e')
58 | {
59 | try
60 | {
61 | ThrowTestEx();
62 | return;
63 | }
64 | catch (Exception ex)
65 | {
66 | _log.Error("TestEx", ex);
67 | }
68 | }
69 | else if (Char.ToLower(keyChar) == 'c')
70 | {
71 | for (int i = 0; i < 10; i++)
72 | {
73 | _log.Info("测试中文");
74 | }
75 | }
76 | else
77 | {
78 | if (_log.IsErrorEnabled)
79 | _log.Error("This is an Error...");
80 |
81 | if (_log.IsDebugEnabled)
82 | for (int i = 0; i < 10; i++)
83 | _log.Debug("This is a simple log!");
84 |
85 | if (_log.IsErrorEnabled)
86 | _log.Error("This is an Error...");
87 |
88 | if (_log.IsInfoEnabled)
89 | _log.Info("This is an Info...");
90 |
91 |
92 | _log.Warn("This is a Warning...");
93 | _log.Fatal("This is a Fatal...");
94 |
95 | _log.Error("This is an error with an exception.", new Exception("The message exception here."));
96 |
97 | _log.Warn("This is a message on many lines...\nlines...\nlines...\nlines...");
98 | _log.Warn("This is a message on many lines...\r\nlines...\r\nlines...\r\nlines...");
99 |
100 | DummyManager dm = new DummyManager();
101 | dm.DoIt();
102 |
103 | DummyTester dt = new DummyTester();
104 | dt.DoIt();
105 | }
106 |
107 | Console.WriteLine("End Doing Log!");
108 | }
109 |
110 | private static void ThrowTestEx()
111 | {
112 | throw new Exception("TestEx");
113 | }
114 |
115 | }
116 |
117 | namespace Company.Product.BusinessLogic
118 | {
119 |
120 | public class DummyManager
121 | {
122 | public static readonly Logger Log = LogManager.GetCurrentClassLogger();
123 |
124 |
125 | public DummyManager()
126 | {
127 | if (Log.IsInfoEnabled)
128 | Log.Info("Dummy Manager ctor");
129 | }
130 |
131 | public void DoIt()
132 | {
133 | if (Log.IsDebugEnabled)
134 | Log.Debug("DM: Do It, Do It Now!!");
135 |
136 | Log.Warn("This is a Warning from DM...");
137 | Log.Error("This is an Error from DM...");
138 | Log.Fatal("This is a Fatal from DM...");
139 |
140 | Log.ErrorException("This is an error from DM with an exception.", new Exception("The message exception here."));
141 | }
142 | }
143 | }
144 |
145 | namespace Company.Product.ServiceTester
146 | {
147 |
148 | public class DummyTester
149 | {
150 | public static readonly Logger Log = LogManager.GetCurrentClassLogger();
151 |
152 | public DummyTester()
153 | {
154 | if (Log.IsInfoEnabled)
155 | Log.Info("Dummy Tester ctor");
156 | }
157 |
158 | public void DoIt()
159 | {
160 | if (Log.IsDebugEnabled)
161 | Log.Debug("DT: Do It, Do It Now!!");
162 |
163 | Log.Warn("This is a Warning from DT...");
164 | Log.Error("This is an Error from DT...");
165 | Log.Fatal("This is a Fatal from DT...");
166 |
167 | Log.ErrorException("This is an error from DT with an exception.", new Exception("The message exception here."));
168 | }
169 | }
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/src/TestNLog/TestNLog.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {7C4E8E11-81E3-4297-A4D9-6F6DB90C8EF7}
9 | Exe
10 | Properties
11 | TestNLog
12 | TestNLog
13 | v4.5.1
14 |
15 |
16 | 512
17 |
18 |
19 | true
20 | bin\Debug\
21 | DEBUG;TRACE
22 | full
23 | AnyCPU
24 | bin\Debug\TestNLog.exe.CodeAnalysisLog.xml
25 | true
26 | GlobalSuppressions.cs
27 | prompt
28 | MinimumRecommendedRules.ruleset
29 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
30 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
31 | true
32 | false
33 |
34 |
35 | bin\Release\
36 | TRACE
37 | true
38 | pdbonly
39 | AnyCPU
40 | bin\Release\TestNLog.exe.CodeAnalysisLog.xml
41 | true
42 | GlobalSuppressions.cs
43 | prompt
44 | MinimumRecommendedRules.ruleset
45 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
46 | true
47 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
48 | true
49 | false
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | PreserveNewest
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | 4.3.10
69 |
70 |
71 |
72 |
79 |
--------------------------------------------------------------------------------
/src/TestNLog/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/script_Publish.sh:
--------------------------------------------------------------------------------
1 |
2 | ####################### 引用common #######################
3 | source "/mnt/d/Projects/XxcProjects/ShellScript/common.sh"
4 |
5 | ####################### 初始化 #######################
6 | # 当前目录被定义在 $startScriptDir 中
7 | alanInit
8 | mydir=$startScriptDir
9 |
10 | ####################### #######################
11 | readVarFromNT msbuild
12 | toBashPath msbuild
13 | "$msbuild"
14 |
15 | if [ "$msbuild" == "" ] ; then
16 | showErrorAndExit "系统环境变量msbuild必须设置到MSBuild.exe的路径"
17 | fi
18 |
19 | rm -rf /mnt/d/temp/Log2Window
20 | checkIfActionError "清空目录出错 $LINENO"
21 | rm -f /mnt/d/temp/Log2Window.zip
22 | checkIfActionError "删除文件出错 $LINENO"
23 |
24 | mkdir -p /mnt/d/temp/Log2Window
25 | mkdir -p /mnt/d/temp/Log2Window/ExampleProject
26 | "$msbuild" \
27 | /t:rebuild \
28 | /property:OutputPath=d:/temp/Log2Window \
29 | /property:Configuration=Release \
30 | /property:DeployOnBuild=true \
31 | "Log2Window\Log2Window.csproj"
32 | checkIfActionError "编译出错"
33 |
34 | cp -rf TestLog4net /mnt/d/temp/Log2Window/ExampleProject
35 | checkIfActionError "出错 $LINENO"
36 | cp -rf TestNLog /mnt/d/temp/Log2Window/ExampleProject
37 | checkIfActionError "出错 $LINENO"
38 |
39 | find /mnt/d/temp/Log2Window/ExampleProject -name "bin" -exec rm -rf {} \;
40 | find /mnt/d/temp/Log2Window/ExampleProject -name "obj" -exec rm -rf {} \;
41 | find /mnt/d/temp/Log2Window/ExampleProject -name "packages" -exec rm -rf {} \;
42 |
43 | mkdir /mnt/d/temp/Log2Window/bin
44 | mv /mnt/d/temp/Log2Window/*.dll /mnt/d/temp/Log2Window/bin
45 | mv /mnt/d/temp/Log2Window/*.xml /mnt/d/temp/Log2Window/bin
46 |
47 | cd /mnt/d/temp
48 | zip -r Log2Window.zip Log2Window
49 | checkIfActionError "压缩出错"
50 | cp -af /mnt/d/temp/Log2Window/. "/mnt/d/Users/Alan/Documents/YunPan/Program Files/Log2Window"
51 | cp -f "/mnt/d/Temp/Log2Window.zip" "/mnt/d/Users/Alan/Documents/YunPan/Program Files"
52 | checkIfActionError "出错 $LINENO"
53 | showInfo 全部完成.
54 |
55 | read temp
--------------------------------------------------------------------------------