Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for hashid.cs

(view source code of hashid.cs as plain text)

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.InteropServices;
  5.  
  6.  
  7. namespace RobvanderWoude
  8. {
  9. 	internal class HasHID
  10. 	{
  11. 		static readonly string progver = "1.00";
  12.  
  13.  
  14. 		static int Main( string[] args )
  15. 		{
  16. 			bool usbkeyboards = true;
  17. 			bool otherkeyboards = true;
  18. 			bool quietmode = false;
  19. 			bool mice = true;
  20. 			bool kbds = true;
  21.  
  22.  
  23. 			#region Parse Command Line
  24.  
  25. 			foreach ( string arg in args )
  26. 			{
  27. 				switch ( arg.ToUpper( ) )
  28. 				{
  29. 					case "/?":
  30. 						return ShowHelp( );
  31. 					case "/K":
  32. 					case "/KBD":
  33. 					case "/KEYBOARD":
  34. 					case "/KEYBOARDS":
  35. 						if ( !mice )
  36. 						{
  37. 							return ShowHelp( "Duplicate command line switch /KEYBOARD" );
  38. 						}
  39. 						mice = false;
  40. 						break;
  41. 					case "/M":
  42. 					case "/MOUSE":
  43. 					case "/MICE":
  44. 						if ( !kbds )
  45. 						{
  46. 							return ShowHelp( "Duplicate command line switch /MOUSE" );
  47. 						}
  48. 						kbds = false;
  49. 						usbkeyboards = false;
  50. 						otherkeyboards = false;
  51. 						break;
  52. 					case "/O":
  53. 					case "/OTHER":
  54. 						if ( !kbds )
  55. 						{
  56. 							return ShowHelp( "Switch /OTHER is not valid with /MOUSE" );
  57. 						}
  58. 						else if ( !usbkeyboards )
  59. 						{
  60. 							return ShowHelp( "Duplicate command line switch /OTHER" );
  61. 						}
  62. 						usbkeyboards = false;
  63. 						break;
  64. 					case "/Q":
  65. 					case "/QUIET":
  66. 						if ( quietmode )
  67. 						{
  68. 							return ShowHelp( "Duplicate command line switch /QUIET" );
  69. 						}
  70. 						quietmode = true;
  71. 						break;
  72. 					case "/U":
  73. 					case "/USB":
  74. 						if ( !kbds )
  75. 						{
  76. 							return ShowHelp( "Switch /USB is not valid with /MOUSE" );
  77. 						}
  78. 						else if ( !otherkeyboards )
  79. 						{
  80. 							return ShowHelp( "Duplicate command line switch /USB" );
  81. 						}
  82. 						otherkeyboards = false;
  83. 						break;
  84. 					default:
  85. 						return ShowHelp( "Invalid command line argument \"{0}\"", arg );
  86. 				}
  87. 				if ( !mice && !kbds )
  88. 				{
  89. 					return ShowHelp( "Command line switches /KEYBOARD and /MOUSE are mutually exclusive" );
  90. 				}
  91. 				if ( !kbds && ( otherkeyboards || usbkeyboards ) )
  92. 				{
  93. 					return ShowHelp( "Switches /USB or /OTHER are not valid with /MOUSE" );
  94. 				}
  95. 				else if ( kbds && ( !otherkeyboards && !usbkeyboards ) )
  96. 				{
  97. 					return ShowHelp( "Command line switches /USB and /OTHER are mutually exclusive" );
  98. 				}
  99. 			}
  100.  
  101. 			#endregion Parse Command Line
  102.  
  103.  
  104. 			#region Enumerate and Count Raw Input Devices
  105.  
  106. 			var rawDeviceEnumerator = new RawInputDeviceEnumerator( );
  107.  
  108. 			int count = -1;
  109. 			if ( kbds && mice )
  110. 			{
  111. 				count = rawDeviceEnumerator.AllKeyboardsCount;
  112. 				int tempcount = count;
  113. 				tempcount = rawDeviceEnumerator.AllMiceCount;
  114. 				if ( !quietmode )
  115. 				{
  116. 					Console.WriteLine( "Total keyboards count: {0}", count );
  117. 					Console.WriteLine( "Total mice count: {0}", tempcount );
  118. 				}
  119. 				count += tempcount;
  120. 			}
  121. 			else if ( mice )
  122. 			{
  123. 				count = rawDeviceEnumerator.AllMiceCount;
  124. 				if ( !quietmode )
  125. 				{
  126. 					Console.WriteLine( "Total mice count: {0}", count );
  127. 				}
  128. 			}
  129. 			else if ( kbds && ( otherkeyboards && usbkeyboards ) )
  130. 			{
  131. 				count = rawDeviceEnumerator.AllKeyboardsCount;
  132. 				if ( !quietmode )
  133. 				{
  134. 					Console.WriteLine( "Total keyboards count: {0}", count );
  135. 				}
  136. 			}
  137. 			else if ( usbkeyboards )
  138. 			{
  139. 				count = rawDeviceEnumerator.UsbKeyboardsCount;
  140. 				if ( !quietmode )
  141. 				{
  142. 					Console.WriteLine( "USB keyboards count: {0}", count );
  143. 				}
  144. 			}
  145. 			else if ( otherkeyboards )
  146. 			{
  147. 				count = rawDeviceEnumerator.OtherKeyboardsCount;
  148. 				if ( !quietmode )
  149. 				{
  150. 					Console.WriteLine( "Other (non-USB) keyboards count: {0}", count );
  151. 				}
  152. 			}
  153.  
  154. 			#endregion Enumerate and Count Raw Input Devices
  155.  
  156.  
  157. 			return count;
  158. 		}
  159.  
  160.  
  161. 		public static int ShowHelp( params string[] errmsg )
  162. 		{
  163. 			#region Error Message
  164.  
  165. 			if ( errmsg.Length > 0 )
  166. 			{
  167. 				List<string> errargs = new List<string>( errmsg );
  168. 				errargs.RemoveAt( 0 );
  169. 				Console.Error.WriteLine( );
  170. 				Console.ForegroundColor = ConsoleColor.Red;
  171. 				Console.Error.Write( "ERROR:\t" );
  172. 				Console.ForegroundColor = ConsoleColor.White;
  173. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  174. 				Console.ResetColor( );
  175. 			}
  176.  
  177. 			#endregion Error Message
  178.  
  179.  
  180. 			#region Help Text
  181.  
  182. 			/*
  183. 			HasHID.exe,  Version 1.00
  184. 			Count number of mice and/or keyboards available at this very moment
  185.  
  186. 			Usage:   HasHID.exe  [ /MOUSE | /KEYBOARD [ /USB | /OTHER ] ]  [ /Q ]
  187.  
  188. 			Where:   /MOUSE        count mice only (default: mice and keyboards)
  189. 			         /KEYBOARD     count keyboards only (default: mice and keyboards)
  190. 			         /USB          count USB keyboards only (default: all keyboards)
  191. 			         /OTHER        count OTHER (non-USB) keyboards only (default: all)
  192. 			         /QUIET        QUIET mode (no screen output)
  193.  
  194. 			Notes:   By default this program counts all mice and keyboards.
  195. 			         Switches may be abbreviated to /K, /M, /U, /O and/or /Q.
  196. 			         The program's return code equals the number of devices of the
  197. 			         specified type detected, or -1 in case of (command line) errors.
  198.  
  199. 			Credits: Based on C# wrapper for GetRawInputDeviceList by Pavel Pachobut
  200. 			         https://github.com/PashaPash/RawInput/
  201.  
  202. 			Written by Rob van der Woude
  203. 			https://www.robvanderwoude.com
  204. 			*/
  205.  
  206. 			#endregion Help Text
  207.  
  208.  
  209. 			#region Display Help Text
  210.  
  211. 			Console.Error.WriteLine( );
  212.  
  213. 			Console.Error.WriteLine( "HasHID.exe,  Version {0}", progver );
  214.  
  215. 			Console.Error.WriteLine( "Count number of mice and/or keyboards available at this very moment" );
  216.  
  217. 			Console.Error.WriteLine( );
  218.  
  219. 			Console.Error.Write( "Usage:   " );
  220. 			Console.ForegroundColor = ConsoleColor.White;
  221. 			Console.Error.WriteLine( "HasHID.exe  [ /MOUSE | /KEYBOARD [ /USB | /OTHER ] ]  [ /Q ]" );
  222. 			Console.ResetColor( );
  223.  
  224. 			Console.Error.WriteLine( );
  225.  
  226. 			Console.Error.Write( "Where:   " );
  227. 			Console.ForegroundColor = ConsoleColor.White;
  228. 			Console.Error.Write( "/MOUSE" );
  229. 			Console.ResetColor( );
  230. 			Console.Error.Write( "        count " );
  231. 			Console.ForegroundColor = ConsoleColor.White;
  232. 			Console.Error.Write( "mice" );
  233. 			Console.ResetColor( );
  234. 			Console.Error.WriteLine( " only (default: mice and keyboards)" );
  235.  
  236. 			Console.ForegroundColor = ConsoleColor.White;
  237. 			Console.Error.Write( "         /KEYBOARD" );
  238. 			Console.ResetColor( );
  239. 			Console.Error.Write( "     count " );
  240. 			Console.ForegroundColor = ConsoleColor.White;
  241. 			Console.Error.Write( "keyboards" );
  242. 			Console.ResetColor( );
  243. 			Console.Error.WriteLine( " only (default: mice and keyboards)" );
  244.  
  245. 			Console.ForegroundColor = ConsoleColor.White;
  246. 			Console.Error.Write( "         /USB" );
  247. 			Console.ResetColor( );
  248. 			Console.Error.Write( "          count " );
  249. 			Console.ForegroundColor = ConsoleColor.White;
  250. 			Console.Error.Write( "USB" );
  251. 			Console.ResetColor( );
  252. 			Console.Error.WriteLine( " keyboards only (default: all keybords)" );
  253.  
  254. 			Console.ForegroundColor = ConsoleColor.White;
  255. 			Console.Error.Write( "         /OTHER" );
  256. 			Console.ResetColor( );
  257. 			Console.Error.Write( "        count " );
  258. 			Console.ForegroundColor = ConsoleColor.White;
  259. 			Console.Error.Write( "OTHER" );
  260. 			Console.ResetColor( );
  261. 			Console.Error.WriteLine( " (non-USB) keyboards only (default: all)" );
  262.  
  263. 			Console.ForegroundColor = ConsoleColor.White;
  264. 			Console.Error.Write( "         /QUIET        QUIET" );
  265. 			Console.ResetColor( );
  266. 			Console.Error.WriteLine( " mode (no screen output)" );
  267.  
  268. 			Console.Error.WriteLine( );
  269.  
  270. 			Console.Error.WriteLine( "Notes:   By default this program counts all mice and keyboards." );
  271.  
  272. 			Console.Error.Write( "         Switches may be abbreviated to " );
  273. 			Console.ForegroundColor = ConsoleColor.White;
  274. 			Console.Error.Write( "/K" );
  275. 			Console.ResetColor( );
  276. 			Console.Error.Write( ", " );
  277. 			Console.ForegroundColor = ConsoleColor.White;
  278. 			Console.Error.Write( "/M" );
  279. 			Console.ResetColor( );
  280. 			Console.Error.Write( ", " );
  281. 			Console.ForegroundColor = ConsoleColor.White;
  282. 			Console.Error.Write( "/U" );
  283. 			Console.ResetColor( );
  284. 			Console.Error.Write( ", " );
  285. 			Console.ForegroundColor = ConsoleColor.White;
  286. 			Console.Error.Write( "/O" );
  287. 			Console.ResetColor( );
  288. 			Console.Error.Write( " and/or " );
  289. 			Console.ForegroundColor = ConsoleColor.White;
  290. 			Console.Error.Write( "/Q" );
  291. 			Console.ResetColor( );
  292. 			Console.Error.WriteLine( "." );
  293.  
  294. 			Console.Error.WriteLine( "         The program's return code equals the number of devices of the" );
  295.  
  296. 			Console.Error.WriteLine( "         specified type detected, or -1 in case of (command line) errors." );
  297.  
  298. 			Console.Error.WriteLine( );
  299.  
  300. 			Console.Error.WriteLine( "Credits: Based on C# wrapper for GetRawInputDeviceList by Pavel Pachobut" );
  301.  
  302. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  303. 			Console.Error.WriteLine( "         https://github.com/PashaPash/RawInput/" );
  304. 			Console.ResetColor( );
  305.  
  306. 			Console.Error.WriteLine( );
  307.  
  308. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  309.  
  310. 			Console.Error.WriteLine( "https://www.robvanderwoude.com" );
  311.  
  312. 			#endregion Display Help Text
  313.  
  314.  
  315. 			return -1;
  316. 		}
  317. 	}
  318.  
  319.  
  320. 	// The following code is copied from Pavel Pachobut's C# wrapper for
  321. 	// GetRawInputDeviceList: https://github.com/PashaPash/RawInput/
  322. 	// and modified by Rob van der Woude (added AllKeyboardsCount, AllMiceCount
  323. 	// and OtherKeyboardsCount properties to RawInputDeviceEnumerator class)
  324. 	public class RawInputDevice
  325. 	{
  326. 		private readonly Win32.RawInputDeviceList _rawInputDeviceList;
  327. 		private readonly string _deviceName;
  328. 		private readonly Win32.DeviceInfo _deviceInfo;
  329.  
  330. 		public IntPtr DeviceHandle
  331. 		{
  332. 			get
  333. 			{
  334. 				return _rawInputDeviceList.DeviceHandle;
  335. 			}
  336. 		}
  337.  
  338. 		public Win32.RawInputDeviceType DeviceType
  339. 		{
  340. 			get
  341. 			{
  342. 				return _rawInputDeviceList.DeviceType;
  343. 			}
  344. 		}
  345.  
  346. 		public string DeviceName
  347. 		{
  348. 			get
  349. 			{
  350. 				return this._deviceName;
  351. 			}
  352. 		}
  353.  
  354. 		public Win32.DeviceInfo DeviceInfo
  355. 		{
  356. 			get
  357. 			{
  358. 				return this._deviceInfo;
  359. 			}
  360. 		}
  361.  
  362. 		public RawInputDevice( Win32.RawInputDeviceList rawInputDeviceList )
  363. 		{
  364. 			this._rawInputDeviceList = rawInputDeviceList;
  365.  
  366. 			_deviceName = GetDeviceName( this._rawInputDeviceList.DeviceHandle );
  367.  
  368. 			_deviceInfo = GetDeviceInfo( this._rawInputDeviceList.DeviceHandle );
  369. 		}
  370.  
  371. 		private static IntPtr GetDeviceData( IntPtr deviceHandle, Win32.RawInputDeviceInfoCommand command )
  372. 		{
  373. 			uint dataSize = 0;
  374. 			var ptrData = IntPtr.Zero;
  375.  
  376. 			Win32.GetRawInputDeviceInfo( deviceHandle, command, ptrData, ref dataSize );
  377.  
  378. 			if ( dataSize == 0 )
  379. 			{
  380. 				return IntPtr.Zero;
  381. 			}
  382.  
  383. 			ptrData = Marshal.AllocHGlobal( (int)dataSize );
  384.  
  385. 			var result = Win32.GetRawInputDeviceInfo( deviceHandle, command, ptrData, ref dataSize );
  386.  
  387. 			if ( result == 0 )
  388. 			{
  389. 				Marshal.FreeHGlobal( ptrData );
  390. 				return IntPtr.Zero;
  391. 			}
  392.  
  393. 			return ptrData;
  394. 		}
  395.  
  396. 		private static string GetDeviceName( IntPtr deviceHandle )
  397. 		{
  398. 			var ptrDeviceName = GetDeviceData( deviceHandle, Win32.RawInputDeviceInfoCommand.DeviceName );
  399.  
  400. 			if ( ptrDeviceName == IntPtr.Zero )
  401. 			{
  402. 				return string.Empty;
  403. 			}
  404.  
  405. 			var deviceName = Marshal.PtrToStringAnsi( ptrDeviceName );
  406. 			Marshal.FreeHGlobal( ptrDeviceName );
  407. 			return deviceName;
  408. 		}
  409.  
  410. 		private static Win32.DeviceInfo GetDeviceInfo( IntPtr deviceHandle )
  411. 		{
  412. 			var ptrDeviceInfo = GetDeviceData( deviceHandle, Win32.RawInputDeviceInfoCommand.DeviceInfo );
  413.  
  414. 			if ( ptrDeviceInfo == IntPtr.Zero )
  415. 			{
  416. 				return new Win32.DeviceInfo( );
  417. 			}
  418.  
  419. 			var deviceInfo = (Win32.DeviceInfo)Marshal.PtrToStructure( ptrDeviceInfo, typeof( Win32.DeviceInfo ) );
  420.  
  421. 			Marshal.FreeHGlobal( ptrDeviceInfo );
  422. 			return deviceInfo;
  423. 		}
  424. 	}
  425.  
  426.  
  427. 	public class RawInputDeviceEnumerator
  428. 	{
  429. 		private readonly RawInputDevice[] _devices;
  430.  
  431. 		public IEnumerable<RawInputDevice> Devices
  432. 		{
  433. 			get
  434. 			{
  435. 				return this._devices;
  436. 			}
  437. 		}
  438.  
  439. 		public RawInputDeviceEnumerator( )
  440. 		{
  441. 			uint deviceCount = 0;
  442. 			var deviceSize = (uint)Marshal.SizeOf( typeof( Win32.RawInputDeviceList ) );
  443.  
  444. 			// first call retrieves the number of raw input devices
  445. 			var result = Win32.GetRawInputDeviceList( IntPtr.Zero, ref deviceCount, deviceSize );
  446.  
  447. 			_devices = new RawInputDevice[deviceCount];
  448.  
  449. 			if ( (int)result == -1 || deviceCount == 0 )
  450. 			{
  451. 				// call failed, or no devices found
  452. 				return;
  453. 			}
  454.  
  455. 			// allocates memory for an array of Win32.RawInputDeviceList
  456. 			IntPtr ptrDeviceList = Marshal.AllocHGlobal( (int)( deviceSize * deviceCount ) );
  457.  
  458. 			result = Win32.GetRawInputDeviceList( ptrDeviceList, ref deviceCount, deviceSize );
  459.  
  460. 			if ( (int)result != -1 )
  461. 			{
  462. 				// enumerates array of Win32.RawInputDeviceList,
  463. 				// and populates array of managed RawInputDevice objects
  464. 				for ( var index = 0; index < deviceCount; index++ )
  465. 				{
  466. 					var rawInputDeviceList = (Win32.RawInputDeviceList)Marshal.PtrToStructure( new IntPtr( ( ptrDeviceList.ToInt32( ) + ( deviceSize * index ) ) ), typeof( Win32.RawInputDeviceList ) );
  467.  
  468. 					_devices[index] = new RawInputDevice( rawInputDeviceList );
  469. 				}
  470. 			}
  471.  
  472. 			Marshal.FreeHGlobal( ptrDeviceList );
  473. 		}
  474.  
  475.  
  476. 		public int AllMiceCount
  477. 		{
  478. 			get
  479. 			{
  480. 				return this.Devices.Count( d => d.DeviceType == Win32.RawInputDeviceType.Mouse );
  481. 			}
  482. 		}
  483.  
  484.  
  485. 		public int AllKeyboardsCount
  486. 		{
  487. 			get
  488. 			{
  489. 				return this.Devices.Count( d => d.DeviceType == Win32.RawInputDeviceType.Keyboard );
  490. 			}
  491. 		}
  492.  
  493.  
  494. 		public int OtherKeyboardsCount
  495. 		{
  496. 			get
  497. 			{
  498. 				return this.Devices.Count( d => d.DeviceType == Win32.RawInputDeviceType.Keyboard && !d.DeviceInfo.KeyboardInfo.IsUSBKeboard );
  499. 			}
  500. 		}
  501.  
  502.  
  503. 		public int UsbKeyboardsCount
  504. 		{
  505. 			get
  506. 			{
  507. 				return this.Devices.Count( d => d.DeviceType == Win32.RawInputDeviceType.Keyboard && d.DeviceInfo.KeyboardInfo.IsUSBKeboard );
  508. 			}
  509. 		}
  510. 	}
  511.  
  512.  
  513. 	public static class Win32
  514. 	{
  515. 		public enum RawInputDeviceType : uint
  516. 		{
  517. 			Mouse = 0,
  518. 			Keyboard = 1,
  519. 			HumanInterfaceDevice = 2
  520. 		}
  521.  
  522. 		public enum RawInputDeviceInfoCommand : uint
  523. 		{
  524. 			PreparsedData = 0x20000005,
  525. 			DeviceName = 0x20000007,
  526. 			DeviceInfo = 0x2000000b,
  527. 		}
  528.  
  529. 		[StructLayout( LayoutKind.Explicit )]
  530. 		public struct DeviceInfo
  531. 		{
  532. 			[FieldOffset( 0 )]
  533. 			public int Size;
  534. 			[FieldOffset( 4 )]
  535. 			public int Type;
  536. 			[FieldOffset( 8 )]
  537. 			public DeviceInfoMouse MouseInfo;
  538. 			[FieldOffset( 8 )]
  539. 			public DeviceInfoKeyboard KeyboardInfo;
  540. 			[FieldOffset( 8 )]
  541. 			public DeviceInfoHID HIDInfo;
  542. 		}
  543.  
  544. 		public struct DeviceInfoMouse
  545. 		{
  546. 			public uint ID;
  547. 			public uint NumberOfButtons;
  548. 			public uint SampleRate;
  549. 		}
  550.  
  551. 		public struct DeviceInfoKeyboard
  552. 		{
  553. 			public uint Type;
  554. 			public uint SubType;
  555. 			public uint KeyboardMode;
  556. 			public uint NumberOfFunctionKeys;
  557. 			public uint NumberOfIndicators;
  558. 			public uint NumberOfKeysTotal;
  559. 			public bool IsUSBKeboard
  560. 			{
  561. 				get
  562. 				{
  563. 					return this.Type == 81; // http://msdn.microsoft.com/en-us/library/windows/desktop/ms724336%28v=vs.85%29.aspx
  564. 				}
  565. 			}
  566. 		}
  567.  
  568. 		public struct DeviceInfoHID
  569. 		{
  570. 			public uint VendorID;
  571. 			public uint ProductID;
  572. 			public uint VersionNumber;
  573. 			public ushort UsagePage;
  574. 			public ushort Usage;
  575. 		}
  576.  
  577. 		[StructLayout( LayoutKind.Sequential )]
  578. 		public struct RawInputDeviceList
  579. 		{
  580. 			public IntPtr DeviceHandle;
  581. 			public RawInputDeviceType DeviceType;
  582. 		}
  583.  
  584. 		[DllImport( "User32.dll", SetLastError = true )]
  585. 		public static extern uint GetRawInputDeviceList( IntPtr pRawInputDeviceList, ref uint uiNumDevices, uint cbSize );
  586.  
  587. 		[DllImport( "user32.dll", SetLastError = true )]
  588. 		public static extern uint GetRawInputDeviceInfo( IntPtr hDevice, RawInputDeviceInfoCommand uiCommand, IntPtr data, ref uint size );
  589. 	}
  590. }

page last modified: 2024-04-16; loaded in 0.0236 seconds