Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates to support writing to new Notepad on Windows 11 #60

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions sample/ConsoleDemo/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
//
#endregion

using Serilog;
using System;
using System.Threading;
using Serilog;

namespace ConsoleDemo
{
Expand All @@ -40,8 +40,16 @@ private static void Main(string[] args)

Log.Debug("Getting started");

Log.Information("Hello {Name} from thread {ThreadId}", Environment.GetEnvironmentVariable("USERNAME"),
Thread.CurrentThread.ManagedThreadId);
var startTime = DateTime.Now;

while (DateTime.Now - startTime < TimeSpan.FromMinutes(1))
{

Log.Information("Hello {Name} from thread {ThreadId}", Environment.GetEnvironmentVariable("USERNAME"),
Thread.CurrentThread.ManagedThreadId);

Thread.Sleep(1000);
}

Log.Warning("No coins remain at position {@Position}", new { Lat = 25, Long = 134 });

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
//
#endregion

using Serilog.Debugging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Serilog.Debugging;

namespace Serilog.Sinks.Notepad.Interop
{
Expand Down Expand Up @@ -55,7 +57,10 @@ public override void Flush()
// No instances of Notepad found... Nothing to do
return;
}
}

if (_currentNotepadEditorHandle == IntPtr.Zero)
{
var notepadWindowHandle = currentNotepadProcess.MainWindowHandle;

var notepadEditorHandle = FindNotepadEditorHandle(notepadWindowHandle);
Expand All @@ -69,18 +74,31 @@ public override void Flush()
}

// Get how many characters are in the Notepad editor already
var textLength = User32.SendMessage(_currentNotepadEditorHandle, User32.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
var textLengthBefore = User32.SendMessage(_currentNotepadEditorHandle, User32.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);

// Set the caret position to the end of the text
User32.SendMessage(_currentNotepadEditorHandle, User32.EM_SETSEL, (IntPtr)textLength, (IntPtr)textLength);
User32.SendMessage(_currentNotepadEditorHandle, User32.EM_SETSEL, (IntPtr)textLengthBefore, (IntPtr)textLengthBefore);

var buffer = base.GetStringBuilder();
var message = buffer.ToString();

// Write the log message to Notepad
User32.SendMessage(_currentNotepadEditorHandle, User32.EM_REPLACESEL, (IntPtr)1, message);

buffer.Clear();
// Get how many characters are in the Notepad editor after putting in new text
var textLengthAfter = User32.SendMessage(_currentNotepadEditorHandle, User32.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);

// If no change in the text length, reset editor handle to try to find it again.
if (textLengthAfter == textLengthBefore)
{
_currentNotepadEditorHandle = IntPtr.Zero;
}
else
{
// Otherwise, we clear the buffer

buffer.Clear();
bstordrup marked this conversation as resolved.
Show resolved Hide resolved
}
}

protected override void Dispose(bool disposing)
Expand Down Expand Up @@ -120,6 +138,13 @@ private static IntPtr FindNotepadEditorHandle(IntPtr notepadWindowHandle)
return richEditHandle;
}

// Issue #59 - Alternate way of finding the RichEditD2DPT class:
if (FindEditorHandleThroughChildWindows(notepadWindowHandle) is var richEditHandleFromChildren
&& richEditHandleFromChildren != IntPtr.Zero)
{
return richEditHandleFromChildren;
}

return User32.FindWindowEx(notepadWindowHandle, IntPtr.Zero, "Edit", null);
}

Expand All @@ -130,5 +155,54 @@ private void EnsureNotDisposed()
throw new ObjectDisposedException(GetType().Name);
}
}

private static string GetClassNameFromWindow(IntPtr handle)
{
StringBuilder sb = new StringBuilder(256);
var ret = User32.GetClassName(handle, sb, sb.Capacity);
return ret != 0 ? sb.ToString() : string.Empty;
}

private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
var gch = GCHandle.FromIntPtr(pointer);
var list = gch.Target as List<IntPtr>;

if (list is null)
{
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
}

if (string.Equals(GetClassNameFromWindow(handle), "RichEditD2DPT", StringComparison.OrdinalIgnoreCase))
{
list.Add(handle);

// Stop enumerating - we found the one.
return false;
}

return true;
}

private static IntPtr FindEditorHandleThroughChildWindows(IntPtr notepadWindowHandle)
{
var result = new List<IntPtr>(1);
var listHandle = GCHandle.Alloc(result);

try
{
User32.Win32Callback childProc = new User32.Win32Callback(EnumWindow);
User32.EnumChildWindows(notepadWindowHandle, childProc, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated)
{
listHandle.Free();
}
}

return result.FirstOrDefault();
}
}
}
12 changes: 12 additions & 0 deletions src/Serilog.Sinks.Notepad/Sinks/Notepad/Interop/User32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,17 @@ internal class User32

[DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);


// Needed for EnumChildWindows for registering a call back function.
public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);

[DllImport("user32.Dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int GetClassName(IntPtr hWnd, System.Text.StringBuilder lpClassName, int nMaxCount);

}
}