(view source code of tostring.cs as plain text)
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
namespace RobvanderWoude
{
internal class ToString
{
static readonly string progver = "1.02";
static string template;
static string decimalseparator = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator;
static int Main( string[] args )
{
if ( args.Length == 0 )
{
return ShowHelp( );
}
foreach ( string arg in args )
{
if ( arg == "/?" )
{
return ShowHelp( );
}
}
List<string> arguments = new List<string>( args );
template = arguments[0].Replace( "\\n", "\n" ).Replace( "\\r", "\r" ).Replace( "\\t", "\t" );
arguments.RemoveAt( 0 );
if ( Console.IsInputRedirected )
{
if ( args.Length == 1 )
{
int rc = 0;
string[] lines = Console.In.ReadToEnd( ).Split( '\n' );
for ( int i = 0; i < lines.Length; i++ )
{
if ( !string.IsNullOrWhiteSpace( lines[i] ) )
{
rc += ParseLine( CommandLineToArgs( lines[i] ) );
}
}
if ( rc == 0 )
{
return 0;
}
return -1;
}
else
{
return ShowHelp( "Specify only template on command line when using redirected arguments" );
}
}
else if ( args.Length > 1 )
{
return ParseLine( arguments.ToArray( ) );
}
else
{
return ShowHelp( );
}
}
static int ParseLine( string[] arguments )
{
object[] values = new object[arguments.Length]; // copy of arguments[] but with different types
for ( int i = 0; i < arguments.Length; i++ )
{
if ( float.TryParse( arguments[i], out float floatvalue ) )
{
if ( int.TryParse( arguments[i], out int intvalue ) )
{
if ( floatvalue == intvalue )
{
values[i] = intvalue;
}
else
{
values[i] = floatvalue;
}
}
else
{
values[i] = floatvalue;
}
}
else if ( DateTime.TryParse( arguments[i], out DateTime datetimevalue ) )
{
values[i] = datetimevalue;
}
else if ( DateTime.TryParse( arguments[i].Replace( decimalseparator, "." ), out datetimevalue ) )
{
// Work-around for issue with decimal separator in time strings (on Dutch systems)
values[i] = datetimevalue;
}
else
{
values[i] = arguments[i];
}
}
try
{
Console.WriteLine( template, values );
return 0;
}
catch ( Exception e )
{
return ShowHelp( e.Message );
}
}
#region Convert redirected input to command line args
// Code by Atif Aziz on StackOverflow.com:
// https://stackoverflow.com/a/749653
[DllImport( "shell32.dll", SetLastError = true )]
static extern IntPtr CommandLineToArgvW( [MarshalAs( UnmanagedType.LPWStr )] string lpCmdLine, out int pNumArgs );
public static string[] CommandLineToArgs( string commandLine )
{
int argc;
var argv = CommandLineToArgvW( commandLine, out argc );
if ( argv == IntPtr.Zero )
throw new System.ComponentModel.Win32Exception( );
try
{
var args = new string[argc];
for ( var i = 0; i < args.Length; i++ )
{
var p = Marshal.ReadIntPtr( argv, i * IntPtr.Size );
args[i] = Marshal.PtrToStringUni( p );
}
return args;
}
finally
{
Marshal.FreeHGlobal( argv );
}
}
#endregion Convert redirected input to command line args
static int ShowHelp( params string[] errmsg )
{
#region Error Message
if ( errmsg.Length > 0 )
{
List<string> errargs = new List<string>( errmsg );
errargs.RemoveAt( 0 );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.Write( "ERROR:\t" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
Console.ResetColor( );
}
#endregion Error Message
#region Help Text
/*
ToString.exe, Version 1.01
Batch tool to format numbers and dates the .NET way
Usage: ToString.exe template arguments
or: some_command | ToString.exe template
Where: template string specifying how the arguments will be formated
arguments single or multiple numbers or dates to be formated
some_command command supplying the argument(s) in its standard output
(multiple lines of input will each be parsed separately)
Example: ToString "{0,6:F2}\t0x{1:X8}\t{2:dd-MM-yyyy}" "0.125" 500 2022-02-24
Returns: 0,13 0x000001F4 24-02-2022
Example: ToString "{0:yyyyMMddTHHmmssfffzzz}" %Time%
Returns: 20220225T121343800+01:00
Example: TIME /T | ToString "{0:yyyyMMddTHHmmssfffzzz}"
Returns: 20220225T121343800+01:00
Example: ToString "{0}" %Time%
Returns: 2022-02-25 15:34:18
Example: ToString "{0}" %Date%
Returns: 2022-02-25 00:00:00
Example: DIR %UserProfile%\.. | FIND "<DIR>" | ToString "{0:D}, {1:T}\t{3}"
Returns: Saturday, 1 January 2022, 09:44:00 .
Saturday, 1 January 2022, 09:44:00 ..
Wednesday, 16 February 2022, 17:22:00 Default
Wednesday, 3 February 2021, 16:46:00 Public
Saturday, 22 January 2022, 09:25:00 Rob
Quirks: Regardless of date and time separators specified in the template,
ToString may still use your culture's separators in its output.
On the other hand, it may have a problem with decimal separators
in a specified time string, even if it complies with your culture;
some code has been added to provide for this issue.
Note: Return code will be -1 if errors were encountered, otherwise 0.
Credits: Merge redirected input with command line by Atif Aziz
https://stackoverflow.com/a/749653
Written by Rob van der Woude
https://www.robvanderwoude.com
*/
#endregion Help Text
#region Display Help Text
Console.Error.WriteLine( );
Console.Error.WriteLine( "ToString.exe, Version {0}", progver );
Console.Error.WriteLine( "Batch tool to format numbers and dates the .NET way" );
Console.Error.WriteLine( );
Console.Error.Write( "Usage: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "ToString.exe template arguments" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.Write( " or: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "some_command | ToString.exe template" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.Write( "Where: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "template" );
Console.ResetColor( );
Console.Error.WriteLine( " string specifying how the arguments will be formated" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " arguments" );
Console.ResetColor( );
Console.Error.WriteLine( " single or multiple numbers or dates to be formated" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " some_command" );
Console.ResetColor( );
Console.Error.WriteLine( " command supplying the argument(s) in its standard output" );
Console.Error.WriteLine( " (multiple lines of input will each be parsed separately)" );
Console.Error.WriteLine( );
Console.Error.Write( "Example: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "ToString \"{0,6:F2}\\t0x{1:X8}\\t{2:dd-MM-yyyy}\" \"0.125\" 500 2022-02-24" );
Console.ResetColor( );
Console.Error.Write( "Returns: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( " 0,13\t0x000001F4\t24-02-2022" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.Write( "Example: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "ToString \"{0:yyyyMMddTHHmmssfffzzz}\" %Time%" );
Console.ResetColor( );
Console.Error.Write( "Returns: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( DateTime.Now.ToString( "yyyyMMddTHHmmssfffzzz" ) );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.Write( "Example: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "TIME /T | ToString \"{0:yyyyMMddTHHmmssfffzzz}\"" );
Console.ResetColor( );
Console.Error.Write( "Returns: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( DateTime.Now.ToString( "yyyyMMddTHHmmssfffzzz" ) );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.Write( "Example: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "ToString \"{0}\" %Time%" );
Console.ResetColor( );
Console.Error.Write( "Returns: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( DateTime.Now.ToString( ) );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.Write( "Example: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "ToString \"{0}\" %Date%" );
Console.ResetColor( );
Console.Error.Write( "Returns: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( DateTime.Now.Date.ToString( ) );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.Write( "Example: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "DIR %UserProfile%\\.. | FIND \"<DIR>\" | ToString \"{0:D}, {1:T}\\t{3}\"" );
Console.ResetColor( );
Console.Error.Write( "Returns: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "Saturday, 1 January 2022, 09:44:00\t." );
Console.Error.WriteLine( " Saturday, 1 January 2022, 09:44:00\t.." );
Console.Error.WriteLine( " Wednesday, 16 February 2022, 17:22:00\tDefault" );
Console.Error.WriteLine( " Wednesday, 3 February 2021, 16:46:00\tPublic" );
Console.Error.WriteLine( " Saturday, 22 January 2022, 09:25:00\t{0}", Environment.GetEnvironmentVariable( "UserName" ) );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Quirks: Regardless of date and time separators specified in the template," );
Console.Error.WriteLine( " ToString may still use your culture's separators in its output." );
Console.Error.WriteLine( " On the other hand, it may have a problem with decimal separators" );
Console.Error.WriteLine( " in a specified time string, even if it complies with your culture;" );
Console.Error.WriteLine( " some code has been added to provide for this issue." );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Note: Return code will be -1 if errors were encountered, otherwise 0." );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Credits: Merge redirected input with command line by Atif Aziz" );
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.Error.WriteLine( " https://stackoverflow.com/a/749653" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Written by Rob van der Woude" );
Console.Error.WriteLine( "https://www.robvanderwoude.com" );
#endregion Display Help Text
return -1;
}
}
}
page last modified: 2024-04-16; loaded in 0.0082 seconds