/// <summary> /// Fills the provided CommandLineBuilderExtension with all the command line options used when /// executing this tool that must go on the command line /// </summary> /// <comments> /// Has to be command line commands because ResGen 3.5 and earlier don't know about /// response files. /// </comments> /// <param name="commandLine">Gets filled with command line options</param> protected internal override void AddCommandLineCommands(CommandLineBuilderExtension commandLine) { ErrorUtilities.VerifyThrow(!ResGen.IsNullOrEmpty(InputFiles), "If InputFiles is empty, the task should have returned before reaching this point"); CommandLineBuilderExtension resGenArguments = new CommandLineBuilderExtension(); GenerateResGenCommands(resGenArguments, false /* don't line-delimit arguments; spaces are just fine */); string pathToResGen = GenerateResGenFullPath(); if ( pathToResGen != null && !pathToResGen.Equals(NativeMethodsShared.GetLongFilePath(ToolLocationHelper.GetPathToDotNetFrameworkSdkFile("resgen.exe", TargetDotNetFrameworkVersion.Version35)), StringComparison.OrdinalIgnoreCase) && String.IsNullOrEmpty(StronglyTypedLanguage) ) { // 4.0 resgen.exe does support response files (at least as long as you're not building an STR), so we can // make use of them here by returning nothing! } else { // otherwise, the toolname is ResGen.exe and we just need the resgen arguments in CommandLineCommands. commandLine.AppendTextUnquoted(resGenArguments.ToString()); } }
/// <summary> /// Validates the parameters passed to the task /// </summary> /// <returns>True if parameters are valid</returns> protected override bool ValidateParameters() { ErrorUtilities.VerifyThrow(!ResGen.IsNullOrEmpty(InputFiles), "If InputFiles is empty, the task should have returned before reaching this point"); // make sure that if the output resources were set, they exactly match the number of input sources if (!ResGen.IsNullOrEmpty(OutputFiles) && (OutputFiles.Length != InputFiles.Length)) { Log.LogErrorWithCodeFromResources("General.TwoVectorsMustHaveSameLength", InputFiles.Length, OutputFiles.Length, "InputFiles", "OutputFiles"); return(false); } // Creating an STR is triggered merely by setting the language if (!String.IsNullOrEmpty(StronglyTypedLanguage)) { // Only a single Sources is allowed if you are generating STR. // Otherwise, each STR class overwrites the previous one. In theory we could generate separate // STR classes for each input, but then the class name and file name parameters would have to be vectors. if (InputFiles.Length != 1) { Log.LogErrorWithCodeFromResources("ResGen.STRLanguageButNotExactlyOneSourceFile"); return(false); } } else { if ( !String.IsNullOrEmpty(StronglyTypedClassName) || !String.IsNullOrEmpty(StronglyTypedNamespace) || !String.IsNullOrEmpty(StronglyTypedFileName) ) { // We have no language to generate a STR, but nevertheless the user passed us a class, // namespace, and/or filename. Let them know that they probably wanted to pass a language too. Log.LogErrorWithCodeFromResources("ResGen.STRClassNamespaceOrFilenameWithoutLanguage"); return(false); } } // Verify that the ToolPath exists -- if the tool doesn't exist in it // we'll worry about that later if ((String.IsNullOrEmpty(ToolPath) || !Directory.Exists(ToolPath)) && (String.IsNullOrEmpty(SdkToolsPath) || !Directory.Exists(SdkToolsPath))) { Log.LogErrorWithCodeFromResources("ResGen.SdkOrToolPathNotSpecifiedOrInvalid", SdkToolsPath ?? "", ToolPath ?? ""); return(false); } return(base.ValidateParameters()); }
/// <summary> /// If OutputFiles is null, we need to generate default output names /// to pass to resgen.exe (which would generate the names on its own, but /// then we wouldn't have access to them) /// </summary> private void GenerateOutputFileNames() { ErrorUtilities.VerifyThrow(!ResGen.IsNullOrEmpty(InputFiles), "If InputFiles is empty, the task should have returned before reaching this point"); ITaskItem[] inputFiles = InputFiles; ITaskItem[] outputFiles = new ITaskItem[inputFiles.Length]; // Set the default OutputFiles values for (int i = 0; i < inputFiles.Length; i++) { ITaskItem2 inputFileAsITaskItem2 = inputFiles[i] as ITaskItem2; if (inputFileAsITaskItem2 != null) { outputFiles[i] = new TaskItem(Path.ChangeExtension(inputFileAsITaskItem2.EvaluatedIncludeEscaped, ".resources")); } else { outputFiles[i] = new TaskItem(Path.ChangeExtension(EscapingUtilities.Escape(inputFiles[i].ItemSpec), ".resources")); } } Bag["OutputFiles"] = outputFiles; }
/// <summary> /// Generate the command line to be passed to resgen.exe, sans the path to the tool. /// </summary> private void GenerateResGenCommands(CommandLineBuilderExtension resGenArguments, bool useForResponseFile) { resGenArguments = resGenArguments ?? new CommandLineBuilderExtension(); if (ResGen.IsNullOrEmpty(OutputFiles)) { GenerateOutputFileNames(); } // Append boolean flags if requested string useSourcePathSwitch = "/useSourcePath" + (useForResponseFile ? "\n" : String.Empty); string publicClassSwitch = "/publicClass" + (useForResponseFile ? "\n" : String.Empty); resGenArguments.AppendWhenTrue(useSourcePathSwitch, Bag, "UseSourcePath"); resGenArguments.AppendWhenTrue(publicClassSwitch, Bag, "PublicClass"); // append the references, if any if (References != null) { foreach (ITaskItem reference in References) { // ResGen.exe response files frown on quotes in filenames, even if there are // spaces in the names of the files. if (useForResponseFile && reference != null) { resGenArguments.AppendTextUnquoted("/r:"); resGenArguments.AppendTextUnquoted(reference.ItemSpec); resGenArguments.AppendTextUnquoted("\n"); } else { resGenArguments.AppendSwitchIfNotNull("/r:", reference); } } } if (String.IsNullOrEmpty(StronglyTypedLanguage)) { // append the compile switch resGenArguments.AppendSwitch("/compile" + (useForResponseFile ? "\n" : String.Empty)); // append the resources to compile if (InputFiles != null && InputFiles.Length > 0) { ITaskItem[] inputFiles = InputFiles; ITaskItem[] outputFiles = OutputFiles; for (int i = 0; i < inputFiles.Length; ++i) { if (useForResponseFile) { // ResGen.exe response files frown on quotes in filenames, even if there are // spaces in the names of the files. if (inputFiles[i] != null && outputFiles[i] != null) { resGenArguments.AppendTextUnquoted(inputFiles[i].ItemSpec); resGenArguments.AppendTextUnquoted(","); resGenArguments.AppendTextUnquoted(outputFiles[i].ItemSpec); resGenArguments.AppendTextUnquoted("\n"); } } else { resGenArguments.AppendFileNamesIfNotNull ( new ITaskItem[] { inputFiles[i], outputFiles[i] }, "," ); } } } } else { // append the resource to compile resGenArguments.AppendFileNamesIfNotNull(InputFiles, " "); resGenArguments.AppendFileNamesIfNotNull(OutputFiles, " "); // append the strongly-typed resource details resGenArguments.AppendSwitchIfNotNull ( "/str:", new string[] { StronglyTypedLanguage, StronglyTypedNamespace, StronglyTypedClassName, StronglyTypedFileName }, "," ); } }
/// <summary> /// Invokes the ToolTask with the given parameters /// </summary> /// <returns>True if the task succeeded, false otherwise</returns> public override bool Execute() { // If there aren't any input resources, well, we've already succeeded! if (ResGen.IsNullOrEmpty(InputFiles)) { Log.LogMessageFromResources(MessageImportance.Low, "ResGen.NoInputFiles"); return(!Log.HasLoggedErrors); } if (ResGen.IsNullOrEmpty(OutputFiles)) { GenerateOutputFileNames(); } bool success = false; // if command line is too long, fail string commandLineCommands = GenerateCommandLineCommands(); // when comparing command line length, need to add one for leading space added between command arguments and tool name if (!string.IsNullOrEmpty(commandLineCommands) && (commandLineCommands.Length + 1) > s_maximumCommandLength) { Log.LogErrorWithCodeFromResources("ResGen.CommandTooLong", commandLineCommands.Length); success = false; } else { // Use ToolTaskExtension's Execute() success = base.Execute(); } if (String.IsNullOrEmpty(StronglyTypedLanguage)) { if (!success) { // One or more of the generated resources was not, in fact generated -- // only keep in OutputFiles the ones that actually exist. ITaskItem[] outputFiles = this.OutputFiles; List <ITaskItem> successfullyGenerated = new List <ITaskItem>(); for (int i = 0; i < outputFiles.Length; i++) { if (File.Exists(outputFiles[i].ItemSpec)) { successfullyGenerated.Add(outputFiles[i]); } } this.OutputFiles = successfullyGenerated.ToArray(); } } else { ITaskItem outputFile = OutputFiles[0]; // if the resource generation was unsuccessful, check to see that the resource file // was in fact generated if (!success) { if (!File.Exists(outputFile.ItemSpec)) { this.OutputFiles = new ITaskItem[0]; } } // Default the class name if we need to - regardless of whether the STR was successfully generated if (StronglyTypedClassName == null) { StronglyTypedClassName = Path.GetFileNameWithoutExtension(outputFile.ItemSpec); } // Default the filename if we need to - regardless of whether the STR was successfully generated if (StronglyTypedFileName == null) { CodeDomProvider provider = null; try { provider = CodeDomProvider.CreateProvider(StronglyTypedLanguage); } catch (System.Configuration.ConfigurationException) { // If the language can't be found, then ResGen.exe will already have // logged an appropriate error. return(false); } catch (System.Security.SecurityException) { // If the language can't be found, then ResGen.exe will already have // logged an appropriate error. return(false); } StronglyTypedFileName = ProcessResourceFiles.GenerateDefaultStronglyTypedFilename(provider, outputFile.ItemSpec); } } return(success && !Log.HasLoggedErrors); }
/// <summary> /// Factoring out the setting of the default parameters to the /// ResGen task. /// </summary> /// <param name="resGen"></param> private ResGen CreateResGenTaskWithDefaultParameters() { ResGen resGen = new ResGen(); resGen.BuildEngine = BuildEngine; resGen.SdkToolsPath = _resgenPath; resGen.PublicClass = PublicClass; resGen.References = References; resGen.UseSourcePath = UseSourcePath; resGen.EnvironmentVariables = EnvironmentVariables; return resGen; }