Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for activatewindow.cs

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Runtime.InteropServices;
  6. using System.Text;
  7.  
  8.  
  9. namespace RobvanderWoude
  10. {
  11. 	class ActivateWindow
  12. 	{
  13. 		static readonly string progver = "1.03";
  14.  
  15.  
  16. 		static bool debug = false;
  17. 		static bool exactmatch = false;
  18. 		static List<string> windowtitles = new List<string>( );
  19. 		static string exact = "partial ";
  20. 		static string matchingtitle = string.Empty;
  21. 		static string progname = string.Empty;
  22. 		static string windowtitle = string.Empty;
  23.  
  24.  
  25. 		static int Main( string[] args )
  26. 		{
  27. 			bool querycurrent = false;
  28. 			bool useprogname = false;
  29.  
  30.  
  31. 			#region Parse and Validate Command Line
  32.  
  33. 			if ( args.Length == 0 )
  34. 			{
  35. 				return ShowHelp( );
  36. 			}
  37.  
  38. 			foreach ( string arg in args )
  39. 			{
  40. 				if ( arg[0] == '/' )
  41. 				{
  42. 					switch ( arg.ToUpper( ) )
  43. 					{
  44. 						case "/?":
  45. 							return ShowHelp( );
  46. 						case "/C":
  47. 							if ( querycurrent )
  48. 							{
  49. 								return ShowHelp( "Duplicate switch /C" );
  50. 							}
  51. 							querycurrent = true;
  52. 							break;
  53. 						case "/D":
  54. 							if ( useprogname )
  55. 							{
  56. 								return ShowHelp( "Switches /P and /D are mutually exclusive" );
  57. 							}
  58. 							if ( debug )
  59. 							{
  60. 								return ShowHelp( "Duplicate switch /D" );
  61. 							}
  62. 							debug = true;
  63. 							break;
  64. 						case "/P":
  65. 							if ( debug )
  66. 							{
  67. 								return ShowHelp( "Switches /P and /D are mutually exclusive" );
  68. 							}
  69. 							if ( useprogname )
  70. 							{
  71. 								return ShowHelp( "Duplicate switch /P" );
  72. 							}
  73. 							useprogname = true;
  74. 							break;
  75. 						case "/X":
  76. 							if ( exactmatch )
  77. 							{
  78. 								return ShowHelp( "Duplicate switch /X" );
  79. 							}
  80. 							exactmatch = true;
  81. 							exact = "exact ";
  82. 							break;
  83. 						default:
  84. 								return ShowHelp( "Invalid switch \"{0}\"", arg );
  85. 					}
  86. 				}
  87. 				else
  88. 				{
  89. 					if ( !windowtitles.Contains( arg ) )
  90. 					{
  91. 						windowtitles.Add( arg );
  92. 					}
  93. 				}
  94. 			}
  95.  
  96. 			if ( useprogname )
  97. 			{
  98. 				if ( exactmatch )
  99. 				{
  100. 					return ShowHelp( "Switches /P and /X are mutually exclusive" );
  101. 				}
  102. 				if ( windowtitles.Count == 1 )
  103. 				{
  104. 					progname = windowtitles[0];
  105. 				}
  106. 				else
  107. 				{
  108. 					return ShowHelp( "Specifie a single program executable when using /P switch" );
  109. 				}
  110. 			}
  111.  
  112. 			if ( querycurrent && args.Length > 1 )
  113. 			{
  114. 				return ShowHelp( "/C switch cannot be combined with other command line arguments" );
  115. 			}
  116.  
  117.  
  118.  
  119. #if DEBUG
  120. 			debug = true;
  121. #endif
  122.  
  123.  
  124. 			#endregion Parse and validate Command Line
  125.  
  126.  
  127. 			if ( querycurrent )
  128. 			{
  129. 				return QueryActive( );
  130. 			}
  131. 			else if ( useprogname )
  132. 			{
  133. 				return ActivateByProgName( );
  134. 			}
  135. 			else
  136. 			{
  137. 				return ActivateByTitle( );
  138. 			}
  139. 		}
  140.  
  141.  
  142. 		static int ActivateByProgName( )
  143. 		{
  144. 			// Based on code by Hans Passant on StackOverflow.com
  145. 			// https://stackoverflow.com/a/2819747
  146. 			Process[] proc = Process.GetProcessesByName( progname ); // progname should be WITHOUT extension
  147. 			if ( proc.Length > 0 )
  148. 			{
  149. 				SetForegroundWindow( proc[0].MainWindowHandle ); // Make first match the foreground window
  150. 			}
  151. 			else
  152. 			{
  153. 				proc = Process.GetProcessesByName( Path.GetFileNameWithoutExtension( progname ) ); // try stripping extension
  154. 				if ( proc.Length > 0 )
  155. 				{
  156. 					SetForegroundWindow( proc[0].MainWindowHandle ); // Make first match the foreground window
  157. 				}
  158. 				else
  159. 				{
  160. 					Console.Error.WriteLine( "No process with specified name \"{0}\" was found.", progname );
  161. 					return 1;
  162. 				}
  163. 			}
  164. 			return 0;
  165. 		}
  166.  
  167.  
  168. 		static int ActivateByTitle( )
  169. 		{
  170. 			// Find the window with the specified title
  171. 			IntPtr handle = FindWindow( windowtitles, exactmatch );
  172. 			if ( handle == IntPtr.Zero )
  173. 			{
  174. 				Console.Error.WriteLine( "No window was found with {0}title.", exact );
  175. 				return 1;
  176. 			}
  177. 			else
  178. 			{
  179. 				if ( debug && !exactmatch )
  180. 				{
  181. 					Console.WriteLine( "Specified title : \"{0}\"\nMatching title  : \"{1}\"\n", windowtitle, matchingtitle );
  182. 				}
  183. 				// If found, make it the foreground window
  184. 				if ( !SetForegroundWindow( handle ) )
  185. 				{
  186. 					Console.Error.WriteLine( "Unable to move the specified window to the foreground." );
  187. 					return -1;
  188. 				}
  189. 			}
  190. 			return 0;
  191. 		}
  192.  
  193.  
  194. 		static IntPtr FindWindow( List<string> titles, bool exacttitlematch = false )
  195. 		{
  196. 			foreach ( Process process in Process.GetProcesses( ) )
  197. 			{
  198. 				foreach( string title in titles )
  199. 				{
  200. 					if ( process.MainWindowTitle.Equals( title, StringComparison.InvariantCultureIgnoreCase ) )
  201. 					{
  202. 						return process.MainWindowHandle; // Return the FIRST matching window
  203. 					}
  204. 					else if ( !exacttitlematch )
  205. 					{
  206.  
  207. 						if ( process.MainWindowTitle.ToUpper( ).Contains( title.ToUpper( ) ) )
  208. 						{
  209. 							matchingtitle = process.MainWindowTitle;
  210. 							windowtitle = title;
  211. 							return process.MainWindowHandle; // Return the FIRST matching window
  212. 						}
  213. 					}
  214. 				}
  215. 			}
  216. 			return IntPtr.Zero; // In case no matching title was found
  217. 		}
  218.  
  219.  
  220. 		static string GetActiveWindowTitle( )
  221. 		{
  222. 			// Code by Jorge Ferreira on StackOverflow.com
  223. 			// https://stackoverflow.com/a/115905
  224. 			const int nChars = 256;
  225. 			StringBuilder Buff = new StringBuilder( nChars );
  226. 			IntPtr handle = GetForegroundWindow( );
  227.  
  228. 			if ( GetWindowText( handle, Buff, nChars ) > 0 )
  229. 			{
  230. 				return Buff.ToString( );
  231. 			}
  232. 			return null;
  233. 		}
  234.  
  235.  
  236. 		static int QueryActive( )
  237. 		{
  238. 			// Find the title of the currently active window
  239. 			string activewindowtitle = GetActiveWindowTitle( );
  240. 			if ( string.IsNullOrWhiteSpace( activewindowtitle ) )
  241. 			{
  242. 				Console.Error.WriteLine( "Unable to query the active window's title." );
  243. 				return -1;
  244. 			}
  245. 			else
  246. 			{
  247. 				Console.WriteLine( activewindowtitle );
  248. 				return 0;
  249. 			}
  250. 		}
  251.  
  252.  
  253. 		#region DLL Imports
  254.  
  255. 		[DllImport( "user32.dll" )]
  256. 		[return: MarshalAs( UnmanagedType.Bool )]
  257. 		static extern bool SetForegroundWindow( IntPtr hWnd );
  258.  
  259.  
  260. 		[DllImport( "user32.dll" )]
  261. 		static extern IntPtr GetForegroundWindow( );
  262.  
  263.  
  264. 		[DllImport( "user32.dll" )]
  265. 		static extern int GetWindowText( IntPtr hWnd, StringBuilder text, int count );
  266.  
  267. 		#endregion DLL Imports
  268.  
  269.  
  270. 		#region Error handling
  271.  
  272. 		static int ShowHelp( params string[] errmsg )
  273. 		{
  274. 			#region Error Message
  275.  
  276. 			if ( errmsg.Length > 0 )
  277. 			{
  278. 				List<string> errargs = new List<string>( errmsg );
  279. 				errargs.RemoveAt( 0 );
  280. 				Console.Error.WriteLine( );
  281. 				Console.ForegroundColor = ConsoleColor.Red;
  282. 				Console.Error.Write( "ERROR:\t" );
  283. 				Console.ForegroundColor = ConsoleColor.White;
  284. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  285. 				Console.ResetColor( );
  286. 			}
  287.  
  288. 			#endregion Error Message
  289.  
  290.  
  291. 			#region Help Text
  292.  
  293. 			/*
  294. 			ActivateWindow.exe,  Version 1.03
  295. 			Activate the specified window
  296.  
  297. 			Usage:   ActivateWindow.exe  title  [ title  [ title ... ] ]  [ /D ]  [ /X ]
  298.  
  299. 			   or:   ActivateWindow.exe  progname  /P
  300.  
  301. 			   or:   ActivateWindow.exe  /C
  302.  
  303. 			Where:   title     is a (partial) title of the window to be activated
  304. 			                   (first matching title is used)
  305. 			         progname  is the executable name of the window to be activated
  306. 			                   (name only, no extension)
  307.  
  308. 			Options: /C        show Currently active window's title on screen
  309. 			         /D        Debug mode: show match used for partial title
  310. 			         /P        specified name is Program executable name
  311. 			                   (default: specified name is window title)
  312. 			         /X        window title and specified title must match eXactly
  313. 			                   (default: window title contains specified title)
  314.  
  315. 			Notes:   With /P switch, if no match is found, the program will try and
  316. 			         strip an extension from progname if applicable, and search again.
  317. 			         Return code 0 on success, 1 if no match, or -1 in case of errors.
  318.  
  319. 			Written by Rob van der Woude
  320. 			https://www.robvanderwoude.com
  321. 			*/
  322.  
  323. 			#endregion Help Text
  324.  
  325.  
  326. 			#region Display Help Text
  327.  
  328. 			Console.Error.WriteLine( );
  329.  
  330. 			Console.Error.WriteLine( "ActivateWindow.exe,  Version {0}", progver );
  331.  
  332. 			Console.Error.WriteLine( "Activate the specified window" );
  333.  
  334. 			Console.Error.WriteLine( );
  335.  
  336. 			Console.Error.Write( "Usage:   " );
  337. 			Console.ForegroundColor = ConsoleColor.White;
  338. 			Console.Error.WriteLine( "ActivateWindow.exe  title  [ title  [ title ... ] ]  [ /D ]  [ /X ]" );
  339. 			Console.ResetColor( );
  340.  
  341. 			Console.Error.WriteLine( );
  342.  
  343. 			Console.Error.Write( "   or:   " );
  344. 			Console.ForegroundColor = ConsoleColor.White;
  345. 			Console.Error.WriteLine( "ActivateWindow.exe  progname  /P" );
  346. 			Console.ResetColor( );
  347.  
  348. 			Console.Error.WriteLine( );
  349.  
  350. 			Console.Error.Write( "   or:   " );
  351. 			Console.ForegroundColor = ConsoleColor.White;
  352. 			Console.Error.WriteLine( "ActivateWindow.exe  /C" );
  353. 			Console.ResetColor( );
  354.  
  355. 			Console.Error.WriteLine( );
  356.  
  357. 			Console.Write( "Where:   " );
  358. 			Console.ForegroundColor = ConsoleColor.White;
  359. 			Console.Write( "title     " );
  360. 			Console.ResetColor( );
  361. 			Console.WriteLine( "is a (partial) title of the window to be activated" );
  362.  
  363. 			Console.Error.WriteLine( "                   (first matching title is used)" );
  364.  
  365. 			Console.Error.WriteLine( );
  366.  
  367. 			Console.ForegroundColor = ConsoleColor.White;
  368. 			Console.Error.Write( "         progname  " );
  369. 			Console.ResetColor( );
  370. 			Console.Error.Write( "is the executable " );
  371. 			Console.ForegroundColor = ConsoleColor.White;
  372. 			Console.Error.Write( "name" );
  373. 			Console.ResetColor( );
  374. 			Console.Error.WriteLine( " of the window to be activated" );
  375.  
  376. 			Console.Error.WriteLine( "                   (name only, no extension)" );
  377.  
  378. 			Console.Error.WriteLine( );
  379.  
  380. 			Console.Error.Write( "Options: " );
  381. 			Console.ForegroundColor = ConsoleColor.White;
  382. 			Console.Error.Write( "/C        " );
  383. 			Console.ResetColor( );
  384. 			Console.Error.Write( "show " );
  385. 			Console.ForegroundColor = ConsoleColor.White;
  386. 			Console.Error.Write( "C" );
  387. 			Console.ResetColor( );
  388. 			Console.Error.WriteLine( "urrently active window's title on screen" );
  389.  
  390.  
  391. 			Console.ForegroundColor = ConsoleColor.White;
  392. 			Console.Error.Write( "         /D        D" );
  393. 			Console.ResetColor( );
  394. 			Console.Error.WriteLine( "ebug mode: show match used for partial title" );
  395.  
  396. 			Console.ForegroundColor = ConsoleColor.White;
  397. 			Console.Error.Write( "         /P" );
  398. 			Console.ResetColor( );
  399. 			Console.Error.Write( "        specified name is " );
  400. 			Console.ForegroundColor = ConsoleColor.White;
  401. 			Console.Error.Write( "P" );
  402. 			Console.ResetColor( );
  403. 			Console.Error.WriteLine( "rogram executable name" );
  404.  
  405. 			Console.Error.WriteLine( "                   (default: specified name is window title)" );
  406.  
  407. 			Console.ForegroundColor = ConsoleColor.White;
  408. 			Console.Error.Write( "         /X        " );
  409. 			Console.ResetColor( );
  410. 			Console.Error.Write( "window title and specified title must match e" );
  411. 			Console.ForegroundColor = ConsoleColor.White;
  412. 			Console.Error.Write( "X" );
  413. 			Console.ResetColor( );
  414. 			Console.Error.WriteLine( "actly" );
  415.  
  416. 			Console.Error.Write( "                   (default: window title " );
  417. 			Console.ForegroundColor = ConsoleColor.White;
  418. 			Console.Error.Write( "contains " );
  419. 			Console.ResetColor( );
  420. 			Console.Error.WriteLine( "specified title)" );
  421.  
  422. 			Console.Error.WriteLine( );
  423.  
  424. 			Console.Error.Write( "Notes:   With " );
  425. 			Console.ForegroundColor = ConsoleColor.White;
  426. 			Console.Error.Write( "/P" );
  427. 			Console.ResetColor( );
  428. 			Console.Error.WriteLine( " switch, if no match is found, the program will try and" );
  429.  
  430. 			Console.Error.Write( "         strip an extension from " );
  431. 			Console.ForegroundColor = ConsoleColor.White;
  432. 			Console.Error.Write( "progname" );
  433. 			Console.ResetColor( );
  434. 			Console.Error.WriteLine( " if applicable, and search again." );
  435.  
  436. 			Console.Error.WriteLine( "         Return code 0 on success, 1 if no match, or -1 in case of errors." );
  437.  
  438. 			Console.Error.WriteLine( );
  439.  
  440. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  441.  
  442. 			Console.Error.WriteLine( "https://www.robvanderwoude.com" );
  443.  
  444. 			#endregion Display Help Text
  445.  
  446.  
  447. 			return -1;
  448. 		}
  449.  
  450. 		#endregion Error handling
  451. 	}
  452. }

page last modified: 2024-02-26; loaded in 0.0348 seconds