Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for systemtraymessage.cs

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.IO;
  5. using System.Runtime.InteropServices;
  6. using System.Text.RegularExpressions;
  7. using System.Threading;
  8. using System.Windows.Forms;
  9.  
  10.  
  11. namespace RobvanderWoude
  12. {
  13. 	class SystemTrayMessage
  14. 	{
  15. 		static string progver = "1.05";
  16.  
  17. 		static int rc = 0;
  18. 		static NotifyIcon notifyicon;
  19.  
  20.  
  21. 		static int Main( string[] args )
  22. 		{
  23. 			#region Initialize Variables
  24.  
  25. 			bool escapemessage = true;
  26. 			bool wait = false;
  27. 			int timeout = 10000;
  28. 			int iconindex = 277;
  29. 			string[] searchpath = Environment.GetEnvironmentVariable( "PATH" ).Split( new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries );
  30. 			string iconfile = "shell32.dll";
  31. 			string iconext = ".dll";
  32. 			Icon systrayicon = IconExtractor.Extract( iconfile, iconindex, true );
  33. 			ToolTipIcon tooltipicon = ToolTipIcon.Info;
  34. 			string message = String.Empty;
  35. 			string title = String.Empty;
  36.  
  37. 			#endregion Initialize Variables
  38.  
  39.  
  40. 			#region Parse Command Line
  41.  
  42. 			if ( args.Length == 0 )
  43. 			{
  44. 				return ShowHelp( );
  45. 			}
  46. 			foreach ( string arg in args )
  47. 			{
  48. 				if ( arg == "/?" )
  49. 				{
  50. 					return ShowHelp( );
  51. 				}
  52. 				if ( arg.ToUpper( ) == "/W" )
  53. 				{
  54. 					if ( wait )
  55. 					{
  56. 						return ShowHelp( "Duplicate command line switch /W" );
  57. 					}
  58. 					wait = true;
  59. 				}
  60. 				else if ( arg.ToUpper( ) == "/L" )
  61. 				{
  62. 					if ( !escapemessage )
  63. 					{
  64. 						return ShowHelp( "Duplicate command line switch /NE" );
  65. 					}
  66. 					escapemessage = false;
  67. 				}
  68. 				else if ( arg[0] == '/' )
  69. 				{
  70. 					if ( arg.Length > 3 && arg[2] == ':' )
  71. 					{
  72. 						switch ( arg[1].ToString( ).ToUpper( ) )
  73. 						{
  74. 							case "I":
  75. 								if ( tooltipicon != ToolTipIcon.Info )
  76. 								{
  77. 									return ShowHelp( "Duplicate command line switch /I" );
  78. 								}
  79. 								switch ( arg.Substring( 3 ).ToUpper( ) )
  80. 								{
  81. 									case "ERROR":
  82. 										tooltipicon = ToolTipIcon.Error;
  83. 										break;
  84. 									case "INFO":
  85. 										tooltipicon = ToolTipIcon.Info;
  86. 										break;
  87. 									case "NONE":
  88. 										tooltipicon = ToolTipIcon.None;
  89. 										break;
  90. 									case "WARNING":
  91. 										tooltipicon = ToolTipIcon.Warning;
  92. 										break;
  93. 									default:
  94. 										return ShowHelp( "Invalid tooltip icon type \"{0}\"", arg.Substring( 3 ) );
  95. 								}
  96. 								break;
  97. 							case "P":
  98. 								if ( iconfile.ToUpper( ) != "SHELL32.DLL" )
  99. 								{
  100. 									return ShowHelp( "Duplicate command line switch /P" );
  101. 								}
  102. 								iconext = Path.GetExtension( arg.Substring( 3 ) ).ToLower( );
  103. 								if ( File.Exists( arg.Substring( 3 ) ) )
  104. 								{
  105. 									iconfile = Path.GetFullPath( arg.Substring( 3 ) );
  106. 								}
  107. 								else if ( iconext == ".dll" || iconext == ".exe" )
  108. 								{
  109. 									foreach ( string folder in searchpath )
  110. 									{
  111. 										if ( File.Exists( Path.Combine( folder, arg.Substring( 3 ) ) ) )
  112. 										{
  113. 											iconfile = Path.Combine( folder, arg.Substring( 3 ) );
  114. 											break;
  115. 										}
  116. 									}
  117. 									if ( !File.Exists( iconfile ) )
  118. 									{
  119. 										return ShowHelp( "Invalid path to icon file or library \"{0}\"", arg.Substring( 3 ) );
  120. 									}
  121. 								}
  122. 								break;
  123. 							case "S":
  124. 								if ( iconindex != 277 )
  125. 								{
  126. 									return ShowHelp( "Duplicate command line switch /S" );
  127. 								}
  128. 								try
  129. 								{
  130. 									iconindex = Convert.ToInt32( arg.Substring( 3 ) );
  131. 									if ( iconindex < 0 )
  132. 									{
  133. 										return ShowHelp( "Invalid system tray icon index \"{0}\"", arg.Substring( 3 ) );
  134. 									}
  135. 								}
  136. 								catch ( Exception )
  137. 								{
  138. 									return ShowHelp( "Invalid system tray icon argument \"{0}\"", arg );
  139. 								}
  140. 								break;
  141. 							case "T":
  142. 								if ( String.IsNullOrWhiteSpace( title ) )
  143. 								{
  144. 									title = arg.Substring( 3 ).Trim( "\" \t".ToCharArray( ) );
  145. 								}
  146. 								else
  147. 								{
  148. 									return ShowHelp( "Duplicate command line switch /T" );
  149. 								}
  150. 								break;
  151. 							case "V":
  152. 								if ( timeout != 10000 )
  153. 								{
  154. 									return ShowHelp( "Duplicate command line switch /V" );
  155. 								}
  156. 								try
  157. 								{
  158. 									timeout = 1000 * Convert.ToInt32( arg.Substring( 3 ) );
  159. 									if ( timeout < 1000 )
  160. 									{
  161. 										return ShowHelp( "Invalid time (\"{0}\"), must be greater than zero", arg.Substring( 3 ) );
  162. 									}
  163. 								}
  164. 								catch ( Exception )
  165. 								{
  166. 									return ShowHelp( "Invalid time \"{0}\"", arg.Substring( 3 ) );
  167. 								}
  168. 								break;
  169. 							default:
  170. 								return ShowHelp( "Invalid command line switch \"{0}\"", arg );
  171. 						}
  172. 					}
  173. 					else
  174. 					{
  175. 						return ShowHelp( "Invalid command line switch \"{0}\"", arg );
  176. 					}
  177. 				}
  178. 				else
  179. 				{
  180. 					if ( String.IsNullOrWhiteSpace( message ) )
  181. 					{
  182. 						message = arg;
  183. 					}
  184. 					else
  185. 					{
  186. 						return ShowHelp( "Duplicate message on command line" );
  187. 					}
  188. 				}
  189. 			}
  190.  
  191. 			if ( String.IsNullOrWhiteSpace( message ) )
  192. 			{
  193. 				return ShowHelp( "Please specify a message text" );
  194. 			}
  195.  
  196. 			if ( escapemessage )
  197. 			{
  198. 				message = Regex.Replace( message, @"(?<!\\)\\n", "\n" );
  199. 				message = Regex.Replace( message, @"(?<!\\)\\t", "\t" );
  200. 				message = Regex.Replace( message, @"\\", @"\" );
  201. 			}
  202.  
  203. 			if ( iconext == ".dll" )
  204. 			{
  205. 				systrayicon = IconExtractor.Extract( iconfile, iconindex, true );
  206. 			}
  207. 			else
  208. 			{
  209. 				systrayicon = new Icon( iconfile );
  210. 			}
  211.  
  212. 			#endregion Parse Command Line
  213.  
  214.  
  215. 			notifyicon = new NotifyIcon( );
  216. 			notifyicon.Icon = systrayicon;
  217. 			notifyicon.Visible = true;
  218.  
  219. 			if ( wait )
  220. 			{
  221. 				// Wait for the icon/message to be clicked
  222. 				notifyicon.BalloonTipClicked += ( object sender, EventArgs e ) => { rc = 2; };
  223. 				notifyicon.BalloonTipClosed += ( object sender, EventArgs e ) => { rc = 2; };
  224. 			}
  225.  
  226. 			notifyicon.ShowBalloonTip( timeout, title, message, tooltipicon );
  227.  
  228. 			if ( wait )
  229. 			{
  230. 				rc = 3;
  231. 				while ( timeout > 0 && rc == 3 )
  232. 				{
  233. 					Thread.Sleep( 1 );
  234. 					Application.DoEvents( );
  235. 					timeout--;
  236. 				}
  237. 				notifyicon.Visible = false;
  238. 				notifyicon.Dispose( );
  239. 			}
  240.  
  241. 			return rc;
  242. 		}
  243.  
  244.  
  245. 		static int ShowHelp( params string[] errmsg )
  246. 		{
  247. 			#region Error Message
  248.  
  249. 			if ( errmsg.Length > 0 )
  250. 			{
  251. 				List<string> errargs = new List<string>( errmsg );
  252. 				errargs.RemoveAt( 0 );
  253. 				Console.Error.WriteLine( );
  254. 				Console.ForegroundColor = ConsoleColor.Red;
  255. 				Console.Error.Write( "ERROR:\t" );
  256. 				Console.ForegroundColor = ConsoleColor.White;
  257. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  258. 				Console.ResetColor( );
  259. 			}
  260.  
  261. 			#endregion Error Message
  262.  
  263.  
  264. 			#region Help Text
  265.  
  266. 			/*
  267. 			SystemTrayMessage.exe,  Version 1.05
  268. 			Display a tooltip message in the system tray's notification area
  269.  
  270. 			Usage:    SystemTrayMessage.exe  message  [ options ]
  271.  
  272. 			Where:    message     is the message text in the tooltip balloon
  273.  
  274. 			Options:  /I:icon     tooltip Icon (Error, Info, None, Warning; default: Info)
  275. 			          /L          treat message as Literal text without interpreting
  276. 			                      escaped characters, e.g. show "\n" as literal "\n"
  277. 			                      instead of interpreting it as a newline character
  278. 			          /P:path     Path to an icon file or library (default: Shell32.dll)
  279. 			          /S:index    System tray icon index in icon library (default: 277)
  280. 			          /T:title    specifies the optional Title in the tooltip balloon
  281. 			          /V:seconds  specifies the number of seconds the tooltip balloon
  282. 			                      will remain Visible (default: 10)
  283. 			          /W          Wait for the timeout to elapse or for the user to click
  284. 			                      the message, then remove the icon from the notification
  285. 			                      area (default: exit without waiting)
  286.  
  287. 			Notes:    By default, \n is interpreted as newline and \t as tab in message;
  288. 			          in some cases this may lead to misinterpretations, e.g. when showing
  289. 			          a path like "c:\temp"; either escape backslashes in paths or use /L
  290. 			          to treat all message text as literal text.
  291. 			          Command line switch /S will be ignored if switch /P specifies
  292. 			          anything but an icon library.
  293. 			          Use my Shell32Icons.exe to select a Shell32 icon and get its index.
  294. 			          Return code ("ErrorLevel") is -1 in case of errors; with /W switch,
  295. 			          return code is 2 if message balloon is clicked, or 3 if the timeout
  296. 			          expired without clicking; otherwise return code is 0.
  297.  
  298. 			Credits:  Code to extract icons from Shell32.dll by Thomas Levesque
  299. 			          http://stackoverflow.com/questions/6873026
  300.  
  301. 			Written by Rob van der Woude
  302. 			http://www.robvanderwoude.com
  303. 			*/
  304.  
  305. 			Console.Error.WriteLine( );
  306.  
  307. 			Console.Error.WriteLine( "SystemTrayMessage.exe,  Version {0}", progver );
  308.  
  309. 			Console.Error.WriteLine( "Display a tooltip message in the system tray's notification area" );
  310.  
  311. 			Console.Error.WriteLine( );
  312.  
  313. 			Console.Error.Write( "Usage:    " );
  314. 			Console.ForegroundColor = ConsoleColor.White;
  315. 			Console.Error.WriteLine( "SystemTrayMessage.exe  message  [ options ]" );
  316. 			Console.ResetColor( );
  317.  
  318. 			Console.Error.WriteLine( );
  319.  
  320. 			Console.Error.Write( "Where:    " );
  321. 			Console.ForegroundColor = ConsoleColor.White;
  322. 			Console.Error.Write( "message" );
  323. 			Console.ResetColor( );
  324. 			Console.Error.Write( "     is the " );
  325. 			Console.ForegroundColor = ConsoleColor.White;
  326. 			Console.Error.Write( "message" );
  327. 			Console.ResetColor( );
  328. 			Console.Error.WriteLine( " text in the tooltip balloon" );
  329.  
  330. 			Console.Error.WriteLine( );
  331.  
  332. 			Console.Error.Write( "Options:  " );
  333. 			Console.ForegroundColor = ConsoleColor.White;
  334. 			Console.Error.Write( "/I:icon" );
  335. 			Console.ResetColor( );
  336. 			Console.Error.Write( "     tooltip " );
  337. 			Console.ForegroundColor = ConsoleColor.White;
  338. 			Console.Error.Write( "I" );
  339. 			Console.ResetColor( );
  340. 			Console.Error.WriteLine( "con (Error, Info, None, Warning; default: Info)" );
  341.  
  342. 			Console.ForegroundColor = ConsoleColor.White;
  343. 			Console.Error.Write( "          /L" );
  344. 			Console.ResetColor( );
  345. 			Console.Error.Write( "          treat " );
  346. 			Console.ForegroundColor = ConsoleColor.White;
  347. 			Console.Error.Write( "message" );
  348. 			Console.ResetColor( );
  349. 			Console.Error.Write( " as " );
  350. 			Console.ForegroundColor = ConsoleColor.White;
  351. 			Console.Error.Write( "L" );
  352. 			Console.ResetColor( );
  353. 			Console.Error.WriteLine( "iteral text without interpreting" );
  354.  
  355. 			Console.Error.WriteLine( "                      escaped characters, e.g. show \"\\n\" as literal \"\\n\"" );
  356.  
  357. 			Console.Error.WriteLine( "                      instead of interpreting it as a newline character" );
  358.  
  359. 			Console.ForegroundColor = ConsoleColor.White;
  360. 			Console.Error.Write( "          /P:path     P" );
  361. 			Console.ResetColor( );
  362. 			Console.Error.WriteLine( "ath to an icon file or library (default: Shell32.dll)" );
  363.  
  364. 			Console.ForegroundColor = ConsoleColor.White;
  365. 			Console.Error.Write( "          /S:index    S" );
  366. 			Console.ResetColor( );
  367. 			Console.Error.Write( "ystem tray icon " );
  368. 			Console.ForegroundColor = ConsoleColor.White;
  369. 			Console.Error.Write( "index" );
  370. 			Console.ResetColor( );
  371. 			Console.Error.WriteLine( "  in icon library (default: 277)" );
  372.  
  373. 			Console.ForegroundColor = ConsoleColor.White;
  374. 			Console.Error.Write( "          /T:title" );
  375. 			Console.ResetColor( );
  376. 			Console.Error.Write( "    optional " );
  377. 			Console.ForegroundColor = ConsoleColor.White;
  378. 			Console.Error.Write( "T" );
  379. 			Console.ResetColor( );
  380. 			Console.Error.WriteLine( "itle in the tooltip balloon" );
  381.  
  382. 			Console.ForegroundColor = ConsoleColor.White;
  383. 			Console.Error.Write( "          /V:seconds" );
  384. 			Console.ResetColor( );
  385. 			Console.Error.Write( "  number of " );
  386. 			Console.ForegroundColor = ConsoleColor.White;
  387. 			Console.Error.Write( "seconds" );
  388. 			Console.ResetColor( );
  389. 			Console.Error.WriteLine( " the tooltip balloon will remain" );
  390.  
  391. 			Console.Error.Write( "" );
  392. 			Console.ForegroundColor = ConsoleColor.White;
  393. 			Console.Error.Write( "                      V" );
  394. 			Console.ResetColor( );
  395. 			Console.Error.WriteLine( "isible (default: 10)" );
  396.  
  397. 			Console.ForegroundColor = ConsoleColor.White;
  398. 			Console.Error.Write( "          /W          W" );
  399. 			Console.ResetColor( );
  400. 			Console.Error.WriteLine( "ait for the timeout to elapse or for the user to click" );
  401.  
  402. 			Console.Error.WriteLine( "                      the message, then remove the icon from the notification" );
  403.  
  404. 			Console.Error.WriteLine( "                      area (default: exit without waiting)" );
  405.  
  406. 			Console.Error.WriteLine( );
  407.  
  408. 			Console.Error.Write( "Notes:    By default, " );
  409. 			Console.ForegroundColor = ConsoleColor.White;
  410. 			Console.Error.Write( "\\n" );
  411. 			Console.ResetColor( );
  412. 			Console.Error.Write( " is interpreted as newline and " );
  413. 			Console.ForegroundColor = ConsoleColor.White;
  414. 			Console.Error.Write( "\\t" );
  415. 			Console.ResetColor( );
  416. 			Console.Error.Write( " as tab in " );
  417. 			Console.ForegroundColor = ConsoleColor.White;
  418. 			Console.Error.Write( "message" );
  419. 			Console.ResetColor( );
  420. 			Console.Error.WriteLine( ";" );
  421.  
  422. 			Console.Error.WriteLine( "          in some cases this may lead to misinterpretations, e.g. when showing" );
  423.  
  424. 			Console.Error.Write( "          a path like \"c:\\temp\"; either escape backslashes in paths or use " );
  425. 			Console.ForegroundColor = ConsoleColor.White;
  426. 			Console.Error.WriteLine( "/L" );
  427. 			Console.ResetColor( );
  428.  
  429. 			Console.Error.WriteLine( "          to treat all message text as literal text." );
  430.  
  431. 			Console.Error.Write( "          Command line switch " );
  432. 			Console.ForegroundColor = ConsoleColor.White;
  433. 			Console.Error.Write( "/S" );
  434. 			Console.ResetColor( );
  435. 			Console.Error.Write( " will be ignored if switch " );
  436. 			Console.ForegroundColor = ConsoleColor.White;
  437. 			Console.Error.Write( "/P" );
  438. 			Console.ResetColor( );
  439. 			Console.Error.WriteLine( " specifies" );
  440.  
  441. 			Console.Error.WriteLine( "          anything but an icon library." );
  442.  
  443. 			Console.Error.WriteLine( "          Use my Shell32Icons.exe to select a Shell32 icon and get its index." );
  444.  
  445. 			Console.Error.Write( "          Return code (\"ErrorLevel\") is -1 in case of errors; with " );
  446. 			Console.ForegroundColor = ConsoleColor.White;
  447. 			Console.Error.Write( "/W" );
  448. 			Console.ResetColor( );
  449. 			Console.Error.WriteLine( " switch," );
  450.  
  451. 			Console.Error.WriteLine( "          return code is 2 if message balloon is clicked, or 3 if the timeout" );
  452.  
  453. 			Console.Error.WriteLine( "          expired without clicking; otherwise return code is 0." );
  454.  
  455. 			Console.Error.WriteLine( );
  456.  
  457. 			Console.Error.WriteLine( "Credits:  Code to extract icons from Shell32.dll by Thomas Levesque" );
  458.  
  459. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  460. 			Console.Error.WriteLine( "          http://stackoverflow.com/questions/6873026" );
  461. 			Console.ResetColor( );
  462.  
  463. 			Console.Error.WriteLine( );
  464.  
  465. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  466.  
  467. 			Console.Error.WriteLine( "http://www.robvanderwoude.com" );
  468.  
  469. 			#endregion Help Text
  470.  
  471.  
  472. 			return -1;
  473. 		}
  474.  
  475.  
  476. 		// Code to extract icons from Shell32.dll by Thomas Levesque
  477. 		// http://stackoverflow.com/questions/6873026
  478. 		public class IconExtractor
  479. 		{
  480. 			public static Icon Extract( string file, int number, bool largeIcon )
  481. 			{
  482. 				IntPtr large;
  483. 				IntPtr small;
  484. 				ExtractIconEx( file, number, out large, out small, 1 );
  485. 				try
  486. 				{
  487. 					return Icon.FromHandle( largeIcon ? large : small );
  488. 				}
  489. 				catch
  490. 				{
  491. 					return null;
  492. 				}
  493. 			}
  494.  
  495. 			[DllImport( "Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall )]
  496. 			private static extern int ExtractIconEx( string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons );
  497. 		}
  498. 	}
  499. }
  500.  

page last uploaded: 2018-12-04, 10:47