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

page last uploaded: 2019-01-21, 22:48