mirror of
https://github.com/yaakov-h/Notepad.Extensions.Logging.git
synced 2024-11-22 11:14:50 +00:00
Remove statics and threadstatic so that we can pass options around
This commit is contained in:
parent
b817c75720
commit
c658b437b5
9 changed files with 143 additions and 80 deletions
7
Notepad.Extensions.Logging/IWindowFinder.cs
Normal file
7
Notepad.Extensions.Logging/IWindowFinder.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Notepad.Extensions.Logging
|
||||||
|
{
|
||||||
|
interface IWindowFinder
|
||||||
|
{
|
||||||
|
WindowInfo FindNotepadWindow();
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,10 +22,10 @@ namespace Notepad.Extensions.Logging
|
||||||
[DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
[DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||||
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
|
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
|
||||||
|
|
||||||
public delegate bool EnumWindowsDelegate(IntPtr hWnd, IntPtr lParam);
|
public delegate bool EnumWindowsDelegate(IntPtr hWnd, object lParam);
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
public static extern bool EnumWindows(EnumWindowsDelegate lpEnumFunc, IntPtr lParam);
|
public static extern bool EnumWindows(EnumWindowsDelegate lpEnumFunc, object lParam);
|
||||||
|
|
||||||
[DllImport("User32.dll")]
|
[DllImport("User32.dll")]
|
||||||
public static extern int GetWindowText(IntPtr hWndParent, StringBuilder sb, int maxCount);
|
public static extern int GetWindowText(IntPtr hWndParent, StringBuilder sb, int maxCount);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -12,13 +11,15 @@ namespace Notepad.Extensions.Logging
|
||||||
{
|
{
|
||||||
class NotepadLogger : ILogger
|
class NotepadLogger : ILogger
|
||||||
{
|
{
|
||||||
public NotepadLogger(ObjectPool<StringBuilder> stringBuilderPool, string categoryName)
|
public NotepadLogger(ObjectPool<StringBuilder> stringBuilderPool, IWindowFinder windowFinder, string categoryName)
|
||||||
{
|
{
|
||||||
this.stringBuilderPool = stringBuilderPool;
|
this.stringBuilderPool = stringBuilderPool ?? throw new ArgumentNullException(nameof(stringBuilderPool));
|
||||||
|
this.windowFinder = windowFinder ?? throw new ArgumentNullException(nameof(windowFinder));
|
||||||
this.categoryName = categoryName;
|
this.categoryName = categoryName;
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly ObjectPool<StringBuilder> stringBuilderPool;
|
readonly ObjectPool<StringBuilder> stringBuilderPool;
|
||||||
|
readonly IWindowFinder windowFinder;
|
||||||
readonly string categoryName;
|
readonly string categoryName;
|
||||||
|
|
||||||
public IDisposable BeginScope<TState>(TState state) => NullDisposable.Instance;
|
public IDisposable BeginScope<TState>(TState state) => NullDisposable.Instance;
|
||||||
|
@ -87,18 +88,18 @@ namespace Notepad.Extensions.Logging
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(logLevel)),
|
_ => throw new ArgumentOutOfRangeException(nameof(logLevel)),
|
||||||
};
|
};
|
||||||
|
|
||||||
static void WriteToNotepad(string message)
|
void WriteToNotepad(string message)
|
||||||
{
|
{
|
||||||
var (kind, hwnd) = WindowFinder.FindNotepadWindow();
|
var info = windowFinder.FindNotepadWindow();
|
||||||
switch (kind)
|
switch (info.Kind)
|
||||||
{
|
{
|
||||||
case WindowKind.Notepad:
|
case WindowKind.Notepad:
|
||||||
SendMessage(hwnd, EM_REPLACESEL, (IntPtr)1, message);
|
SendMessage(info.Handle, EM_REPLACESEL, (IntPtr)1, message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WindowKind.NotepadPlusPlus:
|
case WindowKind.NotepadPlusPlus:
|
||||||
{
|
{
|
||||||
WriteToNotepadPlusPlus(hwnd, message);
|
WriteToNotepadPlusPlus(info.Handle, message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,15 @@ namespace Notepad.Extensions.Logging
|
||||||
{
|
{
|
||||||
var poolProvider = new DefaultObjectPoolProvider();
|
var poolProvider = new DefaultObjectPoolProvider();
|
||||||
stringBuilderPool = poolProvider.CreateStringBuilderPool();
|
stringBuilderPool = poolProvider.CreateStringBuilderPool();
|
||||||
|
windowFinder = new WindowFinder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ILoggerProvider Instance { get; } = new NotepadLoggerProvider();
|
public static ILoggerProvider Instance { get; } = new NotepadLoggerProvider();
|
||||||
|
|
||||||
readonly ObjectPool<StringBuilder> stringBuilderPool;
|
readonly ObjectPool<StringBuilder> stringBuilderPool;
|
||||||
|
readonly IWindowFinder windowFinder;
|
||||||
|
|
||||||
public ILogger CreateLogger(string categoryName) => new NotepadLogger(stringBuilderPool, categoryName);
|
public ILogger CreateLogger(string categoryName) => new NotepadLogger(stringBuilderPool, windowFinder, categoryName);
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
|
72
Notepad.Extensions.Logging/WindowEnumerationState.cs
Normal file
72
Notepad.Extensions.Logging/WindowEnumerationState.cs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Notepad.Extensions.Logging
|
||||||
|
{
|
||||||
|
class WindowEnumerationState
|
||||||
|
{
|
||||||
|
public WindowEnumerationState()
|
||||||
|
{
|
||||||
|
sb = new StringBuilder(capacity: 4096);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly StringBuilder sb;
|
||||||
|
|
||||||
|
public IntPtr Handle { get; private set; }
|
||||||
|
public WindowKind WindowKind { get; private set; }
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
Handle = default;
|
||||||
|
WindowKind = default;
|
||||||
|
sb.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ExamineWindow(IntPtr hWnd)
|
||||||
|
{
|
||||||
|
var result = NativeMethods.GetWindowText(hWnd, sb, sb.Capacity);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
throw new Win32Exception(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle = hWnd;
|
||||||
|
|
||||||
|
if (sb.Length > 0 && sb[0] == '*')
|
||||||
|
{
|
||||||
|
// Notepad and Notepad++ both mark dirty documents by adding a leading asterisk to the window name.
|
||||||
|
sb.Remove(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsKnownNotepadWindow(sb.ToString()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Regex notepadPlusPlusRegex = new Regex(@"^new \d+ - Notepad\+\+$", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
bool IsKnownNotepadWindow(string titleText)
|
||||||
|
{
|
||||||
|
switch (titleText)
|
||||||
|
{
|
||||||
|
case "Untitled - Notepad":
|
||||||
|
WindowKind = WindowKind.Notepad;
|
||||||
|
Handle = NativeMethods.FindWindowEx(Handle, IntPtr.Zero, "EDIT", null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notepadPlusPlusRegex.IsMatch(titleText))
|
||||||
|
{
|
||||||
|
WindowKind = WindowKind.NotepadPlusPlus;
|
||||||
|
Handle = NativeMethods.FindWindowEx(Handle, IntPtr.Zero, "Scintilla", null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
using Microsoft.Extensions.ObjectPool;
|
||||||
|
|
||||||
|
namespace Notepad.Extensions.Logging
|
||||||
|
{
|
||||||
|
class WindowEnumerationStatePoolingPolicy : IPooledObjectPolicy<WindowEnumerationState>
|
||||||
|
{
|
||||||
|
public static IPooledObjectPolicy<WindowEnumerationState> Instance { get; } = new WindowEnumerationStatePoolingPolicy();
|
||||||
|
|
||||||
|
public WindowEnumerationState Create() => new WindowEnumerationState();
|
||||||
|
|
||||||
|
public bool Return(WindowEnumerationState obj)
|
||||||
|
{
|
||||||
|
obj.Reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,89 +1,37 @@
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using Microsoft.Extensions.ObjectPool;
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace Notepad.Extensions.Logging
|
namespace Notepad.Extensions.Logging
|
||||||
{
|
{
|
||||||
static class WindowFinder
|
class WindowFinder : IWindowFinder
|
||||||
{
|
{
|
||||||
public static (WindowKind kind, IntPtr hwnd) FindNotepadWindow()
|
public WindowFinder()
|
||||||
{
|
{
|
||||||
sb ??= new StringBuilder(4096);
|
statePool = new DefaultObjectPool<WindowEnumerationState>(WindowEnumerationStatePoolingPolicy.Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly ObjectPool<WindowEnumerationState> statePool;
|
||||||
|
|
||||||
|
public WindowInfo FindNotepadWindow()
|
||||||
|
{
|
||||||
|
var stateObject = statePool.Get();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
FindMainWindow();
|
NativeMethods.EnumWindows(enumWindowsDelegate, stateObject);
|
||||||
return (windowKind, handle);
|
return new WindowInfo(stateObject.WindowKind, stateObject.Handle);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
handle = IntPtr.Zero;
|
statePool.Return(stateObject);
|
||||||
sb.Clear();
|
|
||||||
windowKind = WindowKind.Invalid;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static IntPtr FindMainWindow()
|
|
||||||
{
|
|
||||||
NativeMethods.EnumWindows(enumWindowsDelegate, IntPtr.Zero);
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NativeMethods.EnumWindowsDelegate enumWindowsDelegate = new NativeMethods.EnumWindowsDelegate(EnumWindowsCallback);
|
static NativeMethods.EnumWindowsDelegate enumWindowsDelegate = new NativeMethods.EnumWindowsDelegate(EnumWindowsCallback);
|
||||||
|
|
||||||
static bool EnumWindowsCallback(IntPtr hWnd, IntPtr lParam)
|
static bool EnumWindowsCallback(IntPtr hWnd, object lParam)
|
||||||
{
|
{
|
||||||
var result = NativeMethods.GetWindowText(hWnd, sb, sb.Capacity);
|
var state = (WindowEnumerationState)lParam;
|
||||||
if (result < 0)
|
return state.ExamineWindow(hWnd);
|
||||||
{
|
|
||||||
throw new Win32Exception(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowFinder.handle = hWnd;
|
|
||||||
|
|
||||||
if (sb.Length > 0 && sb[0] == '*')
|
|
||||||
{
|
|
||||||
// Notepad and Notepad++ both mark dirty documents by adding a leading asterisk to the window name.
|
|
||||||
sb.Remove(0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsKnownNotepadWindow(sb.ToString()))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ThreadStatic]
|
|
||||||
static IntPtr handle;
|
|
||||||
|
|
||||||
[ThreadStatic]
|
|
||||||
static WindowKind windowKind;
|
|
||||||
|
|
||||||
[ThreadStatic]
|
|
||||||
static StringBuilder sb;
|
|
||||||
|
|
||||||
static Regex notepadPlusPlusRegex = new Regex(@"^new \d+ - Notepad\+\+$", RegexOptions.Compiled);
|
|
||||||
|
|
||||||
static bool IsKnownNotepadWindow(string titleText)
|
|
||||||
{
|
|
||||||
switch (titleText)
|
|
||||||
{
|
|
||||||
case "Untitled - Notepad":
|
|
||||||
windowKind = WindowKind.Notepad;
|
|
||||||
handle = NativeMethods.FindWindowEx(handle, IntPtr.Zero, "EDIT", null);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notepadPlusPlusRegex.IsMatch(titleText))
|
|
||||||
{
|
|
||||||
windowKind = WindowKind.NotepadPlusPlus;
|
|
||||||
handle = NativeMethods.FindWindowEx(handle, IntPtr.Zero, "Scintilla", null);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
16
Notepad.Extensions.Logging/WindowInfo.cs
Normal file
16
Notepad.Extensions.Logging/WindowInfo.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Notepad.Extensions.Logging
|
||||||
|
{
|
||||||
|
struct WindowInfo
|
||||||
|
{
|
||||||
|
public WindowInfo(WindowKind kind, IntPtr handle)
|
||||||
|
{
|
||||||
|
Kind = kind;
|
||||||
|
Handle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WindowKind Kind { get; }
|
||||||
|
public IntPtr Handle { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Notepad.Extensions.Logging
|
namespace Notepad.Extensions.Logging
|
||||||
{
|
{
|
||||||
public enum WindowKind
|
enum WindowKind
|
||||||
{
|
{
|
||||||
Invalid,
|
Invalid,
|
||||||
Notepad,
|
Notepad,
|
||||||
|
|
Loading…
Reference in a new issue