Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for messagebox.cs

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

  1. using System;
  2. using System.Globalization;
  3. using System.Runtime.InteropServices;
  4. using System.Text.RegularExpressions;
  5. using System.Windows.Forms;
  6.  
  7.  
  8. namespace RobvanderWoude
  9. {
  10. 	class MessageBox
  11. 	{
  12. 		public static string progver = "1.28";
  13. 		public static bool timeoutelapsed = false;
  14.  
  15.  
  16. 		static int Main( string[] args )
  17. 		{
  18. 			#region Initialize Variables
  19.  
  20. 			string defaultmessage = DefaultMessage( );
  21. 			string message = defaultmessage;
  22. 			string defaulttitle = String.Format( "MessageBox {0}", progver );
  23. 			string title = defaulttitle;
  24. 			MessageBoxButtons buttons = MessageBoxButtons.OK;
  25. 			MessageBoxIcon icon = MessageBoxIcon.Information;
  26. 			MessageBoxDefaultButton defaultbutton = MessageBoxDefaultButton.Button1;
  27. 			MessageBoxOptions option = MessageBoxOptions.DefaultDesktopOnly;
  28. 			bool escapemessage = true;
  29. 			DialogResult result;
  30. 			int timeout = 0;
  31. 			int rc = 1;
  32.  
  33. 			#endregion Initialize Variables
  34.  
  35.  
  36. 			#region Command Line Parsing
  37.  
  38. 			if ( args.Length == 1 && args[0] == "/?" )
  39. 			{
  40. 				Console.Error.Write( message.Replace( "\n\n\t", "\n\t" ).Replace( "Usage:\n", "Usage:\t" ) );
  41. 				return 1;
  42. 			}
  43.  
  44. 			if ( args.Length > 0 && args.Length < 8 )
  45. 			{
  46. 				if ( args.Length > 0 )
  47. 				{
  48. 					if ( escapemessage )
  49. 					{
  50. 						message = UnEscapeString( args[0] );
  51. 					}
  52. 					else
  53. 					{
  54. 						message = args[0];
  55. 					}
  56. 					rc = 0;
  57. 					if ( args.Length > 1 )
  58. 					{
  59. 						if ( escapemessage )
  60. 						{
  61. 							title = UnEscapeString( args[1] );
  62. 						}
  63. 						else
  64. 						{
  65. 							title = args[1];
  66. 						}
  67. 						if ( args.Length > 2 )
  68. 						{
  69. 							switch ( args[2].ToLower( ) )
  70. 							{
  71. 								case "abortretryignore":
  72. 									buttons = MessageBoxButtons.AbortRetryIgnore;
  73. 									break;
  74. 								case "ok":
  75. 									buttons = MessageBoxButtons.OK;
  76. 									break;
  77. 								case "okcancel":
  78. 									buttons = MessageBoxButtons.OKCancel;
  79. 									break;
  80. 								case "retrycancel":
  81. 									buttons = MessageBoxButtons.RetryCancel;
  82. 									break;
  83. 								case "yesno":
  84. 									buttons = MessageBoxButtons.YesNo;
  85. 									break;
  86. 								case "yesnocancel":
  87. 									buttons = MessageBoxButtons.YesNoCancel;
  88. 									break;
  89. 								default:
  90. 									buttons = MessageBoxButtons.OK;
  91. 									rc = 1;
  92. 									break;
  93. 							}
  94. 							if ( args.Length > 3 )
  95. 							{
  96. 								switch ( args[3].ToLower( ) )
  97. 								{
  98. 									case "asterisk":
  99. 										icon = MessageBoxIcon.Asterisk;
  100. 										break;
  101. 									case "error":
  102. 										icon = MessageBoxIcon.Error;
  103. 										break;
  104. 									case "exclamation":
  105. 										icon = MessageBoxIcon.Exclamation;
  106. 										break;
  107. 									case "hand":
  108. 										icon = MessageBoxIcon.Hand;
  109. 										break;
  110. 									case "information":
  111. 										icon = MessageBoxIcon.Information;
  112. 										break;
  113. 									case "none":
  114. 										icon = MessageBoxIcon.None;
  115. 										break;
  116. 									case "question":
  117. 										icon = MessageBoxIcon.Question;
  118. 										break;
  119. 									case "stop":
  120. 										icon = MessageBoxIcon.Stop;
  121. 										break;
  122. 									case "warning":
  123. 										icon = MessageBoxIcon.Warning;
  124. 										break;
  125. 									default:
  126. 										icon = MessageBoxIcon.Warning;
  127. 										rc = 1;
  128. 										break;
  129. 								}
  130. 								if ( args.Length > 4 )
  131. 								{
  132. 									switch ( args[4].ToLower( ) )
  133. 									{
  134. 										case "":
  135. 										case "abort":
  136. 										case "button1":
  137. 										case "ok":
  138. 										case "yes":
  139. 											defaultbutton = MessageBoxDefaultButton.Button1;
  140. 											break;
  141. 										case "button2":
  142. 										case "no":
  143. 											defaultbutton = MessageBoxDefaultButton.Button2;
  144. 											break;
  145. 										case "button3":
  146. 										case "ignore":
  147. 											defaultbutton = MessageBoxDefaultButton.Button3;
  148. 											break;
  149. 										case "cancel":
  150. 											if ( args[2].ToLower( ) == "okcancel" || args[2].ToLower( ) == "retrycancel" )
  151. 											{
  152. 												defaultbutton = MessageBoxDefaultButton.Button2;
  153. 											}
  154. 											else // yesnocancel
  155. 											{
  156. 												defaultbutton = MessageBoxDefaultButton.Button3;
  157. 											}
  158. 											break;
  159. 										case "retry":
  160. 											if ( args[2].ToLower( ) == "abortretryignore" )
  161. 											{
  162. 												defaultbutton = MessageBoxDefaultButton.Button2;
  163. 											}
  164. 											else // retrycancel
  165. 											{
  166. 												defaultbutton = MessageBoxDefaultButton.Button1;
  167. 											}
  168. 											break;
  169. 										default:
  170. 											defaultbutton = MessageBoxDefaultButton.Button1;
  171. 											rc = 1;
  172. 											break;
  173. 									}
  174. 									if ( args.Length > 5 )
  175. 									{
  176. 										switch ( args[5].ToLower( ) )
  177. 										{
  178. 											case "":
  179. 											case "none":
  180. 												break;
  181. 											case "hideconsole":
  182. 												HideConsoleWindow( );
  183. 												break;
  184. 											case "noescape":
  185. 												escapemessage = false;
  186. 												break;
  187. 											case "rightalign":
  188. 												option = MessageBoxOptions.RightAlign;
  189. 												break;
  190. 											case "rtlreading":
  191. 												option = MessageBoxOptions.RtlReading;
  192. 												break;
  193. 											default: // try if 6th argument is timeout
  194. 												try
  195. 												{
  196. 													timeout = Convert.ToInt32( args[5] ) * 1000;
  197. 													if ( timeout < 1000 )
  198. 													{
  199. 														rc = 1;
  200. 													}
  201. 												}
  202. 												catch ( FormatException )
  203. 												{
  204. 													rc = 1;
  205. 												}
  206. 												break;
  207. 										}
  208. 										if ( args.Length == 7 )
  209. 										{
  210. 											try
  211. 											{
  212. 												timeout = Convert.ToInt32( args[6] ) * 1000;
  213. 												if ( timeout < 1000 )
  214. 												{
  215. 													rc = 1;
  216. 												}
  217. 											}
  218. 											catch ( FormatException )
  219. 											{
  220. 												rc = 1;
  221. 											}
  222. 										}
  223. 									}
  224. 								}
  225. 							}
  226. 						}
  227. 					}
  228. 				}
  229. 			}
  230.  
  231. 			#endregion Command Line Parsing
  232.  
  233.  
  234. 			if ( rc == 1 ) // command line error
  235. 			{
  236. 				ShowConsoleWindow( );
  237. 				message = defaultmessage;
  238. 				title = defaulttitle;
  239. 				buttons = MessageBoxButtons.OK;
  240. 				icon = MessageBoxIcon.Warning;
  241. 				defaultbutton = MessageBoxDefaultButton.Button1;
  242. 				// Display the help text in a message box AND in the console
  243. 				Console.Error.Write( message.Replace( "\n\n\t", "\n\t" ).Replace( "Usage:\n", "Usage:\t" ) );
  244. 			}
  245.  
  246. 			if ( rc == 0 && timeout > 0 )
  247. 			{
  248. 				// MessageBoxOptions.ServiceNotification allows interactive use by SYSTEM account (or any other account not currently logged in)
  249. 				result = AutoClosingMessageBox.Show( message, title, timeout, buttons, icon, defaultbutton, option | MessageBoxOptions.ServiceNotification );
  250. 				if ( timeoutelapsed )
  251. 				{
  252. 					Console.WriteLine( "timeout" );
  253. 					return 3;
  254. 				}
  255. 			}
  256. 			else
  257. 			{
  258. 				result = System.Windows.Forms.MessageBox.Show( message, title, buttons, icon, defaultbutton, option | MessageBoxOptions.ServiceNotification );
  259. 			}
  260. 			Console.WriteLine( result.ToString( ).ToLower( ) );
  261. 			return rc;
  262. 		}
  263.  
  264.  
  265. 		static string DefaultMessage( )
  266. 		{
  267. 			string message = "MessageBox.exe,  Version " + progver + "\n";
  268. 			message += "Batch tool to show a message in a MessageBox and return the caption\nof the button that is clicked\n\n";
  269. 			message += "Usage:\nMessageBox \"message\" \"title\" buttons icon default [option] timeout\n\n";
  270. 			message += "Where:\tbuttons\t\"AbortRetryIgnore\", \"OK\", \"OKCancel\",\n";
  271. 			message += "\t\t\"RetryCancel\", \"YesNo\" or \"YesNoCancel\"\n";
  272. 			message += "\ticon\t\"Asterisk\", \"Error\", \"Exclamation\", \"Hand\",\n";
  273. 			message += "\t\t\"Information\", \"None\", \"Question\", \"Stop\"\n";
  274. 			message += "\t\tor \"Warning\"\n";
  275. 			message += "\tdefault\t\"Button1\", \"Button2\" or \"Button3\" or the\n\t\tdefault button's (English) caption\n";
  276. 			message += "\toption\t\"HideConsole\", \"NoEscape\", \"RightAlign\",\n\t\t\"RtlReading\", \"None\" or \"\"\n";
  277. 			message += "\ttimeout\ttimeout interval in seconds\n\n";
  278. 			message += "Notes:\tWhereas all arguments are optional, each argument requires\n\tall preceding arguments, i.e. icon requires \"message\", \"title\"\n\tand buttons, but not necessarily default, option and timeout.\n\n";
  279. 			message += "\tUsing the \"HideConsole\" option will hide the console\n\twindow permanently, thereby disabling all console based\n\tuser interaction (e.g. \"ECHO\" and \"PAUSE\").\n\tIt is meant to be used in scripts that run \"hidden\"\n\tthemselves, e.g. VBScript with the WScript.exe interpreter.\n\tDo not use this option in a batch file unless hiding\n\tthe console window permanently is intended.\n\n";
  280. 			message += "\tLinefeeds (\\n or \\012 and/or \\r or \\015), tabs (\\t or \\007),\n\tsinglequotes (' or \\047) and doublequotes (\\\" or \\042)\n\tare allowed in the message string.\n";
  281. 			message += "\tEscaped Unicode characters (e.g. \"\\u5173\" for \"\u5173\")\n\tare allowed in the message string and in the title.\n";
  282. 			message += "\tUse option \"NoEscape\" to disable all character escaping\n\texcept doublequotes (useful when displaying a path).\n\n";
  283. 			message += "\tThe (English) caption of the button that was clicked\n\tis returned as text to Standard Output (in lower case),\n\tor \"timeout\" if the timeout interval expired.\n\n";
  284. 			message += "\tCode to hide console by Anthony on:\n\thttp://stackoverflow.com/a/15079092\n\n";
  285. 			message += "\tMessageBox timeout based on code by DmitryG on:\n\thttp://stackoverflow.com/a/14522952\n\n";
  286. 			message += "\tNote that when using the timeout feature, A window\n\twith the current MessageBox's TITLE will be closed,\n\tnot necessarily the current MessageBox. To prevent\n\tclosing the wrong MessageBox, use unique titles.\n\n";
  287. 			message += "\tThe return code of the program is 0 if a button was clicked,\n\t1 in case of (command line) errors, 3 if the timeout expired.\n\n";
  288. 			message += "Written by Rob van der Woude\nhttp://www.robvanderwoude.com\n";
  289. 			return message;
  290. 		}
  291.  
  292.  
  293. 		static string UnEscapeString( string message )
  294. 		{
  295. 			// Unescaping tabs, linefeeds and quotes
  296. 			message = message.Replace( "\\n", "\n" );
  297. 			message = message.Replace( "\\r", "\r" );
  298. 			message = message.Replace( "\\t", "\t" );
  299. 			message = message.Replace( "\\007", "\t" );
  300. 			message = message.Replace( "\\012", "\n" );
  301. 			message = message.Replace( "\\015", "\r" );
  302. 			message = message.Replace( "\\042", "\"" );
  303. 			message = message.Replace( "\\047", "'" );
  304. 			// Unescaping Unicode, technique by "dtb" on StackOverflow.com: http://stackoverflow.com/a/8558748
  305. 			message = Regex.Replace( message, @"\\[Uu]([0-9A-Fa-f]{4})", m => char.ToString( (char) ushort.Parse( m.Groups[1].Value, NumberStyles.AllowHexSpecifier ) ) );
  306. 			return message;
  307. 		}
  308.  
  309.  
  310. 		#region Hide or Show Console
  311. 		// Source: http://stackoverflow.com/a/15079092
  312.  
  313. 		public static void ShowConsoleWindow( )
  314. 		{
  315. 			var handle = GetConsoleWindow( );
  316.  
  317. 			if ( handle == IntPtr.Zero )
  318. 			{
  319. 				AllocConsole( );
  320. 			}
  321. 			else
  322. 			{
  323. 				ShowWindow( handle, SW_SHOW );
  324. 			}
  325. 		}
  326.  
  327.  
  328. 		public static void HideConsoleWindow( )
  329. 		{
  330. 			var handle = GetConsoleWindow( );
  331.  
  332. 			ShowWindow( handle, SW_HIDE );
  333. 		}
  334.  
  335.  
  336. 		[DllImport( "kernel32.dll", SetLastError = true )]
  337. 		static extern bool AllocConsole( );
  338.  
  339.  
  340. 		[DllImport( "kernel32.dll" )]
  341. 		static extern IntPtr GetConsoleWindow( );
  342.  
  343.  
  344. 		[DllImport( "user32.dll" )]
  345. 		static extern bool ShowWindow( IntPtr hWnd, int nCmdShow );
  346.  
  347.  
  348. 		const int SW_HIDE = 0;
  349. 		const int SW_SHOW = 5;
  350.  
  351. 		#endregion Hide or Show Console
  352.  
  353.  
  354. 		#region Timed MessageBox
  355.  
  356. 		// Timed MessageBox based on code by DmitryG on StackOverflow.com
  357. 		// http://stackoverflow.com/a/14522952
  358. 		public class AutoClosingMessageBox
  359. 		{
  360. 			System.Threading.Timer _timeouttimer;
  361. 			string _caption;
  362. 			DialogResult _result;
  363.  
  364.  
  365. 			AutoClosingMessageBox( string message, string title, int timeout, MessageBoxButtons buttons = MessageBoxButtons.OK, MessageBoxIcon icon = MessageBoxIcon.None, MessageBoxDefaultButton defaultbutton = MessageBoxDefaultButton.Button1, MessageBoxOptions option = MessageBoxOptions.DefaultDesktopOnly )
  366. 			{
  367. 				_caption = title;
  368. 				_timeouttimer = new System.Threading.Timer( OnTimerElapsed, null, timeout, System.Threading.Timeout.Infinite );
  369.  
  370. 				using ( _timeouttimer )
  371. 				{
  372. 					_result = System.Windows.Forms.MessageBox.Show( message, title, buttons, icon, defaultbutton, option | MessageBoxOptions.ServiceNotification );
  373. 				}
  374. 			}
  375.  
  376.  
  377. 			public static DialogResult Show( string message, string title, int timeout, MessageBoxButtons buttons = MessageBoxButtons.OK, MessageBoxIcon icon = MessageBoxIcon.None, MessageBoxDefaultButton defaultbutton = MessageBoxDefaultButton.Button1, MessageBoxOptions option = MessageBoxOptions.DefaultDesktopOnly )
  378. 			{
  379. 				return new AutoClosingMessageBox( message, title, timeout, buttons, icon, defaultbutton, option | MessageBoxOptions.ServiceNotification )._result;
  380. 			}
  381.  
  382.  
  383. 			void OnTimerElapsed( object state )
  384. 			{
  385. 				IntPtr mbWnd = FindWindow( "#32770", _caption ); // lpClassName is #32770 for MessageBox
  386. 				if ( mbWnd != IntPtr.Zero )
  387. 				{
  388. 					SendMessage( mbWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero );
  389. 				}
  390. 				_timeouttimer.Dispose( );
  391. 				timeoutelapsed = true;
  392. 			}
  393.  
  394.  
  395. 			const int WM_CLOSE = 0x0010;
  396.  
  397.  
  398. 			[System.Runtime.InteropServices.DllImport( "user32.dll", SetLastError = true )]
  399. 			static extern IntPtr FindWindow( string lpClassName, string lpWindowName );
  400.  
  401.  
  402. 			[System.Runtime.InteropServices.DllImport( "user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto )]
  403. 			static extern IntPtr SendMessage( IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam );
  404. 		}
  405.  
  406. 		#endregion Timed MessageBox
  407. 	}
  408. }
  409.  

page last uploaded: 2017-07-06, 12:37