private static int Main() { Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US"); ConsoleHelper.FixEncoding(); List<string> assemblyFileNames = new List<string>(); CommandLineHelper cmdLine = new CommandLineHelper(); var debugOption = cmdLine.RegisterOption("debug").Alias("d"); var helpOption = cmdLine.RegisterOption("help").Alias("h", "?"); var noGzOption = cmdLine.RegisterOption("nogz"); var noNamesOption = cmdLine.RegisterOption("nonames"); var optimizeOption = cmdLine.RegisterOption("optimize").Alias("opt"); var outFileOption = cmdLine.RegisterOption("outfile", 1).Alias("o"); var srcBaseOption = cmdLine.RegisterOption("srcbase", 1); try { cmdLine.Parse(); } catch (Exception ex) { return ConsoleHelper.ExitError(ex.Message, 1); } if (helpOption.IsSet) { ShowHelp(); return 0; } try { foreach (var arg in cmdLine.FreeArguments) { if (arg.IndexOfAny(new[] { '?', '*' }) != -1) { foreach (string foundFile in Directory.GetFiles(Path.GetDirectoryName(arg), Path.GetFileName(arg))) { CheckAddAssemblyFile(assemblyFileNames, foundFile); } } else { CheckAddAssemblyFile(assemblyFileNames, arg); } } } catch (Exception ex) { return ConsoleHelper.ExitError("Cannot load input files. " + ex.Message, 5); } if (assemblyFileNames.Count == 0) { return ConsoleHelper.ExitError("Missing argument: Input assembly file name", 2); } if (debugOption.IsSet) { ConsoleHelper.WriteLine("Input assemblies:", ConsoleColor.DarkGray); foreach (string fileName in assemblyFileNames) { ConsoleHelper.WriteLine(" " + fileName, ConsoleColor.DarkGray); } } XmlDocument doc = new XmlDocument(); XmlWriter xw = doc.CreateNavigator().AppendChild(); PdbReader reader = new PdbReader(assemblyFileNames, xw); if (srcBaseOption.IsSet) { reader.SourceBasePath = Path.GetFullPath(srcBaseOption.Value); } try { reader.Convert(); } catch (System.Reflection.ReflectionTypeLoadException ex) { if (ex.LoaderExceptions != null) { ConsoleHelper.WriteLine("ReflectionTypeLoadException.LoaderExceptions:", ConsoleColor.Red); foreach (var ex2 in ex.LoaderExceptions) { ConsoleHelper.WriteWrapped("- " + ex2.Message); } } return ConsoleHelper.ExitError("Cannot convert symbols. " + ex.Message, 3); } catch (Exception ex) { return ConsoleHelper.ExitError("Cannot convert symbols. " + ex.Message, 3); } xw.Close(); if (optimizeOption.IsSet) { // Reduce multiple subsequent "hidden" sequence points to the first of them doc.SelectNodes("/symbols/module/methods/method/sequencePoints/entry[@hidden='true'][preceding-sibling::entry[1][@hidden='true']]") .OfType<XmlNode>() .ForEachSafe(n => n.ParentNode.RemoveChild(n)); // Remove sequence points if they are all hidden doc.SelectNodes("/symbols/module/methods/method/sequencePoints[not(entry[@startLine])]") .OfType<XmlNode>() .ForEachSafe(n => n.ParentNode.RemoveChild(n)); // Remove all methods with no sequence points doc.SelectNodes("/symbols/module/methods/method[not(sequencePoints)]") .OfType<XmlNode>() .ForEachSafe(n => n.ParentNode.RemoveChild(n)); // Remove all files with no remaining methods doc.SelectNodes("/symbols/module/files/file") .OfType<XmlNode>() .ForEachSafe(n => { if (n.SelectNodes("../../methods/method/sequencePoints/entry[@fileRef='" + n.Attributes["id"].Value + "']").Count == 0) { n.ParentNode.RemoveChild(n); } }); } if (noNamesOption.IsSet) { // Remove all name attributes from methods doc.SelectNodes("/symbols/module/methods/method") .OfType<XmlNode>() .ForEachSafe(n => n.Attributes.RemoveNamedItem("name")); } string xmlFileName = outFileOption.Value ?? Path.ChangeExtension( assemblyFileNames.OrderBy(a => Path.GetExtension(a).Equals(".dll", StringComparison.OrdinalIgnoreCase)).First(), (noGzOption.IsSet ? ".pdb.xml" : ".pdbx")); if (debugOption.IsSet) { ConsoleHelper.WriteLine("Output file:", ConsoleColor.DarkGray); ConsoleHelper.WriteLine(" " + xmlFileName, ConsoleColor.DarkGray); } try { if (!noGzOption.IsSet) { using (FileStream fileStream = new FileStream(xmlFileName, FileMode.Create)) using (GZipStream gzStream = new GZipStream(fileStream, CompressionMode.Compress)) { doc.Save(gzStream); } } else { doc.Save(xmlFileName); } } catch (Exception ex) { return ConsoleHelper.ExitError("Cannot save XML file. " + ex.Message, 4); } return 0; }
protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); // Fix WPF's built-in themes if (OSInfo.IsWindows8OrNewer) { ReAddResourceDictionary("/Resources/RealWindows8.xaml"); } // Initialise and show the main window CommandLineHelper cmdLine = new CommandLineHelper(); var scanOption = cmdLine.RegisterOption("scan", 1).Alias("s"); try { cmdLine.Parse(); } catch (Exception ex) { App.ErrorMessage("Command line error.", ex, "Parsing command line"); Application.Current.Shutdown(); } List<string> filesToLoad = new List<string>(); bool error = false; foreach (string fileNameArg in cmdLine.FreeArguments) { if (!string.IsNullOrWhiteSpace(fileNameArg)) { // File name if (File.Exists(fileNameArg)) { // File exists, open it string fileName = fileNameArg; if (!Path.IsPathRooted(fileName)) { fileName = Path.GetFullPath(fileName); } filesToLoad.Add(fileName); } else if (Directory.Exists(fileNameArg)) { // Directory specified, collect all files foreach (string fileName in Directory.GetFiles(fileNameArg, "*.txd")) { filesToLoad.Add(fileName); } if (filesToLoad.Count == 0) { // Nothing found, try older XML file names foreach (string fileName in Directory.GetFiles(fileNameArg, "*.xml")) { if (FileNameHelper.GetCulture(fileName) != null) { filesToLoad.Add(fileName); } } } } else { FL.Error("File/directory not found", fileNameArg); error = true; } } } if (error) { App.ErrorMessage("At least one of the files or directories specified at the command line could not be found."); } // Scan for other files near the selected files // (Currently only active if a single file is specified) //if (filesToLoad.Count == 1) //{ // foreach (string fileName in filesToLoad.Distinct().ToArray()) // { // if (fileName.ToLowerInvariant().EndsWith(".txd") && File.Exists(fileName)) // { // // Existing .txd file // // Scan same directory for other .txd files // string[] otherFiles = Directory.GetFiles(Path.GetDirectoryName(fileName), "*.txd"); // // otherFiles should contain fileName and may contain additional files // if (otherFiles.Length > 1) // { // if (App.YesNoQuestion("Other Tx dictionary files are located in the same directory as the selected file. Should they also be loaded?")) // { // // Duplicates will be removed later // filesToLoad.AddRange(otherFiles); // } // } // } // } //} // NOTE: Loading multiple txd files is not supported. (Only scan for more cultures of version 1 files. - Done) if (!FileNameHelper.FindOtherCultures(filesToLoad)) Application.Current.Shutdown(); // Create main window and view model var view = new MainWindow(); var viewModel = new MainViewModel(); if (filesToLoad.Count == 0 && scanOption.IsSet) { viewModel.ScanDirectory = scanOption.Value; } view.DataContext = viewModel; // Load selected files if (filesToLoad.Count > 0) { viewModel.LoadFiles(filesToLoad); } // Show the main window view.Show(); }
/// <summary> /// Wrapped main program, uses <see cref="ConsoleException"/> as return code in case of /// error and does not wait at the end. /// </summary> private static void MainWrapper() { CommandLineHelper cmdLine = new CommandLineHelper(); var showHelpOption = cmdLine.RegisterOption("help").Alias("h", "?"); var showVersionOption = cmdLine.RegisterOption("version").Alias("ver"); var debugOption = cmdLine.RegisterOption("debug"); var patchAssemblyInfoOption = cmdLine.RegisterOption("patch"); var restorePatchedFilesOption = cmdLine.RegisterOption("restore"); var simpleAttributeOption = cmdLine.RegisterOption("simple"); var informationalAttributeOption = cmdLine.RegisterOption("info"); var allAttributesOption = cmdLine.RegisterOption("all"); var formatOption = cmdLine.RegisterOption("format", 1); var revisionOnlyOption = cmdLine.RegisterOption("revonly"); var requireVcsOption = cmdLine.RegisterOption("require", 1); var rejectModifiedOption = cmdLine.RegisterOption("rejectmod").Alias("rejectmodified"); var rejectMixedOption = cmdLine.RegisterOption("rejectmix").Alias("rejectmixed"); var multiProjectOption = cmdLine.RegisterOption("multi"); var scanRootOption = cmdLine.RegisterOption("root"); var decodeRevisionOption = cmdLine.RegisterOption("decode", 1); var predictRevisionsOption = cmdLine.RegisterOption("predict"); try { //cmdLine.ReadArgs(Environment.CommandLine, true); // Alternative split method, should have the same result cmdLine.Parse(); showDebugOutput = debugOption.IsSet; if (showDebugOutput) { ShowDebugMessage( "Command line: " + Environment.GetCommandLineArgs() .Select(s => "[" + s + "]") .Aggregate((a, b) => a + " " + b)); } } catch (Exception ex) { throw new ConsoleException(ex.Message, ExitCodes.CmdLineError); } // Handle simple text output options if (showHelpOption.IsSet) { ShowHelp(); return; } if (showVersionOption.IsSet) { ShowVersion(); return; } // Check for environment variable from PowerShell build framework. // If psbuild has set this variable, it is using NetRevisionTool itself in multi-project // mode and pre/postbuild actions in individual projects should not do anything on their // own. if (!string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("SuppressNetRevisionTool"))) { ShowDebugMessage("SuppressNetRevisionTool environment variable is set. Quitting…"); return; } // Find all directories string path = GetWorkPath(cmdLine); string[] projectDirs = null; if (multiProjectOption.IsSet) { // Read solution file and collect all projects projectDirs = GetProjectsFromSolution(path); // From now on, work with the solution directory as default path to get the revision of if (Path.GetExtension(path).ToLowerInvariant() == ".sln") { path = Path.GetDirectoryName(path); } } else { if (!Directory.Exists(path)) throw new ConsoleException("The specified project directory does not exist.", ExitCodes.FileNotFound); projectDirs = new[] { path }; } // Restoring doesn't need more info, do it now if (restorePatchedFilesOption.IsSet) { // Restore AssemblyInfo file(s) foreach (string projectDir in projectDirs) { var aih = new AssemblyInfoHelper(projectDir, true); aih.RestoreFile(); } return; } // Analyse working directory RevisionData data = ProcessDirectory(path, scanRootOption.IsSet, requireVcsOption.Value); data.Normalize(); // Check for required VCS if (requireVcsOption.IsSet) { if (data.VcsProvider == null || !data.VcsProvider.Name.Equals(requireVcsOption.Value, StringComparison.OrdinalIgnoreCase)) { throw new ConsoleException("Required VCS \"" + requireVcsOption.Value + "\" not present.", ExitCodes.RequiredVcs); } } // Check for reject modifications/mixed revisions if (rejectModifiedOption.IsSet && data.IsModified) { throw new ConsoleException("The working directory contains uncommitted modifications.", ExitCodes.RejectModified); } if (rejectMixedOption.IsSet && data.IsMixed) { throw new ConsoleException("The working directory contains mixed revisions.", ExitCodes.RejectMixed); } // Determine revision ID format, in case we need one here string format = null; if (formatOption.IsSet && !string.IsNullOrWhiteSpace(formatOption.Value)) { // Take from command-line option format = formatOption.Value; ShowDebugMessage("Format specified: " + format); } else { // None or empty specified. Search in AssemblyInfo file(s) in the project(s) ShowDebugMessage("No format specified, searching AssemblyInfo source file."); AssemblyInfoHelper aih = null; foreach (string projectDir in projectDirs) { aih = new AssemblyInfoHelper(projectDir, false); if (aih.FileExists) { format = aih.GetRevisionFormat(); if (format != null) { if (projectDirs.Length > 1) { ShowDebugMessage("Found format in project \"" + projectDir + "\"."); } break; } } else { ShowDebugMessage(" AssemblyInfo source file not found.", 2); } } if (format != null) { ShowDebugMessage("Found format: " + format); } } if (format == null) { if (data.RevisionNumber > 0) { ShowDebugMessage("No format available, using default format for revision number."); format = "{revnum}"; } else if (!string.IsNullOrEmpty(data.CommitHash) && !Regex.IsMatch(data.CommitHash, "^0+$")) { ShowDebugMessage("No format available, using default format for commit hash."); format = "{chash:8}"; } else { ShowDebugMessage("No format available, using empty format."); format = ""; } } if (decodeRevisionOption.IsSet) { // Decode specified revision ID RevisionFormat.ShowDecode(format, decodeRevisionOption.Value); } else if (predictRevisionsOption.IsSet) { // Predict next revision IDs RevisionFormat.PredictValue(format); } else if (patchAssemblyInfoOption.IsSet) { // Patch AssemblyInfo file(s) bool noAttrSet = !simpleAttributeOption.IsSet && !informationalAttributeOption.IsSet; bool simpleAttributes = simpleAttributeOption.IsSet || noAttrSet; bool informationalAttribute = informationalAttributeOption.IsSet || noAttrSet; foreach (string projectDir in projectDirs) { var aih = new AssemblyInfoHelper(projectDir, true); aih.PatchFile(format, data, simpleAttributes, informationalAttribute, revisionOnlyOption.IsSet); } } else { // Just display revision ID var rf = new RevisionFormat(); rf.RevisionData = data; Console.WriteLine(rf.Resolve(format)); } }
/// <summary> /// Wrapped main program, uses <see cref="ConsoleException"/> as return code in case of /// error and does not wait at the end. /// </summary> private static void MainWrapper() { CommandLineHelper cmdLine = new CommandLineHelper(); var showHelpOption = cmdLine.RegisterOption("help").Alias("h", "?"); var showVersionOption = cmdLine.RegisterOption("version").Alias("ver"); var debugOption = cmdLine.RegisterOption("debug"); var utf8Option = cmdLine.RegisterOption("utf8"); var utf16Option = cmdLine.RegisterOption("utf16"); var utf8NoBomOption = cmdLine.RegisterOption("utf8nobom"); var defaultEncodingOption = cmdLine.RegisterOption("defaultenc"); try { //cmdLine.ReadArgs(Environment.CommandLine, true); // Alternative split method, should have the same result cmdLine.Parse(); showDebugOutput = debugOption.IsSet; if (showDebugOutput) { ShowDebugMessage( "Command line: " + Environment.GetCommandLineArgs() .Select(s => "[" + s + "]") .Aggregate((a, b) => a + " " + b)); } } catch (Exception ex) { throw new ConsoleException(ex.Message, ExitCodes.CmdLineError); } // Handle simple text output options if (showHelpOption.IsSet) { ShowHelp(); return; } if (showVersionOption.IsSet) { ShowVersion(); return; } if (cmdLine.FreeArguments.Length < 2) { throw new ConsoleException("Too few arguments.", ExitCodes.CmdLineError); } // Prepare arguments string fileName = cmdLine.FreeArguments[0]; string targetName = cmdLine.FreeArguments[1]; Encoding encoding = null; if (utf8Option.IsSet) encoding = Encoding.UTF8; if (utf16Option.IsSet) encoding = Encoding.Unicode; if (utf8NoBomOption.IsSet) encoding = new UTF8Encoding(false); if (defaultEncodingOption.IsSet) encoding = Encoding.Default; Dictionary<string, string> data = new Dictionary<string, string>(); for (int i = 2; i < cmdLine.FreeArguments.Length; i++) { string arg = cmdLine.FreeArguments[i]; string[] parts = arg.Split(new[] { '=' }, 2); if (parts.Length < 2) { throw new ConsoleException("Invalid name value pair specification in argument " + (i + 1) + ".", ExitCodes.CmdLineError); } if (data.ContainsKey(parts[0])) { throw new ConsoleException("Duplicate name value pair specification in argument " + (i + 1) + ".", ExitCodes.CmdLineError); } data[parts[0]] = parts[1]; } // Replace data in file ReplaceHelper rh = new ReplaceHelper(fileName, encoding); rh.ReplaceData(targetName, data); }
/// <summary> /// Gets the work path from the command line or the current directory. /// </summary> /// <param name="cmdLine">Command line.</param> /// <returns>The work path.</returns> private static string GetWorkPath(CommandLineHelper cmdLine) { string path = Environment.CurrentDirectory; if (cmdLine.FreeArguments.Length > 0) { // Trim quotes, they can appear for mysterious reasons from VS/MSBuild path = cmdLine.FreeArguments[0].Trim(' ', '"'); if (!Path.IsPathRooted(path)) { path = Path.GetFullPath(path); } // Remove all trailing directory separators to make it safer path = path.TrimEnd('/', '\\'); } else { ShowDebugMessage("No path specified, using current directory."); } ShowDebugMessage("Input directory: " + path); return path; }