using System.Runtime.InteropServices; using System.Text; namespace Automata.Game; /// /// Win32 clipboard access without WinForms dependency. /// public static class ClipboardHelper { private const int MaxRetries = 5; private const int RetryDelayMs = 30; public static string Read() { for (var attempt = 0; attempt < MaxRetries; attempt++) { if (ClipboardNative.OpenClipboard(IntPtr.Zero)) { try { var handle = ClipboardNative.GetClipboardData(ClipboardNative.CF_UNICODETEXT); if (handle == IntPtr.Zero) return ""; var ptr = ClipboardNative.GlobalLock(handle); if (ptr == IntPtr.Zero) return ""; try { return Marshal.PtrToStringUni(ptr) ?? ""; } finally { ClipboardNative.GlobalUnlock(handle); } } finally { ClipboardNative.CloseClipboard(); } } Thread.Sleep(RetryDelayMs); } return ""; } public static void Write(string text) { for (var attempt = 0; attempt < MaxRetries; attempt++) { if (ClipboardNative.OpenClipboard(IntPtr.Zero)) { try { ClipboardNative.EmptyClipboard(); var bytes = Encoding.Unicode.GetBytes(text + "\0"); var hGlobal = ClipboardNative.GlobalAlloc(ClipboardNative.GMEM_MOVEABLE, (UIntPtr)bytes.Length); if (hGlobal == IntPtr.Zero) return; var ptr = ClipboardNative.GlobalLock(hGlobal); if (ptr == IntPtr.Zero) { ClipboardNative.GlobalFree(hGlobal); return; } try { Marshal.Copy(bytes, 0, ptr, bytes.Length); } finally { ClipboardNative.GlobalUnlock(hGlobal); } ClipboardNative.SetClipboardData(ClipboardNative.CF_UNICODETEXT, hGlobal); return; } finally { ClipboardNative.CloseClipboard(); } } Thread.Sleep(RetryDelayMs); } } } internal static partial class ClipboardNative { public const uint CF_UNICODETEXT = 13; public const uint GMEM_MOVEABLE = 0x0002; [LibraryImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static partial bool OpenClipboard(IntPtr hWndNewOwner); [LibraryImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static partial bool CloseClipboard(); [LibraryImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static partial bool EmptyClipboard(); [LibraryImport("user32.dll")] public static partial IntPtr GetClipboardData(uint uFormat); [LibraryImport("user32.dll")] public static partial IntPtr SetClipboardData(uint uFormat, IntPtr hMem); [LibraryImport("kernel32.dll")] public static partial IntPtr GlobalAlloc(uint uFlags, UIntPtr dwBytes); [LibraryImport("kernel32.dll")] public static partial IntPtr GlobalLock(IntPtr hMem); [LibraryImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static partial bool GlobalUnlock(IntPtr hMem); [LibraryImport("kernel32.dll")] public static partial IntPtr GlobalFree(IntPtr hMem); }