1 using System; 2 using System.Collections.Generic; 3 using System.Diagnostics; 4 using System.Globalization; 5 using System.IO; 6 using System.Reflection; 7 using System.Text; 8 9 namespace MS.StrongName.ManagedSN 10 { 11 /// <summary> 12 /// Entry point for the ManagedSN tool. Handles the first level of command line parsing 13 /// and dispatching to appropriate methods for each option. 14 /// </summary> 15 public static class ManagedStrongName 16 { 17 /// <summary> 18 /// Return code for successfully completion 19 /// </summary> 20 public const int SuccessCode = 0; 21 22 /// <summary> 23 /// Return code when an error occurs or a failed completion 24 /// </summary> 25 public const int ErrorCode = 101; 26 27 private static IDictionary<string, Command> commands = null; 28 29 /// <summary> 30 /// Table of available commands 31 /// </summary> 32 internal static IDictionary<string, Command> CommandTable 33 { 34 get 35 { 36 if(commands == null) 37 commands = CreateCommandTable(); 38 39 return commands; 40 } 41 } 42 43 /// <summary> 44 /// Managed tool that provides the same services as the .NET SDK's sn.exe tool 45 /// </summary> 46 public static int Main(string[] args) 47 { 48 Log.Message(String.Format( 49 CultureInfo.CurrentCulture, 50 Resources.Header, 51 FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion)); 52 Log.Message(String.Empty); 53 54 // make sure we hook all unexpected errors to fail more gracefully 55 AppDomain.CurrentDomain.UnhandledException += delegate(object sender, UnhandledExceptionEventArgs e) 56 { 57 Log.Error(Resources.InternalError); 58 Log.Error(e.ExceptionObject.ToString()); 59 return; 60 }; 61 62 // get the first command line option 63 string option; 64 if(args.Length >= 1) 65 { 66 option = args[0].Trim(); 67 if(String.IsNullOrEmpty(option)) 68 option = "?"; // empty means get help 69 70 // get the - or / off the front of the option 71 if(option[0] == '-' || option[0] == '/') 72 option = option.Substring(1, option.Length - 1); 73 } 74 else 75 option = "?"; // no options means get help 76 77 // go do what's requested of us 78 OptionHandler handler; 79 Command command = CommandTable[option]; 80 81 // null means we had an invalid option 82 if(command == null) 83 handler = new OptionHandler(InvalidOption); 84 else 85 handler = command.Handler; 86 87 return handler(args); 88 } 89 90 /// <summary> 91 /// Setup the table of options -> SN commands 92 /// </summary> 93 /// <returns>A dictionary mapping option names to Command objects</returns> 94 private static IDictionary<string, Command> CreateCommandTable() 95 { 96 Command[] commandList = new Command[] 97 { 98 new Command("d", new OptionHandler(Commands.DeleteKeyPair), Resources.DeleteKeyPairArguments, Resources.DeleteKeyPairHelp), 99 new Command("e", new OptionHandler(Commands.ExtractAssemblyPublicKey), Resources.ExtractAssemblyPublicKeyArguments, Resources.ExtractAssemblyPublicKeyHelp), 100 new Command("h", new OptionHandler(Commands.Help), null, Resources.HelpHelp), 101 new Command("?", new OptionHandler(Commands.Help), null, Resources.HelpHelp), 102 new Command("i", new OptionHandler(Commands.InstallKeyPair), Resources.InstallKeyPairArguments, Resources.InstallKeyPairHelp), 103 new Command("k", new OptionHandler(Commands.GenerateKey), Resources.GenerateKeyArguments, Resources.GenerateKeyHelp), 104 new Command("m", new OptionHandler(Commands.MachineKeyStore), Resources.MachineKeyStoreArguments, Resources.MachineKeyStoreHelp), 105 new Command("p", new OptionHandler(Commands.ExtractPublicKeyFromKeyPair), Resources.ExtractPublicKeyFromKeyPairArguments, Resources.ExtractPublicKeyFromKeyPairHelp), 106 new Command("pc", new OptionHandler(Commands.ExtractPublicKeyFromKeyContainer), Resources.ExtractPublicKeyFromKeyContainerArguments, Resources.ExtractPublicKeyFromKeyContainerHelp), 107 new Command("t", new OptionHandler(Commands.DisplayPublicKeyTokenFromFile), Resources.DisplayPublicKeyTokenFromFileArguments, Resources.DisplayPublicKeyTokenFromFileHelp), 108 new Command("tp", new OptionHandler(Commands.DisplayPublicKeyTokenWithKeyFromFile), Resources.DisplayPublicKeyTokenWithKeyFromFileArguments, Resources.DisplayPublicKeyTokenWithKeyFromFileHelp), 109 new Command("T", new OptionHandler(Commands.DisplayPublicKeyTokenFromAssembly), Resources.DisplayPublicKeyTokenFromAssemblyArguments, Resources.DisplayPublicKeyTokenFromAssemblyHelp), 110 new Command("Tp", new OptionHandler(Commands.DisplayPublicKeyTokenWithKeyFromAssembly), Resources.DisplayPublicKeyTokenWithKeyFromAssemblyArguments, Resources.DisplayPublicKeyTokenWithKeyFromAssemblyHelp), 111 new Command("v", new OptionHandler(Commands.Verify), Resources.VerifyArguments, Resources.VerifyHelp), 112 new Command("vf", new OptionHandler(Commands.ForceVerify), Resources.ForceVerifyArguments, Resources.ForceVerifyHelp) 113 }; 114 115 // set the commands up in a dictionary 116 Dictionary<string, Command> commandTable = new Dictionary<string, Command>(commandList.Length); 117 foreach(Command command in commandList) 118 commandTable[command.Option] = command; 119 120 return commandTable; 121 } 122 123 /// <summary> 124 /// Display help for an invalid option 125 /// </summary> 126 private static int InvalidOption(string[] arguments) 127 { 128 Debug.Assert(arguments.Length > 0); 129 130 Log.Error(String.Format( 131 CultureInfo.InvariantCulture, 132 Resources.InvalidOption, 133 arguments[0])); 134 Log.Error(String.Empty); 135 136 return Commands.Help(arguments); 137 } 138 139 /// <summary> 140 /// Format a help string to be displayed on multiple lines 141 /// </summary> 142 /// <param name="help">help string to format</param> 143 /// <param name="padding">number of spaces to add to the beginning of each line</param> 144 public static string[] FormatHelp(string help, int padding) 145 { 146 Debug.Assert(help != null, "Null help string"); 147 Debug.Assert(padding >= 0, "Invalid padding value"); 148 149 int consoleSize = Console.WindowWidth; 150 List<string> lines = new List<string>((help.Length / consoleSize) + 1); 151 152 // split on whitespace 153 string[] words = help.Split(new char[] {' ', '\t', '\n'}); 154 155 // setup the first line 156 StringBuilder currentLine = new StringBuilder(consoleSize); 157 currentLine.Append(' ', (int)padding); 158 159 // add each word in the help text 160 foreach(string word in words) 161 { 162 // if this word will make the line too big, start a new line 163 // allow an exception for the first word of a line, to prevent 164 // infinite looping when one word is bigger than the console 165 if(currentLine.Length != padding && currentLine.Length + word.Length >= consoleSize) 166 { 167 lines.Add(currentLine.ToString()); 168 169 currentLine = new StringBuilder(consoleSize); 170 currentLine.Append(' ', (int)padding); 171 } 172 173 currentLine.Append(word); 174 currentLine.Append(' '); 175 } 176 177 // finish the last line 178 lines.Add(currentLine.ToString()); 179 return lines.ToArray(); 180 } 181 } 182 }