diff --git a/Sources/DesktopManager.Example/KeyboardInputExample.cs b/Sources/DesktopManager.Example/KeyboardInputExample.cs
new file mode 100644
index 0000000..65ce13c
--- /dev/null
+++ b/Sources/DesktopManager.Example/KeyboardInputExample.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace DesktopManager.Example;
+
+///
+/// Demonstrates basic keyboard input using .
+///
+internal static class KeyboardInputExample {
+ /// Runs the keyboard input example.
+ public static void Run() {
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
+ Console.WriteLine("Keyboard input examples require Windows.");
+ return;
+ }
+
+ Console.WriteLine("Pressing WIN+R to open Run dialog...");
+ KeyboardInputService.PressShortcut(VirtualKey.VK_LWIN, VirtualKey.VK_R);
+ }
+}
diff --git a/Sources/DesktopManager.Example/Program.cs b/Sources/DesktopManager.Example/Program.cs
index 1cdaefd..cb44d42 100644
--- a/Sources/DesktopManager.Example/Program.cs
+++ b/Sources/DesktopManager.Example/Program.cs
@@ -78,6 +78,9 @@ static void Main(string[] args) {
// Demonstrate window keep-alive features
WindowKeepAliveExample.Run();
+ // Demonstrate keyboard input features
+ KeyboardInputExample.Run();
+
// Run monitor watcher example for 30 seconds
MonitorWatcherExample.RunAsync(TimeSpan.FromSeconds(30)).Wait();
diff --git a/Sources/DesktopManager.Tests/KeyboardInputServiceTests.cs b/Sources/DesktopManager.Tests/KeyboardInputServiceTests.cs
new file mode 100644
index 0000000..97b3a2b
--- /dev/null
+++ b/Sources/DesktopManager.Tests/KeyboardInputServiceTests.cs
@@ -0,0 +1,33 @@
+using System.Runtime.InteropServices;
+
+namespace DesktopManager.Tests;
+
+[TestClass]
+///
+/// Tests for .
+///
+public class KeyboardInputServiceTests {
+ [TestMethod]
+ ///
+ /// Test for PressKey_DoesNotThrow.
+ ///
+ public void PressKey_DoesNotThrow() {
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
+ Assert.Inconclusive("Test requires Windows");
+ }
+
+ KeyboardInputService.PressKey(VirtualKey.VK_F24);
+ }
+
+ [TestMethod]
+ ///
+ /// Test for PressShortcut_DoesNotThrow.
+ ///
+ public void PressShortcut_DoesNotThrow() {
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
+ Assert.Inconclusive("Test requires Windows");
+ }
+
+ KeyboardInputService.PressShortcut(VirtualKey.VK_F23, VirtualKey.VK_F24);
+ }
+}
diff --git a/Sources/DesktopManager/DesktopManager.csproj b/Sources/DesktopManager/DesktopManager.csproj
index c7083aa..c76512d 100644
--- a/Sources/DesktopManager/DesktopManager.csproj
+++ b/Sources/DesktopManager/DesktopManager.csproj
@@ -52,6 +52,8 @@
+
+
diff --git a/Sources/DesktopManager/KeyboardInputService.cs b/Sources/DesktopManager/KeyboardInputService.cs
new file mode 100644
index 0000000..0e85227
--- /dev/null
+++ b/Sources/DesktopManager/KeyboardInputService.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace DesktopManager;
+
+///
+/// Provides methods for simulating keyboard input.
+///
+[SupportedOSPlatform("windows")]
+public static class KeyboardInputService {
+ ///
+ /// Presses a single key using SendInput.
+ ///
+ /// Key to press.
+ public static void PressKey(VirtualKey key) {
+ MonitorNativeMethods.INPUT[] inputs = new MonitorNativeMethods.INPUT[2];
+ inputs[0].Type = MonitorNativeMethods.INPUT_KEYBOARD;
+ inputs[0].Data.Keyboard = new MonitorNativeMethods.KEYBDINPUT {
+ Vk = (ushort)key,
+ Scan = 0,
+ Flags = 0,
+ Time = 0,
+ ExtraInfo = IntPtr.Zero
+ };
+ inputs[1].Type = MonitorNativeMethods.INPUT_KEYBOARD;
+ inputs[1].Data.Keyboard = new MonitorNativeMethods.KEYBDINPUT {
+ Vk = (ushort)key,
+ Scan = 0,
+ Flags = MonitorNativeMethods.KEYEVENTF_KEYUP,
+ Time = 0,
+ ExtraInfo = IntPtr.Zero
+ };
+ MonitorNativeMethods.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf());
+ }
+
+ ///
+ /// Presses a shortcut combination of keys.
+ ///
+ /// Keys to press in order.
+ public static void PressShortcut(params VirtualKey[] keys) {
+ if (keys == null || keys.Length == 0) {
+ throw new ArgumentException("No keys specified", nameof(keys));
+ }
+
+ MonitorNativeMethods.INPUT[] inputs = new MonitorNativeMethods.INPUT[keys.Length * 2];
+ int index = 0;
+ foreach (VirtualKey key in keys) {
+ inputs[index].Type = MonitorNativeMethods.INPUT_KEYBOARD;
+ inputs[index].Data.Keyboard = new MonitorNativeMethods.KEYBDINPUT {
+ Vk = (ushort)key,
+ Scan = 0,
+ Flags = 0,
+ Time = 0,
+ ExtraInfo = IntPtr.Zero
+ };
+ index++;
+ }
+
+ for (int i = keys.Length - 1; i >= 0; i--) {
+ inputs[index].Type = MonitorNativeMethods.INPUT_KEYBOARD;
+ inputs[index].Data.Keyboard = new MonitorNativeMethods.KEYBDINPUT {
+ Vk = (ushort)keys[i],
+ Scan = 0,
+ Flags = MonitorNativeMethods.KEYEVENTF_KEYUP,
+ Time = 0,
+ ExtraInfo = IntPtr.Zero
+ };
+ index++;
+ }
+
+ MonitorNativeMethods.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf());
+ }
+}
diff --git a/Sources/DesktopManager/VirtualKey.cs b/Sources/DesktopManager/VirtualKey.cs
new file mode 100644
index 0000000..096dd4a
--- /dev/null
+++ b/Sources/DesktopManager/VirtualKey.cs
@@ -0,0 +1,311 @@
+namespace DesktopManager;
+
+///
+/// Virtual key codes used for keyboard input.
+///
+public enum VirtualKey : ushort {
+ /// Left mouse button.
+ VK_LBUTTON = 0x01,
+ /// Right mouse button.
+ VK_RBUTTON = 0x02,
+ /// Cancel key.
+ VK_CANCEL = 0x03,
+ /// Middle mouse button.
+ VK_MBUTTON = 0x04,
+ /// Backspace key.
+ VK_BACK = 0x08,
+ /// Tab key.
+ VK_TAB = 0x09,
+ /// Enter key.
+ VK_RETURN = 0x0D,
+ /// Shift key.
+ VK_SHIFT = 0x10,
+ /// Control key.
+ VK_CONTROL = 0x11,
+ /// Alt key.
+ VK_MENU = 0x12,
+ /// Pause key.
+ VK_PAUSE = 0x13,
+ /// Caps Lock key.
+ VK_CAPITAL = 0x14,
+ /// Escape key.
+ VK_ESCAPE = 0x1B,
+ /// Spacebar.
+ VK_SPACE = 0x20,
+ /// Page Up key.
+ VK_PRIOR = 0x21,
+ /// Page Down key.
+ VK_NEXT = 0x22,
+ /// End key.
+ VK_END = 0x23,
+ /// Home key.
+ VK_HOME = 0x24,
+ /// Left Arrow key.
+ VK_LEFT = 0x25,
+ /// Up Arrow key.
+ VK_UP = 0x26,
+ /// Right Arrow key.
+ VK_RIGHT = 0x27,
+ /// Down Arrow key.
+ VK_DOWN = 0x28,
+ /// Insert key.
+ VK_INSERT = 0x2D,
+ /// Delete key.
+ VK_DELETE = 0x2E,
+ /// 0 key.
+ VK_0 = 0x30,
+ /// 1 key.
+ VK_1 = 0x31,
+ /// 2 key.
+ VK_2 = 0x32,
+ /// 3 key.
+ VK_3 = 0x33,
+ /// 4 key.
+ VK_4 = 0x34,
+ /// 5 key.
+ VK_5 = 0x35,
+ /// 6 key.
+ VK_6 = 0x36,
+ /// 7 key.
+ VK_7 = 0x37,
+ /// 8 key.
+ VK_8 = 0x38,
+ /// 9 key.
+ VK_9 = 0x39,
+ /// A key.
+ VK_A = 0x41,
+ /// B key.
+ VK_B = 0x42,
+ /// C key.
+ VK_C = 0x43,
+ /// D key.
+ VK_D = 0x44,
+ /// E key.
+ VK_E = 0x45,
+ /// F key.
+ VK_F = 0x46,
+ /// G key.
+ VK_G = 0x47,
+ /// H key.
+ VK_H = 0x48,
+ /// I key.
+ VK_I = 0x49,
+ /// J key.
+ VK_J = 0x4A,
+ /// K key.
+ VK_K = 0x4B,
+ /// L key.
+ VK_L = 0x4C,
+ /// M key.
+ VK_M = 0x4D,
+ /// N key.
+ VK_N = 0x4E,
+ /// O key.
+ VK_O = 0x4F,
+ /// P key.
+ VK_P = 0x50,
+ /// Q key.
+ VK_Q = 0x51,
+ /// R key.
+ VK_R = 0x52,
+ /// S key.
+ VK_S = 0x53,
+ /// T key.
+ VK_T = 0x54,
+ /// U key.
+ VK_U = 0x55,
+ /// V key.
+ VK_V = 0x56,
+ /// W key.
+ VK_W = 0x57,
+ /// X key.
+ VK_X = 0x58,
+ /// Y key.
+ VK_Y = 0x59,
+ /// Z key.
+ VK_Z = 0x5A,
+ /// Left Windows key.
+ VK_LWIN = 0x5B,
+ /// Right Windows key.
+ VK_RWIN = 0x5C,
+ /// Numpad 0 key.
+ VK_NUMPAD0 = 0x60,
+ /// Numpad 1 key.
+ VK_NUMPAD1 = 0x61,
+ /// Numpad 2 key.
+ VK_NUMPAD2 = 0x62,
+ /// Numpad 3 key.
+ VK_NUMPAD3 = 0x63,
+ /// Numpad 4 key.
+ VK_NUMPAD4 = 0x64,
+ /// Numpad 5 key.
+ VK_NUMPAD5 = 0x65,
+ /// Numpad 6 key.
+ VK_NUMPAD6 = 0x66,
+ /// Numpad 7 key.
+ VK_NUMPAD7 = 0x67,
+ /// Numpad 8 key.
+ VK_NUMPAD8 = 0x68,
+ /// Numpad 9 key.
+ VK_NUMPAD9 = 0x69,
+ /// Multiply key.
+ VK_MULTIPLY = 0x6A,
+ /// Add key.
+ VK_ADD = 0x6B,
+ /// Separator key.
+ VK_SEPARATOR = 0x6C,
+ /// Subtract key.
+ VK_SUBTRACT = 0x6D,
+ /// Decimal key.
+ VK_DECIMAL = 0x6E,
+ /// Divide key.
+ VK_DIVIDE = 0x6F,
+ /// F1 key.
+ VK_F1 = 0x70,
+ /// F2 key.
+ VK_F2 = 0x71,
+ /// F3 key.
+ VK_F3 = 0x72,
+ /// F4 key.
+ VK_F4 = 0x73,
+ /// F5 key.
+ VK_F5 = 0x74,
+ /// F6 key.
+ VK_F6 = 0x75,
+ /// F7 key.
+ VK_F7 = 0x76,
+ /// F8 key.
+ VK_F8 = 0x77,
+ /// F9 key.
+ VK_F9 = 0x78,
+ /// F10 key.
+ VK_F10 = 0x79,
+ /// F11 key.
+ VK_F11 = 0x7A,
+ /// F12 key.
+ VK_F12 = 0x7B,
+ /// F13 key.
+ VK_F13 = 0x7C,
+ /// F14 key.
+ VK_F14 = 0x7D,
+ /// F15 key.
+ VK_F15 = 0x7E,
+ /// F16 key.
+ VK_F16 = 0x7F,
+ /// F17 key.
+ VK_F17 = 0x80,
+ /// F18 key.
+ VK_F18 = 0x81,
+ /// F19 key.
+ VK_F19 = 0x82,
+ /// F20 key.
+ VK_F20 = 0x83,
+ /// F21 key.
+ VK_F21 = 0x84,
+ /// F22 key.
+ VK_F22 = 0x85,
+ /// F23 key.
+ VK_F23 = 0x86,
+ /// F24 key.
+ VK_F24 = 0x87,
+ /// Num Lock key.
+ VK_NUMLOCK = 0x90,
+ /// Scroll Lock key.
+ VK_SCROLL = 0x91,
+ /// Left Shift key.
+ VK_LSHIFT = 0xA0,
+ /// Right Shift key.
+ VK_RSHIFT = 0xA1,
+ /// Left Control key.
+ VK_LCONTROL = 0xA2,
+ /// Right Control key.
+ VK_RCONTROL = 0xA3,
+ /// Left Alt key.
+ VK_LMENU = 0xA4,
+ /// Right Alt key.
+ VK_RMENU = 0xA5,
+ /// Browser Back key.
+ VK_BROWSER_BACK = 0xA6,
+ /// Browser Forward key.
+ VK_BROWSER_FORWARD = 0xA7,
+ /// Browser Refresh key.
+ VK_BROWSER_REFRESH = 0xA8,
+ /// Browser Stop key.
+ VK_BROWSER_STOP = 0xA9,
+ /// Browser Search key.
+ VK_BROWSER_SEARCH = 0xAA,
+ /// Browser Favorites key.
+ VK_BROWSER_FAVORITES = 0xAB,
+ /// Browser Home key.
+ VK_BROWSER_HOME = 0xAC,
+ /// Volume Mute key.
+ VK_VOLUME_MUTE = 0xAD,
+ /// Volume Down key.
+ VK_VOLUME_DOWN = 0xAE,
+ /// Volume Up key.
+ VK_VOLUME_UP = 0xAF,
+ /// Next Track key.
+ VK_MEDIA_NEXT_TRACK = 0xB0,
+ /// Previous Track key.
+ VK_MEDIA_PREV_TRACK = 0xB1,
+ /// Stop Media key.
+ VK_MEDIA_STOP = 0xB2,
+ /// Play/Pause Media key.
+ VK_MEDIA_PLAY_PAUSE = 0xB3,
+ /// Launch Mail key.
+ VK_LAUNCH_MAIL = 0xB4,
+ /// Launch Media Select key.
+ VK_LAUNCH_MEDIA_SELECT = 0xB5,
+ /// Launch App1 key.
+ VK_LAUNCH_APP1 = 0xB6,
+ /// Launch App2 key.
+ VK_LAUNCH_APP2 = 0xB7,
+ /// OEM 1 key.
+ VK_OEM_1 = 0xBA,
+ /// OEM Plus key.
+ VK_OEM_PLUS = 0xBB,
+ /// OEM Comma key.
+ VK_OEM_COMMA = 0xBC,
+ /// OEM Minus key.
+ VK_OEM_MINUS = 0xBD,
+ /// OEM Period key.
+ VK_OEM_PERIOD = 0xBE,
+ /// OEM 2 key.
+ VK_OEM_2 = 0xBF,
+ /// OEM 3 key.
+ VK_OEM_3 = 0xC0,
+ /// OEM 4 key.
+ VK_OEM_4 = 0xDB,
+ /// OEM 5 key.
+ VK_OEM_5 = 0xDC,
+ /// OEM 6 key.
+ VK_OEM_6 = 0xDD,
+ /// OEM 7 key.
+ VK_OEM_7 = 0xDE,
+ /// OEM 8 key.
+ VK_OEM_8 = 0xDF,
+ /// OEM 102 key.
+ VK_OEM_102 = 0xE2,
+ /// Process key.
+ VK_PROCESSKEY = 0xE5,
+ /// Packet key.
+ VK_PACKET = 0xE7,
+ /// Attention key.
+ VK_ATTN = 0xF6,
+ /// CrSel key.
+ VK_CRSEL = 0xF7,
+ /// ExSel key.
+ VK_EXSEL = 0xF8,
+ /// Erase EOF key.
+ VK_EREOF = 0xF9,
+ /// Play key.
+ VK_PLAY = 0xFA,
+ /// Zoom key.
+ VK_ZOOM = 0xFB,
+ /// NoName key.
+ VK_NONAME = 0xFC,
+ /// PA1 key.
+ VK_PA1 = 0xFD,
+ /// Clear key.
+ VK_OEM_CLEAR = 0xFE
+}