Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for tostring.cs

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Runtime.InteropServices;
  5.  
  6.  
  7. namespace RobvanderWoude
  8. {
  9. 	internal class ToString
  10. 	{
  11. 		static readonly string progver = "1.02";
  12.  
  13. 		static string template;
  14. 		static string decimalseparator = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator;
  15.  
  16.  
  17. 		static int Main( string[] args )
  18. 		{
  19. 			if ( args.Length == 0 )
  20. 			{
  21. 				return ShowHelp( );
  22. 			}
  23. 			foreach ( string arg in args )
  24. 			{
  25. 				if ( arg == "/?" )
  26. 				{
  27. 					return ShowHelp( );
  28. 				}
  29. 			}
  30.  
  31. 			List<string> arguments = new List<string>( args );
  32. 			template = arguments[0].Replace( "\\n", "\n" ).Replace( "\\r", "\r" ).Replace( "\\t", "\t" );
  33. 			arguments.RemoveAt( 0 );
  34.  
  35. 			if ( Console.IsInputRedirected )
  36. 			{
  37. 				if ( args.Length == 1 )
  38. 				{
  39. 					int rc = 0;
  40. 					string[] lines = Console.In.ReadToEnd( ).Split( '\n' );
  41. 					for ( int i = 0; i < lines.Length; i++ )
  42. 					{
  43. 						if ( !string.IsNullOrWhiteSpace( lines[i] ) )
  44. 						{
  45. 							rc += ParseLine( CommandLineToArgs( lines[i] ) );
  46. 						}
  47. 					}
  48. 					if ( rc == 0 )
  49. 					{
  50. 						return 0;
  51. 					}
  52. 					return -1;
  53. 				}
  54. 				else
  55. 				{
  56. 					return ShowHelp( "Specify only template on command line when using redirected arguments" );
  57. 				}
  58. 			}
  59. 			else if ( args.Length > 1 )
  60. 			{
  61. 				return ParseLine( arguments.ToArray( ) );
  62. 			}
  63. 			else
  64. 			{
  65. 				return ShowHelp( );
  66. 			}
  67. 		}
  68.  
  69.  
  70. 		static int ParseLine( string[] arguments )
  71. 		{
  72. 			object[] values = new object[arguments.Length]; // copy of arguments[] but with different types
  73. 			for ( int i = 0; i < arguments.Length; i++ )
  74. 			{
  75. 				if ( float.TryParse( arguments[i], out float floatvalue ) )
  76. 				{
  77. 					if ( int.TryParse( arguments[i], out int intvalue ) )
  78. 					{
  79. 						if ( floatvalue == intvalue )
  80. 						{
  81. 							values[i] = intvalue;
  82. 						}
  83. 						else
  84. 						{
  85. 							values[i] = floatvalue;
  86. 						}
  87. 					}
  88. 					else
  89. 					{
  90. 						values[i] = floatvalue;
  91. 					}
  92. 				}
  93. 				else if ( DateTime.TryParse( arguments[i], out DateTime datetimevalue ) )
  94. 				{
  95. 					values[i] = datetimevalue;
  96. 				}
  97. 				else if ( DateTime.TryParse( arguments[i].Replace( decimalseparator, "." ), out datetimevalue ) )
  98. 				{
  99. 					// Work-around for issue with decimal separator in time strings (on Dutch systems)
  100. 					values[i] = datetimevalue;
  101. 				}
  102. 				else
  103. 				{
  104. 					values[i] = arguments[i];
  105. 				}
  106. 			}
  107. 			try
  108. 			{
  109. 				Console.WriteLine( template, values );
  110. 				return 0;
  111. 			}
  112. 			catch ( Exception e )
  113. 			{
  114. 				return ShowHelp( e.Message );
  115. 			}
  116. 		}
  117.  
  118.  
  119. 		#region Convert redirected input to command line args
  120.  
  121. 		// Code by Atif Aziz on StackOverflow.com:
  122. 		// https://stackoverflow.com/a/749653
  123. 		[DllImport( "shell32.dll", SetLastError = true )]
  124. 		static extern IntPtr CommandLineToArgvW( [MarshalAs( UnmanagedType.LPWStr )] string lpCmdLine, out int pNumArgs );
  125.  
  126.  
  127. 		public static string[] CommandLineToArgs( string commandLine )
  128. 		{
  129. 			int argc;
  130. 			var argv = CommandLineToArgvW( commandLine, out argc );
  131. 			if ( argv == IntPtr.Zero )
  132. 				throw new System.ComponentModel.Win32Exception( );
  133. 			try
  134. 			{
  135. 				var args = new string[argc];
  136. 				for ( var i = 0; i < args.Length; i++ )
  137. 				{
  138. 					var p = Marshal.ReadIntPtr( argv, i * IntPtr.Size );
  139. 					args[i] = Marshal.PtrToStringUni( p );
  140. 				}
  141.  
  142. 				return args;
  143. 			}
  144. 			finally
  145. 			{
  146. 				Marshal.FreeHGlobal( argv );
  147. 			}
  148. 		}
  149.  
  150. 		#endregion Convert redirected input to command line args
  151.  
  152.  
  153. 		static int ShowHelp( params string[] errmsg )
  154. 		{
  155. 			#region Error Message
  156.  
  157. 			if ( errmsg.Length > 0 )
  158. 			{
  159. 				List<string> errargs = new List<string>( errmsg );
  160. 				errargs.RemoveAt( 0 );
  161. 				Console.Error.WriteLine( );
  162. 				Console.ForegroundColor = ConsoleColor.Red;
  163. 				Console.Error.Write( "ERROR:\t" );
  164. 				Console.ForegroundColor = ConsoleColor.White;
  165. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  166. 				Console.ResetColor( );
  167. 			}
  168.  
  169. 			#endregion Error Message
  170.  
  171.  
  172. 			#region Help Text
  173.  
  174. 			/*
  175. 			ToString.exe,  Version 1.01
  176. 			Batch tool to format numbers and dates the .NET way
  177.  
  178. 			Usage:   ToString.exe  template  arguments
  179.  
  180. 			   or:   some_command  |  ToString.exe  template
  181.  
  182. 			Where:   template      string specifying how the arguments will be formated
  183. 			         arguments     single or multiple numbers or dates to be formated
  184. 			         some_command  command supplying the argument(s) in its standard output
  185. 			                       (multiple lines of input will each be parsed separately)
  186.  
  187. 			Example: ToString "{0,6:F2}\t0x{1:X8}\t{2:dd-MM-yyyy}" "0.125" 500 2022-02-24
  188. 			Returns:   0,13    0x000001F4      24-02-2022
  189.  
  190. 			Example: ToString "{0:yyyyMMddTHHmmssfffzzz}" %Time%
  191. 			Returns: 20220225T121343800+01:00
  192.  
  193. 			Example: TIME /T | ToString "{0:yyyyMMddTHHmmssfffzzz}"
  194. 			Returns: 20220225T121343800+01:00
  195.  
  196. 			Example: ToString "{0}" %Time%
  197. 			Returns: 2022-02-25 15:34:18
  198.  
  199. 			Example: ToString "{0}" %Date%
  200. 			Returns: 2022-02-25 00:00:00
  201.  
  202. 			Example: DIR %UserProfile%\.. | FIND "<DIR>" | ToString "{0:D}, {1:T}\t{3}"
  203. 			Returns: Saturday, 1 January 2022, 09:44:00     .
  204. 			         Saturday, 1 January 2022, 09:44:00     ..
  205. 			         Wednesday, 16 February 2022, 17:22:00  Default
  206. 			         Wednesday, 3 February 2021, 16:46:00   Public
  207. 			         Saturday, 22 January 2022, 09:25:00    Rob
  208.  
  209. 			Quirks:  Regardless of date and time separators specified in the template,
  210. 			         ToString may still use your culture's separators in its output.
  211. 			         On the other hand, it may have a problem with decimal separators
  212. 			         in a specified time string, even if it complies with your culture;
  213. 			         some code has been added to provide for this issue.
  214.  
  215. 			Note:    Return code will be -1 if errors were encountered, otherwise 0.
  216.  
  217. 			Credits: Merge redirected input with command line by Atif Aziz
  218. 			         https://stackoverflow.com/a/749653
  219.  
  220. 			Written by Rob van der Woude
  221. 			https://www.robvanderwoude.com
  222. 			*/
  223.  
  224. 			#endregion Help Text
  225.  
  226.  
  227. 			#region Display Help Text
  228.  
  229. 			Console.Error.WriteLine( );
  230.  
  231. 			Console.Error.WriteLine( "ToString.exe,  Version {0}", progver );
  232.  
  233. 			Console.Error.WriteLine( "Batch tool to format numbers and dates the .NET way" );
  234.  
  235. 			Console.Error.WriteLine( );
  236.  
  237. 			Console.Error.Write( "Usage:   " );
  238. 			Console.ForegroundColor = ConsoleColor.White;
  239. 			Console.Error.WriteLine( "ToString.exe  template  arguments" );
  240. 			Console.ResetColor( );
  241.  
  242. 			Console.Error.WriteLine( );
  243.  
  244. 			Console.Error.Write( "   or:   " );
  245. 			Console.ForegroundColor = ConsoleColor.White;
  246. 			Console.Error.WriteLine( "some_command  |  ToString.exe  template" );
  247. 			Console.ResetColor( );
  248.  
  249. 			Console.Error.WriteLine( );
  250.  
  251. 			Console.Error.Write( "Where:   " );
  252. 			Console.ForegroundColor = ConsoleColor.White;
  253. 			Console.Error.Write( "template" );
  254. 			Console.ResetColor( );
  255. 			Console.Error.WriteLine( "      string specifying how the arguments will be formated" );
  256.  
  257. 			Console.ForegroundColor = ConsoleColor.White;
  258. 			Console.Error.Write( "         arguments" );
  259. 			Console.ResetColor( );
  260. 			Console.Error.WriteLine( "     single or multiple numbers or dates to be formated" );
  261.  
  262. 			Console.ForegroundColor = ConsoleColor.White;
  263. 			Console.Error.Write( "         some_command" );
  264. 			Console.ResetColor( );
  265. 			Console.Error.WriteLine( "  command supplying the argument(s) in its standard output" );
  266.  
  267. 			Console.Error.WriteLine( "                       (multiple lines of input will each be parsed separately)" );
  268.  
  269. 			Console.Error.WriteLine( );
  270.  
  271. 			Console.Error.Write( "Example: " );
  272. 			Console.ForegroundColor = ConsoleColor.White;
  273. 			Console.Error.WriteLine( "ToString \"{0,6:F2}\\t0x{1:X8}\\t{2:dd-MM-yyyy}\" \"0.125\" 500 2022-02-24" );
  274. 			Console.ResetColor( );
  275.  
  276. 			Console.Error.Write( "Returns: " );
  277. 			Console.ForegroundColor = ConsoleColor.White;
  278. 			Console.Error.WriteLine( "  0,13\t0x000001F4\t24-02-2022" );
  279. 			Console.ResetColor( );
  280.  
  281. 			Console.Error.WriteLine( );
  282.  
  283. 			Console.Error.Write( "Example: " );
  284. 			Console.ForegroundColor = ConsoleColor.White;
  285. 			Console.Error.WriteLine( "ToString \"{0:yyyyMMddTHHmmssfffzzz}\" %Time%" );
  286. 			Console.ResetColor( );
  287.  
  288. 			Console.Error.Write( "Returns: " );
  289. 			Console.ForegroundColor = ConsoleColor.White;
  290. 			Console.Error.WriteLine( DateTime.Now.ToString( "yyyyMMddTHHmmssfffzzz" ) );
  291. 			Console.ResetColor( );
  292.  
  293. 			Console.Error.WriteLine( );
  294.  
  295. 			Console.Error.Write( "Example: " );
  296. 			Console.ForegroundColor = ConsoleColor.White;
  297. 			Console.Error.WriteLine( "TIME /T | ToString \"{0:yyyyMMddTHHmmssfffzzz}\"" );
  298. 			Console.ResetColor( );
  299.  
  300. 			Console.Error.Write( "Returns: " );
  301. 			Console.ForegroundColor = ConsoleColor.White;
  302. 			Console.Error.WriteLine( DateTime.Now.ToString( "yyyyMMddTHHmmssfffzzz" ) );
  303. 			Console.ResetColor( );
  304.  
  305. 			Console.Error.WriteLine( );
  306.  
  307. 			Console.Error.Write( "Example: " );
  308. 			Console.ForegroundColor = ConsoleColor.White;
  309. 			Console.Error.WriteLine( "ToString \"{0}\" %Time%" );
  310. 			Console.ResetColor( );
  311.  
  312. 			Console.Error.Write( "Returns: " );
  313. 			Console.ForegroundColor = ConsoleColor.White;
  314. 			Console.Error.WriteLine( DateTime.Now.ToString( ) );
  315. 			Console.ResetColor( );
  316.  
  317. 			Console.Error.WriteLine( );
  318.  
  319. 			Console.Error.Write( "Example: " );
  320. 			Console.ForegroundColor = ConsoleColor.White;
  321. 			Console.Error.WriteLine( "ToString \"{0}\" %Date%" );
  322. 			Console.ResetColor( );
  323.  
  324. 			Console.Error.Write( "Returns: " );
  325. 			Console.ForegroundColor = ConsoleColor.White;
  326. 			Console.Error.WriteLine( DateTime.Now.Date.ToString( ) );
  327. 			Console.ResetColor( );
  328.  
  329. 			Console.Error.WriteLine( );
  330.  
  331. 			Console.Error.Write( "Example: " );
  332. 			Console.ForegroundColor = ConsoleColor.White;
  333. 			Console.Error.WriteLine( "DIR %UserProfile%\\.. | FIND \"<DIR>\" | ToString \"{0:D}, {1:T}\\t{3}\"" );
  334. 			Console.ResetColor( );
  335.  
  336. 			Console.Error.Write( "Returns: " );
  337.  
  338. 			Console.ForegroundColor = ConsoleColor.White;
  339. 			Console.Error.WriteLine( "Saturday, 1 January 2022, 09:44:00\t." );
  340.  
  341. 			Console.Error.WriteLine( "         Saturday, 1 January 2022, 09:44:00\t.." );
  342.  
  343. 			Console.Error.WriteLine( "         Wednesday, 16 February 2022, 17:22:00\tDefault" );
  344.  
  345. 			Console.Error.WriteLine( "         Wednesday, 3 February 2021, 16:46:00\tPublic" );
  346.  
  347. 			Console.Error.WriteLine( "         Saturday, 22 January 2022, 09:25:00\t{0}", Environment.GetEnvironmentVariable( "UserName" ) );
  348. 			Console.ResetColor( );
  349.  
  350. 			Console.Error.WriteLine( );
  351.  
  352. 			Console.Error.WriteLine( "Quirks:  Regardless of date and time separators specified in the template," );
  353.  
  354. 			Console.Error.WriteLine( "         ToString may still use your culture's separators in its output." );
  355.  
  356. 			Console.Error.WriteLine( "         On the other hand, it may have a problem with decimal separators" );
  357.  
  358. 			Console.Error.WriteLine( "         in a specified time string, even if it complies with your culture;" );
  359.  
  360. 			Console.Error.WriteLine( "         some code has been added to provide for this issue." );
  361.  
  362. 			Console.Error.WriteLine( );
  363.  
  364. 			Console.Error.WriteLine( "Note:    Return code will be -1 if errors were encountered, otherwise 0." );
  365.  
  366. 			Console.Error.WriteLine( );
  367.  
  368. 			Console.Error.WriteLine( "Credits: Merge redirected input with command line by Atif Aziz" );
  369.  
  370. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  371. 			Console.Error.WriteLine( "         https://stackoverflow.com/a/749653" );
  372. 			Console.ResetColor( );
  373.  
  374. 			Console.Error.WriteLine( );
  375.  
  376. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  377.  
  378. 			Console.Error.WriteLine( "https://www.robvanderwoude.com" );
  379.  
  380. 			#endregion Display Help Text
  381.  
  382.  
  383. 			return -1;
  384. 		}
  385. 	}
  386. }
  387.  

page last uploaded: 2021-01-27