Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for hashardware.cs

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Management;
  5.  
  6.  
  7. namespace RobvanderWoude
  8. {
  9. 	internal class HasHardware
  10. 	{
  11. 		static readonly string progver = "1.05";
  12.  
  13.  
  14. 		#region Global Variables
  15.  
  16. 		static bool analog = false;
  17. 		static bool continueonerrors = false;
  18. 		static bool digital = false;
  19. 		static bool errors = false;
  20. 		static bool hideerrors = false;
  21. 		static bool includekeyboards = false;
  22. 		static bool includemice = false;
  23. 		static bool includemonitors = false;
  24. 		static bool ps2 = false;
  25. 		static bool quiet = false;
  26. 		static bool serial = false;
  27. 		static bool usb = false;
  28. 		static bool verbose = false;
  29. 		static bool yesno = false;
  30. 		static int keyboardcount = 0;
  31. 		static int monitorcount = 0;
  32. 		static int mousecount = 0;
  33. 		static string keyboardquery;
  34. 		static string keyboardtype;
  35. 		static string mousequery;
  36. 		static string mousetype;
  37. 		static List<SortedList<string, string>> monitors = new List<SortedList<string, string>>( );
  38. 		static SortedList<string, string> monitor;
  39. 		// Monitor/mouse/keyboard availability (root\CIMV2)
  40. 		static readonly Dictionary<int, string> Availability = new Dictionary<int, string>
  41. 		{
  42. 			{ 1, "Other" },
  43. 			{ 2, "Unknown" },
  44. 			{ 3, "Running/Full Power" },
  45. 			{ 4, "Warning" },
  46. 			{ 5, "In Test" },
  47. 			{ 6, "Not Applicable" },
  48. 			{ 7, "Power Off" },
  49. 			{ 8, "Off Line" },
  50. 			{ 9, "Off Duty" },
  51. 			{ 10, "Degraded" },
  52. 			{ 11, "Not Installed" },
  53. 			{ 12, "Install Error" },
  54. 			{ 13, "Power Save - Unknown" },
  55. 			{ 14, "Power Save - Low Power Mode" },
  56. 			{ 15, "Power Save - Standby" },
  57. 			{ 16, "Power Cycle" },
  58. 			{ 17, "Power Save - Warning" },
  59. 			{ 18, "Paused" },
  60. 			{ 19, "Not Ready" },
  61. 			{ 20, "Not Configured" },
  62. 			{ 21, "Quiesced" }
  63. 		};
  64. 		// Keyboard and mouse connector type (root\WMI)
  65. 		static readonly Dictionary<int, string> ConnectorType = new Dictionary<int, string>
  66. 		{
  67. 			{ 0, "PS/2" },
  68. 			{ 1, "Serial" },
  69. 			{ 2, "USB" },
  70. 		};
  71. 		// Mouse device interface (root\CIMV2)
  72. 		static readonly Dictionary<int, string> DeviceInterface = new Dictionary<int, string>
  73. 		{
  74. 			{ 1,"Other" },
  75. 			{ 2, "Unknown" },
  76. 			{ 3, "Serial" },
  77. 			{ 4, "PS/2" },
  78. 			{ 5, "Infrared" },
  79. 			{ 6, "HP-HIL" },
  80. 			{ 7, "Bus mouse" },
  81. 			{ 8, "ADB (Apple Desktop Bus)" },
  82. 			{ 160, "Bus mouse DB-9" },
  83. 			{ 161, "Bus mouse micro-DIN" },
  84. 			{ 162, "USB" }
  85. 		};
  86. 		// Mouse hardware type (root\WMI)
  87. 		static readonly Dictionary<int, string> HardwareType = new Dictionary<int, string>
  88. 		{
  89. 			{ 0, "Standard Mouse" },
  90. 			{ 1, "Standard Pointer" },
  91. 			{ 2, "Standard Absolute Pointer" },
  92. 			{ 3, "Tablet" },
  93. 			{ 4, "Touch Screen" },
  94. 			{ 5, "Pen" },
  95. 			{ 6, "Track Ball" },
  96. 			{ 256, "Other" }
  97. 		};
  98.  
  99. 		#endregion Global Variables
  100.  
  101.  
  102. 		static int Main( string[] args )
  103. 		{
  104. 			#region Initialize Variables
  105.  
  106. 			keyboardtype = string.Empty;
  107. 			keyboardquery = "SELECT * FROM MsKeyboard_PortInformation";
  108. 			string monitortype = string.Empty;
  109. 			string monitorquery = "SELECT * FROM Win32_DesktopMonitor WHERE NOT MonitorType='Default Monitor' AND MonitorManufacturer IS NOT NULL"; // common PNPDeviceID
  110. 			string monitordetails = "SELECT * FROM WmiMonitorBasicDisplayParams"; // common InstanceName
  111. 			mousetype = string.Empty;
  112. 			mousequery = "SELECT * FROM MSMouse_PortInformation";
  113.  
  114. 			#endregion Initialize Variables
  115.  
  116.  
  117. 			#region Parse Command Line
  118.  
  119. 			foreach ( string arg in args )
  120. 			{
  121. 				switch ( arg.ToUpper( ) )
  122. 				{
  123. 					case "/?":
  124. 						return ShowHelp( );
  125. 					case "/A":
  126. 						CheckArg( ref analog, arg );
  127. 						break;
  128. 					case "/C":
  129. 						CheckArg( ref continueonerrors, arg );
  130. 						break;
  131. 					case "/D":
  132. 						CheckArg( ref digital, arg );
  133. 						break;
  134. 					case "/H":
  135. 						CheckArg( ref hideerrors, arg );
  136. 						break;
  137. 					case "/I":
  138. 						CheckArg( ref includemonitors, arg );
  139. 						break;
  140. 					case "/K":
  141. 						CheckArg( ref includekeyboards, arg );
  142. 						break;
  143. 					case "/M":
  144. 						CheckArg( ref includemice, arg );
  145. 						break;
  146. 					case "/P":
  147. 						CheckArg( ref ps2, arg );
  148. 						break;
  149. 					case "/Q":
  150. 						CheckArg( ref quiet, arg );
  151. 						break;
  152. 					case "/S":
  153. 						CheckArg( ref serial, arg );
  154. 						break;
  155. 					case "/U":
  156. 						CheckArg( ref usb, arg );
  157. 						break;
  158. 					case "/V":
  159. 						CheckArg( ref verbose, arg );
  160. 						break;
  161. 					case "/Y":
  162. 						CheckArg( ref yesno, arg );
  163. 						break;
  164. 					default:
  165. 						return ShowHelp( "Invalid command line argument \"{0}\"", arg );
  166. 				}
  167. 			}
  168.  
  169. 			continueonerrors = continueonerrors || hideerrors;
  170.  
  171. 			if ( quiet && verbose )
  172. 			{
  173. 				Console.ForegroundColor = ConsoleColor.Red;
  174. 				Console.Error.Write( "ERROR:\t" );
  175. 				Console.ForegroundColor = ConsoleColor.White;
  176. 				Console.Error.WriteLine( "Command line switches /Q and /V are mutually exclusive" );
  177. 				Console.ResetColor( );
  178. 				errors = true;
  179. 			}
  180.  
  181. 			if ( errors )
  182. 			{
  183. 				return ShowHelp( );
  184. 			}
  185.  
  186. 			if ( !includekeyboards && !includemice && !includemonitors )
  187. 			{
  188. 				includekeyboards = true;
  189. 				includemice = true;
  190. 				includemonitors = true;
  191. 			}
  192.  
  193. 			if ( includekeyboards || includemice )
  194. 			{
  195. 				if ( !ps2 && !serial && !usb )
  196. 				{
  197. 					ps2 = true;
  198. 					serial = true;
  199. 					usb = true;
  200. 				}
  201. 			}
  202.  
  203. 			#endregion Parse Command Line
  204.  
  205.  
  206. 			if ( includekeyboards || includemice )
  207. 			{
  208. 				ConnectorTypeQuery( );
  209. 			}
  210.  
  211.  
  212. 			if ( includekeyboards )
  213. 			{
  214. 				#region Count Keyboards
  215.  
  216. 				try
  217. 				{
  218. 					ManagementObjectSearcher searcher = new ManagementObjectSearcher( @"root\WMI", keyboardquery );
  219. 					ManagementObjectCollection colItems = searcher.Get( );
  220. 					keyboardcount = colItems.Count;
  221. 					if ( !quiet )
  222. 					{
  223. 						ShowCount( keyboardcount, "keyboard", keyboardtype, "keyboards" );
  224. 					}
  225.  
  226.  
  227. 					#region Show Keyboards Details
  228.  
  229. 					if ( verbose && keyboardcount > 0 )
  230. 					{
  231. 						foreach ( ManagementObject queryObj in colItems.Cast<ManagementObject>( ) )
  232. 						{
  233. 							int connectortype = int.Parse( queryObj["ConnectorType"].ToString( ) );
  234. 							Console.WriteLine( "\tConnector Type : {0}", ConnectorType[connectortype] );
  235. 							Console.WriteLine( "\tFunction Keys  : {0}", queryObj["FunctionKeys"] );
  236. 							Console.WriteLine( "\tIndicators     : {0}", queryObj["Indicators"] );
  237. 							Console.WriteLine( );
  238. 							queryObj.Dispose( );
  239. 						}
  240. 					}
  241.  
  242. 					#endregion Show Keyboards Details
  243. 				}
  244. 				catch ( ManagementException e )
  245. 				{
  246. 					if ( hideerrors )
  247. 					{
  248. 						errors = true;
  249. 						// Plan B: use root\CIMV2 if access to root\WMI is denied
  250. 						Win32_Keyboard( );
  251. 					}
  252. 					else if ( continueonerrors )
  253. 					{
  254. 						Console.ForegroundColor = ConsoleColor.Red;
  255. 						Console.Error.Write( "\nERROR:\t" );
  256. 						Console.ResetColor( );
  257. 						Console.Error.WriteLine( "{0} (namespace: root/WMI; class: MsKeyboard_PortInformation)", e.Message );
  258. 						Console.WriteLine( "      \tTrying alternative query (namespace: root/CIMV2; class: Win32_Keyboard)\n" );
  259. 						errors = true;
  260. 						// Plan B: use root\CIMV2 if access to root\WMI is denied
  261. 						Win32_Keyboard( );
  262. 					}
  263. 					else
  264. 					{
  265. 						return ShowHelp( "{0} (namespace: root/WMI; class: MsKeyboard_PortInformation)", e.Message );
  266. 					}
  267. 				}
  268.  
  269. 				#endregion Count Keyboards
  270. 			}
  271.  
  272.  
  273. 			if ( includemonitors )
  274. 			{
  275. 				#region Prepare Monitor Query
  276.  
  277. 				if ( analog != digital )
  278. 				{
  279. 					if ( analog )
  280. 					{
  281. 						monitordetails += " WHERE VideoInputType='0'";
  282. 						monitortype += " analog";
  283. 					}
  284. 					else
  285. 					{
  286. 						monitordetails += " WHERE VideoInputType='1'";
  287. 						monitortype += " digital";
  288. 					}
  289. 				}
  290.  
  291. 				#endregion Prepare Monitor Query
  292.  
  293.  
  294. 				#region Count Monitors
  295.  
  296. 				ManagementObjectSearcher searcher = new ManagementObjectSearcher( @"root\WMI", monitordetails );
  297. 				ManagementObjectCollection colItems = searcher.Get( );
  298. 				monitorcount = colItems.Count;
  299. 				if ( !quiet )
  300. 				{
  301. 					ShowCount( monitorcount, "monitor", monitortype, "monitors" );
  302. 				}
  303.  
  304. 				#endregion Count Monitors
  305.  
  306.  
  307. 				#region Prepare Monitor Details Queries
  308.  
  309. 				searcher = new ManagementObjectSearcher( @"root\CIMV2", monitorquery );
  310. 				colItems = searcher.Get( );
  311. 				if ( verbose )
  312. 				{
  313. 					foreach ( ManagementObject queryObj in colItems.Cast<ManagementObject>( ) )
  314. 					{
  315. 						monitor = new SortedList<string, string>( );
  316. 						int availability = int.Parse( queryObj["Availability"].ToString( ) );
  317. 						monitor.Add( "Availability", Availability[availability] );
  318. 						monitor.Add( "Manufacturer", queryObj["MonitorManufacturer"].ToString( ) );
  319. 						monitor.Add( "Description", queryObj["MonitorType"].ToString( ) );
  320. 						string deviceid = queryObj["PNPDeviceID"].ToString( ).Replace( "&amp;", "&" );
  321. 						monitor.Add( "PnP Device ID", deviceid );
  322. 						monitor.Add( "Screen Height (px)", queryObj["ScreenHeight"].ToString( ) );
  323. 						monitor.Add( "Screen Width (px)", queryObj["ScreenWidth"].ToString( ) );
  324. 						monitor.Add( "Status", queryObj["Status"].ToString( ) );
  325. 						queryObj.Dispose( );
  326. 						WMIMonitorID( deviceid );
  327. 						string inputtype = monitor["Video Input (Monitor)"].ToLower( );
  328. 						if ( ( analog == digital ) || ( inputtype == "analog" && analog ) || ( inputtype == "digital" && digital ) )
  329. 						{
  330. 							monitors.Add( monitor );
  331. 						}
  332. 						//monitor.Clear( );
  333. 					}
  334.  
  335. 					// determine left column width
  336. 					int columnwidth = 0;
  337. 					foreach ( var mon in monitors )
  338. 					{
  339. 						foreach ( string key in mon.Keys )
  340. 						{
  341. 							columnwidth = Math.Max( columnwidth, key.Length );
  342. 						}
  343. 					}
  344.  
  345. 					// list a selection of all properties and values
  346. 					foreach ( var mon in monitors )
  347. 					{
  348. 						foreach ( string key in mon.Keys )
  349. 						{
  350. 							Console.WriteLine( "\t{0,-" + columnwidth + "} : {1}", key, mon[key] );
  351. 						}
  352. 						Console.WriteLine( );
  353. 					}
  354. 				}
  355.  
  356. 				#endregion Prepare Monitor Details Queries
  357. 			}
  358.  
  359.  
  360. 			if ( includemice )
  361. 			{
  362. 				#region Count Mice
  363.  
  364. 				try
  365. 				{
  366. 					ManagementObjectSearcher searcher = new ManagementObjectSearcher( @"root\WMI", mousequery );
  367. 					ManagementObjectCollection colItems = searcher.Get( );
  368. 					mousecount = colItems.Count;
  369. 					if ( !quiet )
  370. 					{
  371. 						ShowCount( mousecount, "mouse", mousetype, "mice" );
  372. 					}
  373.  
  374.  
  375. 					#region Show Mice Details
  376.  
  377. 					if ( verbose && mousecount > 0 )
  378. 					{
  379. 						foreach ( ManagementObject queryObj in colItems.Cast<ManagementObject>( ) )
  380. 						{
  381. 							Console.WriteLine( "\tButtons        : {0}", queryObj["Buttons"] );
  382. 							int connectortype = int.Parse( queryObj["ConnectorType"].ToString( ) );
  383. 							Console.WriteLine( "\tConnector Type : {0}", ConnectorType[connectortype] );
  384. 							int hardwaretype = int.Parse( queryObj["HardwareType"].ToString( ) );
  385. 							Console.WriteLine( "\tHardware Type  : {0}", HardwareType[hardwaretype] );
  386. 							Console.WriteLine( );
  387. 							queryObj.Dispose( );
  388. 						}
  389. 					}
  390.  
  391. 					#endregion Show Mice Details
  392. 				}
  393. 				catch ( ManagementException e )
  394. 				{
  395. 					if ( hideerrors )
  396. 					{
  397. 						errors = true;
  398. 						Win32_PointingDevice( );
  399. 					}
  400. 					else if ( continueonerrors )
  401. 					{
  402. 						Console.ForegroundColor = ConsoleColor.Red;
  403. 						Console.Error.Write( "\nERROR:\t" );
  404. 						Console.ResetColor( );
  405. 						Console.Error.WriteLine( "{0} (namespace: root/WMI; class: MSMouse_PortInformation)", e.Message );
  406. 						Console.WriteLine( "      \tTrying alternative query (namespace: root/CIMV2; class: Win32_PointingDevice)\n" );
  407. 						errors = true;
  408. 						Win32_PointingDevice( );
  409. 					}
  410. 					else
  411. 					{
  412. 						return ShowHelp( "{0} (namespace: root/WMI; class: MSMouse_PortInformation)", e.Message );
  413. 					}
  414. 				}
  415.  
  416. 				#endregion Count Mice
  417. 			}
  418.  
  419.  
  420. 			// calculate return code
  421. 			if ( errors && !hideerrors )
  422. 			{
  423. 				return -1;
  424. 			}
  425. 			else if ( yesno )
  426. 			{
  427. 				int rc = 0;
  428. 				if ( keyboardcount > 0 )
  429. 				{
  430. 					rc += 100;
  431. 				}
  432. 				if ( monitorcount > 0 )
  433. 				{
  434. 					rc += 10;
  435. 				}
  436.                 if ( mousecount > 0 )
  437.                 {
  438. 					rc += 1;
  439.                 }
  440.                 return rc;
  441. 			}
  442. 			else
  443. 			{
  444. 				return keyboardcount + monitorcount + mousecount;
  445. 			}
  446. 		}
  447.  
  448.  
  449. 		static string Chain( UInt16[] chararray )
  450. 		{
  451. 			string charstring = null;
  452. 			foreach ( UInt16 chr in chararray )
  453. 			{
  454. 				if ( chr == 0 )
  455. 				{
  456. 					return charstring;
  457. 				}
  458. 				else
  459. 				{
  460. 					charstring += ( (char)chr ).ToString( );
  461. 				}
  462. 			}
  463. 			return charstring;
  464. 		}
  465.  
  466.  
  467. 		public static void CheckArg( ref bool variable, string argument )
  468. 		{
  469. 			if ( variable )
  470. 			{
  471. 				Console.ForegroundColor = ConsoleColor.Red;
  472. 				Console.Error.Write( "ERROR:\t" );
  473. 				Console.ForegroundColor = ConsoleColor.White;
  474. 				Console.Error.WriteLine( "Duplicate command line switch {0}", argument.ToUpper( ) );
  475. 				Console.ResetColor( );
  476. 				errors = true;
  477. 			}
  478. 			else
  479. 			{
  480. 				variable = true;
  481. 			}
  482. 		}
  483.  
  484.  
  485. 		public static void ConnectorTypeQuery( )
  486. 		{
  487. 			string query = string.Empty;
  488. 			string type = string.Empty;
  489.  
  490. 			if ( ps2 && serial && usb )
  491. 			{
  492. 				ps2 = false;
  493. 				serial = false;
  494. 				usb = false;
  495. 			}
  496.  
  497. 			if ( ps2 || serial || usb )
  498. 			{
  499. 				if ( ps2 )
  500. 				{
  501. 					if ( query.Contains( "WHERE" ) )
  502. 					{
  503. 						query += " OR ConnectorType='0'";
  504. 					}
  505. 					else
  506. 					{
  507. 						query += " WHERE ConnectorType='0'";
  508. 					}
  509. 					if ( string.IsNullOrWhiteSpace( type ) )
  510. 					{
  511. 						type += " PS/2";
  512. 					}
  513. 					else
  514. 					{
  515. 						type += " or PS/2";
  516. 					}
  517. 				}
  518. 				if ( serial )
  519. 				{
  520. 					if ( query.Contains( "WHERE" ) )
  521. 					{
  522. 						query += " OR ConnectorType='1'";
  523. 					}
  524. 					else
  525. 					{
  526. 						query += " WHERE ConnectorType='1'";
  527. 					}
  528. 					if ( string.IsNullOrWhiteSpace( type ) )
  529. 					{
  530. 						type += " serial";
  531. 					}
  532. 					else
  533. 					{
  534. 						type += " or serial";
  535. 					}
  536. 				}
  537. 				if ( usb )
  538. 				{
  539. 					if ( query.Contains( "WHERE" ) )
  540. 					{
  541. 						query += " OR ConnectorType='2'";
  542. 					}
  543. 					else
  544. 					{
  545. 						query += " WHERE ConnectorType='2'";
  546. 					}
  547. 					if ( string.IsNullOrWhiteSpace( type ) )
  548. 					{
  549. 						type += " USB";
  550. 					}
  551. 					else
  552. 					{
  553. 						type += " or USB";
  554. 					}
  555. 				}
  556. 			}
  557.  
  558. 			keyboardquery += query;
  559. 			keyboardtype += type;
  560. 			mousequery += query;
  561. 			mousetype += type;
  562. 		}
  563.  
  564.  
  565. 		public static void ShowCount( int count, string deviceclass, string devicetype, string plural )
  566. 		{
  567. 			if ( !quiet )
  568. 			{
  569. 				if ( count == 0 )
  570. 				{
  571. 					Console.ForegroundColor = ConsoleColor.Red;
  572. 					Console.Write( "No" );
  573. 					Console.ResetColor( );
  574. 					Console.WriteLine( "{0} {1} detected", devicetype, deviceclass );
  575. 					if ( verbose )
  576. 					{
  577. 						Console.WriteLine( );
  578. 					}
  579. 				}
  580. 				else if ( count == 1 )
  581. 				{
  582. 					Console.ForegroundColor = ConsoleColor.Green;
  583. 					Console.Write( "1" );
  584. 					Console.ResetColor( );
  585. 					Console.Write( "{0} {1} detected", devicetype, deviceclass );
  586. 					if ( verbose )
  587. 					{
  588. 						Console.Write( ":" );
  589. 					}
  590. 					Console.WriteLine( );
  591. 				}
  592. 				else
  593. 				{
  594. 					Console.ForegroundColor = ConsoleColor.Green;
  595. 					Console.Write( count );
  596. 					Console.ResetColor( );
  597. 					Console.Write( "{0} {1} detected", devicetype, plural );
  598. 					if ( verbose )
  599. 					{
  600. 						Console.Write( ":" );
  601. 					}
  602. 					Console.WriteLine( );
  603. 				}
  604. 			}
  605. 		}
  606.  
  607.  
  608. 		public static int ShowHelp( params string[] errmsg )
  609. 		{
  610. 			#region Error Message
  611.  
  612. 			if ( errmsg.Length > 0 )
  613. 			{
  614. 				List<string> errargs = new List<string>( errmsg );
  615. 				errargs.RemoveAt( 0 );
  616. 				Console.Error.WriteLine( );
  617. 				Console.ForegroundColor = ConsoleColor.Red;
  618. 				Console.Error.Write( "ERROR:\t" );
  619. 				Console.ForegroundColor = ConsoleColor.White;
  620. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  621. 				Console.ResetColor( );
  622. 			}
  623.  
  624. 			#endregion Error Message
  625.  
  626.  
  627. 			#region Help Text
  628.  
  629. 			/*
  630. 			HasHardware.exe,  Version 1.03
  631. 			Check the actual number of connected input and video devices available
  632.  
  633. 			Usage:    HasHardware.exe  [ hardware  [ type ] ]  [ output ]
  634.  
  635. 			Hardware: /I  check dIsplay (monitors) only (default: keyboard, monitor, mouse)
  636. 					  /K  check Keyboards only          (default: keyboard, monitor, mouse)
  637. 					  /M  check Mice only               (default: keyboard, monitor, mouse)
  638.  
  639. 			Type:     /A  count Analog (VGA) monitors only          (default: all types)
  640. 					  /D  count Digital (DVI/HDMI/DP) monitors only (default: all types)
  641. 					  /P  count PS/2 mice and/or keyboards only     (default: all types)
  642. 					  /S  count Serial mice and/or keyboards only   (default: all types)
  643. 					  /U  count USB mice and/or keyboards only      (default: all types)
  644.  
  645. 			Output:   /C  Continue on (access denied) errors (default: terminate on error)
  646. 			          /H  Hide (access denied) errors        (default: terminate on error)
  647. 			          /Q  Quiet mode: no screen output       (default: # per device class)
  648. 					  /V  Verbose output: display properties (default: # per device class)
  649. 					  /Y  YesNo mode: available or not?      (see Notes)
  650.  
  651. 			Notes:    This program requires elevated privileges.
  652. 					  Hardware and types can be combined, e.g. /K /M /P /U for PS/2 and
  653. 					  USB keyboards and mice; if no type is specified, all types will be
  654. 			          listed.
  655. 					  Command line switches /Q and /V are mutually exclusive.
  656. 			          In case of access denied errors, switches /C and /H will use
  657. 			          alternative WMI queries to count keyboards and/or mice; with /C an
  658. 			          error message will be displayed, followed by the "plan B count", and
  659. 			          return code will be -1; with /H the "plan B count" will be shown
  660. 			          without error message, and return code will not be affected; the
  661. 			          alternative WMI queries may return less details, e.g. there is no way
  662. 			          to determine the keyboard connector type without elevated privileges.
  663. 					  Return code equals the sum of detected matching devices, or with /Y
  664. 			          100 x K + 10 x V + M (K = keyboard count, V = monitors, M = mice),
  665. 			          or -1 in case of command line or access denied errors.
  666.  
  667. 			Examples:   HasHardware
  668. 			            Show keyboards, monitors and mice (all types)
  669. 			            Return code equals total number of matching devices
  670.  
  671. 			            HasHardware /Y
  672. 			            Show keyboards, monitors and mice
  673. 			            Return code 111 if at least 1 keyboard and at least 1 monitor and
  674. 			            at least 1 mouse were detected
  675.  
  676. 			            HasHardware /M /K /U /Y
  677. 			            Show USB keyboards and mice, ignore monitors
  678. 			            Return code 101 if at least 1 USB keyboard and at least 1 USB mouse
  679. 			            were detected
  680.  
  681. 			            HasHardware /U /D
  682. 			            Show USB keyboards and mice and digital moitors
  683. 			            Return code equals total number of matching devices
  684.  
  685. 			Written by Rob van der Woude
  686. 			https://www.robvanderwoude.com
  687. 			*/
  688.  
  689. 			#endregion Help Text
  690.  
  691.  
  692. 			#region Display Help Text
  693.  
  694. 			Console.Error.WriteLine( );
  695.  
  696. 			Console.Error.WriteLine( "HasHardware.exe,  Version {0}", progver );
  697.  
  698. 			Console.Error.WriteLine( "Check the actual number of connected input and video devices available" );
  699.  
  700. 			Console.Error.WriteLine( );
  701.  
  702. 			Console.Error.Write( "Usage:    " );
  703. 			Console.ForegroundColor = ConsoleColor.White;
  704. 			Console.Error.WriteLine( "HasHardware.exe  [ hardware  [ type ] ]  [ output ]" );
  705. 			Console.ResetColor( );
  706.  
  707. 			Console.Error.WriteLine( );
  708.  
  709. 			Console.Error.Write( "Hardware: " );
  710. 			Console.ForegroundColor = ConsoleColor.White;
  711. 			Console.Error.Write( "/I" );
  712. 			Console.ResetColor( );
  713. 			Console.Error.Write( "  check d" );
  714. 			Console.ForegroundColor = ConsoleColor.White;
  715. 			Console.Error.Write( "I" );
  716. 			Console.ResetColor( );
  717. 			Console.Error.WriteLine( "splay (monitors) only (default: keyboard, monitor, mouse)" );
  718.  
  719. 			Console.ForegroundColor = ConsoleColor.White;
  720. 			Console.Error.Write( "          /K" );
  721. 			Console.ResetColor( );
  722. 			Console.Error.Write( "  check " );
  723. 			Console.ForegroundColor = ConsoleColor.White;
  724. 			Console.Error.Write( "K" );
  725. 			Console.ResetColor( );
  726. 			Console.Error.WriteLine( "eyboards only          (default: keyboard, monitor, mouse)" );
  727.  
  728. 			Console.ForegroundColor = ConsoleColor.White;
  729. 			Console.Error.Write( "          /M" );
  730. 			Console.ResetColor( );
  731. 			Console.Error.Write( "  check " );
  732. 			Console.ForegroundColor = ConsoleColor.White;
  733. 			Console.Error.Write( "M" );
  734. 			Console.ResetColor( );
  735. 			Console.Error.WriteLine( "ice only               (default: keyboard, monitor, mouse)" );
  736.  
  737. 			Console.Error.WriteLine( );
  738.  
  739. 			Console.Error.Write( "Type:     " );
  740. 			Console.ForegroundColor = ConsoleColor.White;
  741. 			Console.Error.Write( "/A" );
  742. 			Console.ResetColor( );
  743. 			Console.Error.Write( "  count " );
  744. 			Console.ForegroundColor = ConsoleColor.White;
  745. 			Console.Error.Write( "A" );
  746. 			Console.ResetColor( );
  747. 			Console.Error.WriteLine( "nalog (VGA) monitors only          (default: all types)" );
  748.  
  749. 			Console.ForegroundColor = ConsoleColor.White;
  750. 			Console.Error.Write( "          /D" );
  751. 			Console.ResetColor( );
  752. 			Console.Error.Write( "  count " );
  753. 			Console.ForegroundColor = ConsoleColor.White;
  754. 			Console.Error.Write( "D" );
  755. 			Console.ResetColor( );
  756. 			Console.Error.WriteLine( "igital (DVI/HDMI/DP) monitors only (default: all types)" );
  757.  
  758. 			Console.ForegroundColor = ConsoleColor.White;
  759. 			Console.Error.Write( "          /P" );
  760. 			Console.ResetColor( );
  761. 			Console.Error.Write( "  count " );
  762. 			Console.ForegroundColor = ConsoleColor.White;
  763. 			Console.Error.Write( "P" );
  764. 			Console.ResetColor( );
  765. 			Console.Error.WriteLine( "S/2 mice and/or keyboards only     (default: all types)" );
  766.  
  767. 			Console.ForegroundColor = ConsoleColor.White;
  768. 			Console.Error.Write( "          /S" );
  769. 			Console.ResetColor( );
  770. 			Console.Error.Write( "  count " );
  771. 			Console.ForegroundColor = ConsoleColor.White;
  772. 			Console.Error.Write( "S" );
  773. 			Console.ResetColor( );
  774. 			Console.Error.WriteLine( "erial mice and/or keyboards only   (default: all types)" );
  775.  
  776. 			Console.ForegroundColor = ConsoleColor.White;
  777. 			Console.Error.Write( "          /U" );
  778. 			Console.ResetColor( );
  779. 			Console.Error.Write( "  count " );
  780. 			Console.ForegroundColor = ConsoleColor.White;
  781. 			Console.Error.Write( "U" );
  782. 			Console.ResetColor( );
  783. 			Console.Error.WriteLine( "SB mice and/or keyboards only      (default: all types)" );
  784.  
  785. 			Console.Error.WriteLine( );
  786.  
  787. 			Console.Error.Write( "Output:   " );
  788. 			Console.ForegroundColor = ConsoleColor.White;
  789. 			Console.Error.Write( "/C  C" );
  790. 			Console.ResetColor( );
  791. 			Console.Error.WriteLine( "ontinue on (access denied) errors (default: terminate on error)" );
  792.  
  793. 			Console.ForegroundColor = ConsoleColor.White;
  794. 			Console.Error.Write( "          /H  H" );
  795. 			Console.ResetColor( );
  796. 			Console.Error.WriteLine( "ide (access denied) errors        (default: terminate on error)" );
  797.  
  798. 			Console.ForegroundColor = ConsoleColor.White;
  799. 			Console.Error.Write( "          /Q  Q" );
  800. 			Console.ResetColor( );
  801. 			Console.Error.WriteLine( "uiet mode: no screen output       (default: # per device class)" );
  802.  
  803. 			Console.ForegroundColor = ConsoleColor.White;
  804. 			Console.Error.Write( "          /V  V" );
  805. 			Console.ResetColor( );
  806. 			Console.Error.WriteLine( "erbose output: display properties (default: # per device class)" );
  807.  
  808. 			Console.ForegroundColor = ConsoleColor.White;
  809. 			Console.Error.Write( "          /Y  Y" );
  810. 			Console.ResetColor( );
  811. 			Console.Error.WriteLine( "esNo mode: available or not?      (see Notes)" );
  812.  
  813. 			Console.Error.WriteLine( );
  814.  
  815. 			Console.Error.WriteLine( "Notes:    This program requires elevated privileges." );
  816.  
  817. 			Console.Error.Write( "          Hardware and types can be combined, e.g. " );
  818. 			Console.ForegroundColor = ConsoleColor.White;
  819. 			Console.Error.Write( "/K /M /P /U" );
  820. 			Console.ResetColor( );
  821. 			Console.Error.WriteLine( " for PS/2 and" );
  822.  
  823. 			Console.Error.WriteLine( "          USB keyboards and mice; if no type is specified, all types will be" );
  824.  
  825. 			Console.Error.WriteLine( "          listed." );
  826.  
  827. 			Console.Error.Write( "          Command line switches " );
  828. 			Console.ForegroundColor = ConsoleColor.White;
  829. 			Console.Error.Write( "/Q" );
  830. 			Console.ResetColor( );
  831. 			Console.Error.Write( " and " );
  832. 			Console.ForegroundColor = ConsoleColor.White;
  833. 			Console.Error.Write( "/V" );
  834. 			Console.ResetColor( );
  835. 			Console.Error.WriteLine( " are mutually exclusive." );
  836.  
  837. 			Console.Error.Write( "          In case of access denied errors, switches " );
  838. 			Console.ForegroundColor = ConsoleColor.White;
  839. 			Console.Error.Write( "/C" );
  840. 			Console.ResetColor( );
  841. 			Console.Error.Write( " and " );
  842. 			Console.ForegroundColor = ConsoleColor.White;
  843. 			Console.Error.Write( "/H" );
  844. 			Console.ResetColor( );
  845. 			Console.Error.WriteLine( " will use" );
  846.  
  847. 			Console.Error.Write( "          alternative WMI queries to count keyboards and/or mice; with " );
  848. 			Console.ForegroundColor = ConsoleColor.White;
  849. 			Console.Error.Write( "/C" );
  850. 			Console.ResetColor( );
  851. 			Console.Error.WriteLine( " an" );
  852.  
  853. 			Console.Error.WriteLine( "          error message will be displayed, followed by the \"plan B count\", and" );
  854.  
  855. 			Console.Error.Write( "          return code will equal -1; with " );
  856. 			Console.ForegroundColor = ConsoleColor.White;
  857. 			Console.Error.Write( "/H" );
  858. 			Console.ResetColor( );
  859. 			Console.Error.WriteLine( " the \"plan B count\" will be shown" );
  860.  
  861. 			Console.Error.WriteLine( "          without error message, and return code will not be affected; the" );
  862.  
  863. 			Console.Error.WriteLine( "          alternative WMI queries may return less details, e.g. there is no way" );
  864.  
  865. 			Console.Error.WriteLine( "          to determine the keyboard connector type without elevated privileges." );
  866.  
  867. 			Console.Error.Write( "          Return code equals the sum of detected matching devices, or with " );
  868. 			Console.ForegroundColor = ConsoleColor.White;
  869. 			Console.Error.WriteLine( "/Y" );
  870.  
  871. 			Console.Error.Write( "          100 x K + 10 x V + M" );
  872. 			Console.ResetColor( );
  873. 			Console.Error.WriteLine( "  (K = keyboards, V = monitors, M = mice)," );
  874.  
  875. 			Console.Error.WriteLine( "          or -1 in case of command line or access denied errors." );
  876.  
  877. 			Console.Error.WriteLine( );
  878.  
  879. 			Console.Error.Write( "Examples:   " );
  880. 			Console.ForegroundColor = ConsoleColor.White;
  881. 			Console.Error.WriteLine( "HasHardware" );
  882. 			Console.ResetColor( );
  883.  
  884. 			Console.Error.WriteLine( "            Show keyboards, monitors and mice (all types)" );
  885.  
  886. 			Console.Error.WriteLine( "            Return code equals total number of matching devices" );
  887.  
  888. 			Console.Error.WriteLine( );
  889.  
  890. 			Console.ForegroundColor = ConsoleColor.White;
  891. 			Console.Error.WriteLine( "            HasHardware /Y" );
  892. 			Console.ResetColor( );
  893.  
  894. 			Console.Error.WriteLine( "            Show keyboards, monitors and mice" );
  895.  
  896. 			Console.Error.WriteLine( "            Return code 111 if at least 1 keyboard and at least 1 monitor and" );
  897.  
  898. 			Console.Error.WriteLine( "            at least 1 mouse were detected" );
  899.  
  900. 			Console.Error.WriteLine( );
  901.  
  902. 			Console.ForegroundColor = ConsoleColor.White;
  903. 			Console.Error.WriteLine( "            HasHardware /M /K /U /Y" );
  904. 			Console.ResetColor( );
  905.  
  906. 			Console.Error.WriteLine( "            Show USB keyboards and mice, ignore monitors" );
  907.  
  908. 			Console.Error.WriteLine( "            Return code 101 if at least 1 USB keyboard and at least 1 USB mouse" );
  909.  
  910. 			Console.Error.WriteLine( "            were detected" );
  911.  
  912. 			Console.Error.WriteLine( );
  913.  
  914. 			Console.ForegroundColor = ConsoleColor.White;
  915. 			Console.Error.WriteLine( "            HasHardware /U /D" );
  916. 			Console.ResetColor( );
  917.  
  918. 			Console.Error.WriteLine( "            Show USB keyboards and mice and digital moitors" );
  919.  
  920. 			Console.Error.WriteLine( "            Return code equals total number of matching devices" );
  921.  
  922. 			Console.Error.WriteLine( );
  923.  
  924. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  925.  
  926. 			Console.Error.WriteLine( "https://www.robvanderwoude.com" );
  927.  
  928. 			#endregion Display Help Text
  929.  
  930.  
  931. 			return -1;
  932. 		}
  933.  
  934.  
  935. 		static string VideoOutputTechnology( string id )
  936. 		{
  937. 			string result = null;
  938.  
  939. 			Dictionary<long, string> VideoOutputTechnology = new Dictionary<long, string>
  940. 			{
  941. 				{ -2, "unknown connector(s)" },
  942. 				{ -1, "other connector(s)" },
  943. 				{ 0, "HD15 (VGA) connector" },
  944. 				{ 1, "S-video connector" },
  945. 				{ 2, "composite video connectors" },
  946. 				{ 3, "component video connectors" },
  947. 				{ 4, "Digital Video Interface (DVI) connector" },
  948. 				{ 5, "High-Definition Multimedia Interface (HDMI) connector" },
  949. 				{ 6, "Low Voltage Differential Swing (LVDS) or Mobile Industry Processor Interface (MIPI) Digital Serial Interface (DSI) connector" },
  950. 				{ 8, "D-Jpn connector" },
  951. 				{ 9, "SDI connector" },
  952. 				{ 10, "external display port" },
  953. 				{ 11, "embedded display port" },
  954. 				{ 12, "external Unified Display Interface (UDI)" },
  955. 				{ 13, "embedded Unified Display Interface (UDI)" },
  956. 				{ 14, "dongle cable that supports SDTV" },
  957. 				{ 15, "wireless Miracast" },
  958. 				{ 16, "wired indirect" },
  959. 				{ 0x80000000, "internal connection (e.g. laptop)" }
  960. 			};
  961.  
  962. 			// This query gets the monitor connector type ON THE VIDEO CARD SIDE
  963. 			string query = string.Format( "SELECT * FROM WmiMonitorConnectionParams WHERE InstanceName='{0}'", id ).Replace( @"\", @"\\" );
  964. 			ManagementObjectSearcher searcher = new ManagementObjectSearcher( @"root\WMI", query );
  965. 			ManagementObjectCollection colItems = searcher.Get( );
  966. 			foreach ( ManagementObject queryObj in colItems.Cast<ManagementObject>( ) )
  967. 			{
  968. 				long videooutputtechnology = long.Parse( queryObj["VideoOutputTechnology"].ToString( ) );
  969. 				result = VideoOutputTechnology[videooutputtechnology];
  970. 				queryObj.Dispose( );
  971. 			}
  972.  
  973. 			return result;
  974. 		}
  975.  
  976.  
  977. 		static void Win32_Keyboard( )
  978. 		{
  979. 			ManagementObjectSearcher searcher = new ManagementObjectSearcher( @"root\CIMV2", "SELECT * FROM Win32_Keyboard" );
  980. 			ManagementObjectCollection colItems = searcher.Get( );
  981. 			keyboardcount = colItems.Count;
  982. 			ShowCount( keyboardcount, "keyboard", string.Empty, "keyboards" ); // unable to determine connector type without elevated privileges
  983. 			if ( verbose && keyboardcount > 0 )
  984. 			{
  985. 				foreach ( ManagementObject queryObj in colItems.Cast<ManagementObject>( ) )
  986. 				{
  987. 					int availability = 2; // default: Unknown
  988. 					if ( !( queryObj["Availability"] is null ) )
  989. 					{
  990. 						availability = int.Parse( queryObj["Availability"].ToString( ) );
  991. 					}
  992. 					Console.WriteLine( "\tAvailability            : {0}", Availability[availability] );
  993. 					Console.WriteLine( "\tCaption                 : {0}", queryObj["Caption"] );
  994. 					Console.WriteLine( "\tDescription             : {0}", queryObj["Description"] );
  995. 					Console.WriteLine( "\tLayout                  : {0}", queryObj["Layout"] );
  996. 					Console.WriteLine( "\tName                    : {0}", queryObj["Name"] );
  997. 					Console.WriteLine( "\tNumber of Function Keys : {0}", queryObj["NumberOfFunctionKeys"] );
  998. 					Console.WriteLine( "\tPnP Device ID           : {0}", queryObj["PNPDeviceID"] );
  999. 					Console.WriteLine( "\tStatus                  : {0}", queryObj["Status"] );
  1000. 					Console.WriteLine( );
  1001. 					queryObj.Dispose( );
  1002. 				}
  1003. 				Console.WriteLine( );
  1004. 			}
  1005. 		}
  1006.  
  1007.  
  1008. 		static void Win32_PointingDevice( )
  1009. 		{
  1010. 			string query = "SELECT * FROM Win32_PointingDevice";
  1011. 			if ( !( ps2 && serial && usb ) || ps2 || serial || usb )
  1012. 			{
  1013. 				if ( ps2 )
  1014. 				{
  1015. 					if ( query.Contains( "WHERE" ) )
  1016. 					{
  1017. 						query += " OR DeviceInterface='4'";
  1018. 					}
  1019. 					else
  1020. 					{
  1021. 						query += " WHERE DeviceInterface='4'";
  1022. 					}
  1023. 				}
  1024. 				if ( serial )
  1025. 				{
  1026. 					if ( query.Contains( "WHERE" ) )
  1027. 					{
  1028. 						query += " OR DeviceInterface='3'";
  1029. 					}
  1030. 					else
  1031. 					{
  1032. 						query += " WHERE DeviceInterface='3'";
  1033. 					}
  1034. 				}
  1035. 				if ( usb )
  1036. 				{
  1037. 					if ( query.Contains( "WHERE" ) )
  1038. 					{
  1039. 						query += " OR DeviceInterface='162'";
  1040. 					}
  1041. 					else
  1042. 					{
  1043. 						query += " WHERE DeviceInterface='162'";
  1044. 					}
  1045. 				}
  1046. 			}
  1047. 			ManagementObjectSearcher searcher = new ManagementObjectSearcher( @"root\CIMV2", query );
  1048. 			ManagementObjectCollection colItems = searcher.Get( );
  1049. 			mousecount = colItems.Count;
  1050. 			ShowCount( mousecount, "mouse", mousetype, "mice" );
  1051. 			if ( verbose && mousecount > 0 )
  1052. 			{
  1053. 				foreach ( ManagementObject queryObj in colItems.Cast<ManagementObject>( ) )
  1054. 				{
  1055. 					int availability = 2; // default: Unknown
  1056. 					if ( !( queryObj["Availability"] is null ) )
  1057. 					{
  1058. 						availability = int.Parse( queryObj["Availability"].ToString( ) );
  1059. 					}
  1060. 					Console.WriteLine( "\tAvailability      : {0}", Availability[availability] );
  1061. 					int deviceinterface = int.Parse( queryObj["DeviceInterface"].ToString( ) );
  1062. 					Console.WriteLine( "\tDevice Interface  : {0}", DeviceInterface[deviceinterface] );
  1063. 					Console.WriteLine( "\tHardware Type     : {0}", queryObj["HardwareType"] );
  1064. 					Console.WriteLine( "\tManufacturer      : {0}", queryObj["Manufacturer"] );
  1065. 					Console.WriteLine( "\tNumber of Buttons : {0}", queryObj["NumberOfButtons"] );
  1066. 					Console.WriteLine( "\tPnP Device ID     : {0}", queryObj["PNPDeviceID"] );
  1067. 					Console.WriteLine( "\tPointing Type     : {0}", queryObj["PointingType"] );
  1068. 					Console.WriteLine( "\tStatus            : {0}", queryObj["Status"] );
  1069. 					queryObj.Dispose( );
  1070. 				}
  1071. 				Console.WriteLine( );
  1072. 			}
  1073. 		}
  1074.  
  1075.  
  1076. 		static void WmiMonitorBasicDisplayParams( string id )
  1077. 		{
  1078. 			SortedList<int, string> VideoInputType = new SortedList<int, string>
  1079. 			{
  1080. 				{ 0, "Analog" },
  1081. 				{ 1, "Digital" }
  1082. 			};
  1083.  
  1084. 			int videoinputtype;
  1085. 			string query = string.Format( "SELECT * FROM WmiMonitorBasicDisplayParams WHERE InstanceName='{0}'", id ).Replace( @"\", @"\\" );
  1086. 			ManagementObjectSearcher searcher = new ManagementObjectSearcher( @"root\WMI", query );
  1087. 			ManagementObjectCollection colItems = searcher.Get( );
  1088. 			foreach ( ManagementObject queryObj in colItems.Cast<ManagementObject>( ) )
  1089. 			{
  1090. 				monitor.Add( "Screen Width (cm)", queryObj["MaxHorizontalImageSize"].ToString( ) );
  1091. 				monitor.Add( "Screen Height (cm)", queryObj["MaxVerticalImageSize"].ToString( ) );
  1092. 				videoinputtype = int.Parse( queryObj["VideoInputType"].ToString( ) );
  1093. 				monitor.Add( "Video Input (Monitor)", VideoInputType[videoinputtype] );
  1094. 			}
  1095. 		}
  1096.  
  1097.  
  1098. 		static void WMIMonitorID( string id )
  1099. 		{
  1100. 			string query = string.Format( "SELECT * FROM WmiMonitorID WHERE InstanceName LIKE '{0}%'", id ).Replace( @"\", @"\\" );
  1101. 			ManagementObjectSearcher searcher = new ManagementObjectSearcher( @"root\WMI", query );
  1102. 			ManagementObjectCollection colItems = searcher.Get( );
  1103. 			foreach ( ManagementObject queryObj in colItems.Cast<ManagementObject>( ) )
  1104. 			{
  1105. 				monitor.Add( "Active", queryObj["Active"].ToString( ) );
  1106. 				string instancename = queryObj["InstanceName"].ToString( );
  1107. 				monitor.Add( "Product Code", Chain( (UInt16[])queryObj["ProductCodeID"] ) );
  1108. 				monitor.Add( "Serial Number", Chain( (UInt16[])queryObj["SerialNumberID"] ) );
  1109. 				monitor.Add( "Monitor Type", Chain( (UInt16[])queryObj["UserFriendlyName"] ) );
  1110. 				monitor.Add( "Video Output (Display Adapter)", VideoOutputTechnology( instancename ) );
  1111. 				monitor.Add( "Week of Manufacture", queryObj["WeekOfManufacture"].ToString( ) );
  1112. 				monitor.Add( "Year of Manufacture", queryObj["YearOfManufacture"].ToString( ) );
  1113. 				queryObj.Dispose( );
  1114. 				WmiMonitorBasicDisplayParams( instancename );
  1115. 			}
  1116. 		}
  1117. 	}
  1118. }

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