Migrate MsgGen
This commit is contained in:
Родитель
0358780c77
Коммит
4418bd52f1
|
@ -6,6 +6,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{00E50075-E89
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixBuildTools.XsdGen", "src\WixBuildTools.XsdGen\WixBuildTools.XsdGen.csproj", "{E89E52C9-A4A1-4174-A1B1-3B72975E6ED6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixBuildTools.MsgGen", "src\WixBuildTools.MsgGen\WixBuildTools.MsgGen.csproj", "{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -28,12 +30,25 @@ Global
|
|||
{E89E52C9-A4A1-4174-A1B1-3B72975E6ED6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E89E52C9-A4A1-4174-A1B1-3B72975E6ED6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E89E52C9-A4A1-4174-A1B1-3B72975E6ED6}.Release|x86.Build.0 = Release|Any CPU
|
||||
{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{E89E52C9-A4A1-4174-A1B1-3B72975E6ED6} = {00E50075-E896-42D1-AC30-2D2E7D129FB9}
|
||||
{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4} = {00E50075-E896-42D1-AC30-2D2E7D129FB9}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {83E9E075-B440-471A-9C37-9D84BA0AE3E0}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyCulture("")]
|
|
@ -0,0 +1,250 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
|
||||
|
||||
namespace WixBuildTools.MsgGen
|
||||
{
|
||||
using System;
|
||||
using System.CodeDom;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Xml;
|
||||
|
||||
/// <summary>
|
||||
/// Message files generation class.
|
||||
/// </summary>
|
||||
public class GenerateMessageFiles
|
||||
{
|
||||
/// <summary>
|
||||
/// Generate the message files.
|
||||
/// </summary>
|
||||
/// <param name="messagesDoc">Input Xml document containing message definitions.</param>
|
||||
/// <param name="codeCompileUnit">CodeDom container.</param>
|
||||
/// <param name="resourceWriter">Writer for default resource file.</param>
|
||||
public static void Generate(XmlDocument messagesDoc, CodeCompileUnit codeCompileUnit, ResourceWriter resourceWriter)
|
||||
{
|
||||
Hashtable usedNumbers = new Hashtable();
|
||||
|
||||
if (null == messagesDoc)
|
||||
{
|
||||
throw new ArgumentNullException("messagesDoc");
|
||||
}
|
||||
|
||||
if (null == codeCompileUnit)
|
||||
{
|
||||
throw new ArgumentNullException("codeCompileUnit");
|
||||
}
|
||||
|
||||
if (null == resourceWriter)
|
||||
{
|
||||
throw new ArgumentNullException("resourceWriter");
|
||||
}
|
||||
|
||||
string namespaceAttr = messagesDoc.DocumentElement.GetAttribute("Namespace");
|
||||
string resourcesAttr = messagesDoc.DocumentElement.GetAttribute("Resources");
|
||||
|
||||
// namespace
|
||||
CodeNamespace messagesNamespace = new CodeNamespace(namespaceAttr);
|
||||
codeCompileUnit.Namespaces.Add(messagesNamespace);
|
||||
|
||||
// imports
|
||||
messagesNamespace.Imports.Add(new CodeNamespaceImport("System"));
|
||||
messagesNamespace.Imports.Add(new CodeNamespaceImport("System.Reflection"));
|
||||
messagesNamespace.Imports.Add(new CodeNamespaceImport("System.Resources"));
|
||||
if (namespaceAttr != "WixToolset.Data")
|
||||
{
|
||||
messagesNamespace.Imports.Add(new CodeNamespaceImport("WixToolset.Data"));
|
||||
}
|
||||
|
||||
foreach (XmlElement classElement in messagesDoc.DocumentElement.ChildNodes)
|
||||
{
|
||||
string className = classElement.GetAttribute("Name");
|
||||
string baseContainerName = classElement.GetAttribute("BaseContainerName");
|
||||
string containerName = classElement.GetAttribute("ContainerName");
|
||||
string messageLevel = classElement.GetAttribute("Level");
|
||||
|
||||
// message container class
|
||||
messagesNamespace.Types.Add(CreateContainer(namespaceAttr, baseContainerName, containerName, messageLevel, resourcesAttr));
|
||||
|
||||
// class
|
||||
CodeTypeDeclaration messagesClass = new CodeTypeDeclaration(className);
|
||||
messagesClass.TypeAttributes = TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed;
|
||||
messagesNamespace.Types.Add(messagesClass);
|
||||
|
||||
// private constructor (needed since all methods in this class are static)
|
||||
CodeConstructor constructor = new CodeConstructor();
|
||||
constructor.Attributes = MemberAttributes.Private;
|
||||
constructor.ReturnType = null;
|
||||
messagesClass.Members.Add(constructor);
|
||||
|
||||
// messages
|
||||
foreach (XmlElement messageElement in classElement.ChildNodes)
|
||||
{
|
||||
int number;
|
||||
string id = messageElement.GetAttribute("Id");
|
||||
string numberString = messageElement.GetAttribute("Number");
|
||||
bool sourceLineNumbers = true;
|
||||
|
||||
// determine the message number (and ensure it was set properly)
|
||||
if (0 < numberString.Length)
|
||||
{
|
||||
number = Convert.ToInt32(numberString, CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ApplicationException(String.Format("Message number must be assigned for {0} '{1}'.", containerName, id));
|
||||
}
|
||||
|
||||
// check for message number collisions
|
||||
if (usedNumbers.Contains(number))
|
||||
{
|
||||
throw new ApplicationException(String.Format("Collision detected between two or more messages with number '{0}'.", number));
|
||||
}
|
||||
|
||||
usedNumbers.Add(number, null);
|
||||
|
||||
if ("no" == messageElement.GetAttribute("SourceLineNumbers"))
|
||||
{
|
||||
sourceLineNumbers = false;
|
||||
}
|
||||
|
||||
int instanceCount = 0;
|
||||
foreach (XmlElement instanceElement in messageElement.ChildNodes)
|
||||
{
|
||||
string formatString = instanceElement.InnerText.Trim();
|
||||
string resourceName = String.Concat(className, "_", id, "_", (++instanceCount).ToString());
|
||||
|
||||
// create a resource
|
||||
resourceWriter.AddResource(resourceName, formatString);
|
||||
|
||||
// create method
|
||||
CodeMemberMethod method = new CodeMemberMethod();
|
||||
method.ReturnType = new CodeTypeReference(baseContainerName);
|
||||
method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
|
||||
messagesClass.Members.Add(method);
|
||||
|
||||
// method name
|
||||
method.Name = id;
|
||||
|
||||
// return statement
|
||||
CodeMethodReturnStatement stmt = new CodeMethodReturnStatement();
|
||||
method.Statements.Add(stmt);
|
||||
|
||||
// return statement expression
|
||||
CodeObjectCreateExpression expr = new CodeObjectCreateExpression();
|
||||
stmt.Expression = expr;
|
||||
|
||||
// new struct
|
||||
expr.CreateType = new CodeTypeReference(containerName);
|
||||
|
||||
// optionally have sourceLineNumbers as the first parameter
|
||||
if (sourceLineNumbers)
|
||||
{
|
||||
// sourceLineNumbers parameter
|
||||
expr.Parameters.Add(new CodeArgumentReferenceExpression("sourceLineNumbers"));
|
||||
}
|
||||
else
|
||||
{
|
||||
expr.Parameters.Add(new CodePrimitiveExpression(null));
|
||||
}
|
||||
|
||||
// message number parameter
|
||||
expr.Parameters.Add(new CodePrimitiveExpression(number));
|
||||
|
||||
// resource name parameter
|
||||
expr.Parameters.Add(new CodePrimitiveExpression(resourceName));
|
||||
|
||||
// optionally have sourceLineNumbers as the first parameter
|
||||
if (sourceLineNumbers)
|
||||
{
|
||||
method.Parameters.Add(new CodeParameterDeclarationExpression("SourceLineNumber", "sourceLineNumbers"));
|
||||
}
|
||||
|
||||
foreach (XmlNode parameterNode in instanceElement.ChildNodes)
|
||||
{
|
||||
XmlElement parameterElement;
|
||||
|
||||
if (null != (parameterElement = parameterNode as XmlElement))
|
||||
{
|
||||
string type = parameterElement.GetAttribute("Type");
|
||||
string name = parameterElement.GetAttribute("Name");
|
||||
|
||||
// method parameter
|
||||
method.Parameters.Add(new CodeParameterDeclarationExpression(type, name));
|
||||
|
||||
// String.Format parameter
|
||||
expr.Parameters.Add(new CodeArgumentReferenceExpression(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create message container class.
|
||||
/// </summary>
|
||||
/// <param name="namespaceName">Namespace to use for resources stream.</param>
|
||||
/// <param name="baseContainerName">Name of the base message container class.</param>
|
||||
/// <param name="containerName">Name of the message container class.</param>
|
||||
/// <param name="messageLevel">Message level of for the message.</param>
|
||||
/// <param name="resourcesName">Name of the resources stream (will get namespace prepended).</param>
|
||||
/// <returns>Message container class CodeDom object.</returns>
|
||||
private static CodeTypeDeclaration CreateContainer(string namespaceName, string baseContainerName, string containerName, string messageLevel, string resourcesName)
|
||||
{
|
||||
CodeTypeDeclaration messageContainer = new CodeTypeDeclaration();
|
||||
|
||||
messageContainer.Name = containerName;
|
||||
messageContainer.BaseTypes.Add(new CodeTypeReference(baseContainerName));
|
||||
|
||||
// constructor
|
||||
CodeConstructor constructor = new CodeConstructor();
|
||||
constructor.Attributes = MemberAttributes.Public;
|
||||
constructor.ReturnType = null;
|
||||
messageContainer.Members.Add(constructor);
|
||||
|
||||
CodeMemberField resourceManager = new CodeMemberField();
|
||||
resourceManager.Attributes = MemberAttributes.Private | MemberAttributes.Static;
|
||||
resourceManager.Name = "resourceManager";
|
||||
resourceManager.Type = new CodeTypeReference("ResourceManager");
|
||||
resourceManager.InitExpression = new CodeObjectCreateExpression("ResourceManager", new CodeSnippetExpression(String.Format("\"{0}.{1}\"", namespaceName, resourcesName)), new CodeSnippetExpression("Assembly.GetExecutingAssembly()"));
|
||||
messageContainer.Members.Add(resourceManager);
|
||||
|
||||
// constructor parameters
|
||||
constructor.Parameters.Add(new CodeParameterDeclarationExpression("SourceLineNumber", "sourceLineNumbers"));
|
||||
constructor.Parameters.Add(new CodeParameterDeclarationExpression(typeof(int), "id"));
|
||||
constructor.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "resourceName"));
|
||||
CodeParameterDeclarationExpression messageArgsParam = new CodeParameterDeclarationExpression("params object[]", "messageArgs");
|
||||
constructor.Parameters.Add(messageArgsParam);
|
||||
|
||||
constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("sourceLineNumbers"));
|
||||
constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("id"));
|
||||
constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("resourceName"));
|
||||
constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("messageArgs"));
|
||||
|
||||
// assign base.Level if messageLevel is specified
|
||||
if (!String.IsNullOrEmpty(messageLevel))
|
||||
{
|
||||
CodePropertyReferenceExpression levelReference = new CodePropertyReferenceExpression(new CodeBaseReferenceExpression(), "Level");
|
||||
CodeFieldReferenceExpression messageLevelField = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("MessageLevel"), messageLevel);
|
||||
constructor.Statements.Add(new CodeAssignStatement(levelReference, messageLevelField));
|
||||
}
|
||||
|
||||
// Assign base.ResourceManager property
|
||||
CodePropertyReferenceExpression baseResourceManagerReference = new CodePropertyReferenceExpression(new CodeBaseReferenceExpression(), "ResourceManager");
|
||||
CodeFieldReferenceExpression resourceManagerField = new CodeFieldReferenceExpression(null, "resourceManager");
|
||||
constructor.Statements.Add(new CodeAssignStatement(baseResourceManagerReference, resourceManagerField));
|
||||
|
||||
//CodeMemberProperty resourceManagerProperty = new CodeMemberProperty();
|
||||
//resourceManagerProperty.Attributes = MemberAttributes.Public | MemberAttributes.Override;
|
||||
//resourceManagerProperty.Name = "ResourceManager";
|
||||
//resourceManagerProperty.Type = new CodeTypeReference("ResourceManager");
|
||||
//CodeFieldReferenceExpression resourceManagerReference = new CodeFieldReferenceExpression();
|
||||
//resourceManagerReference.FieldName = "resourceManager";
|
||||
//resourceManagerProperty.GetStatements.Add(new CodeMethodReturnStatement(resourceManagerReference));
|
||||
//messageContainer.Members.Add(resourceManagerProperty);
|
||||
|
||||
return messageContainer;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,261 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
|
||||
|
||||
namespace WixBuildTools.MsgGen
|
||||
{
|
||||
using Microsoft.CSharp;
|
||||
using System;
|
||||
using System.CodeDom;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
|
||||
/// <summary>
|
||||
/// The main entry point for MsgGen.
|
||||
/// </summary>
|
||||
public class MsgGen
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for MsgGen.
|
||||
/// </summary>
|
||||
/// <param name="args">Commandline arguments for the application.</param>
|
||||
/// <returns>Returns the application error code.</returns>
|
||||
[STAThread]
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
MsgGenMain msgGen = new MsgGenMain(args);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("MsgGen.exe : fatal error MSGG0000: {0}\r\n\r\nStack Trace:\r\n{1}", e.Message, e.StackTrace);
|
||||
if (e is NullReferenceException || e is SEHException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main class for MsgGen.
|
||||
/// </summary>
|
||||
private class MsgGenMain
|
||||
{
|
||||
private bool showLogo;
|
||||
private bool showHelp;
|
||||
|
||||
private string sourceFile;
|
||||
private string destClassFile;
|
||||
private string destResourcesFile;
|
||||
|
||||
/// <summary>
|
||||
/// Main method for the MsgGen application within the MsgGenMain class.
|
||||
/// </summary>
|
||||
/// <param name="args">Commandline arguments to the application.</param>
|
||||
public MsgGenMain(string[] args)
|
||||
{
|
||||
this.showLogo = true;
|
||||
this.showHelp = false;
|
||||
|
||||
this.sourceFile = null;
|
||||
this.destClassFile = null;
|
||||
this.destResourcesFile = null;
|
||||
|
||||
// parse the command line
|
||||
this.ParseCommandLine(args);
|
||||
|
||||
if (null == this.sourceFile || null == this.destClassFile)
|
||||
{
|
||||
this.showHelp = true;
|
||||
}
|
||||
if (null == this.destResourcesFile)
|
||||
{
|
||||
this.destResourcesFile = Path.ChangeExtension(this.destClassFile, ".resources");
|
||||
}
|
||||
|
||||
// get the assemblies
|
||||
Assembly msgGenAssembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
if (this.showLogo)
|
||||
{
|
||||
Console.WriteLine("Microsoft (R) Message Generation Tool version {0}", msgGenAssembly.GetName().Version.ToString());
|
||||
Console.WriteLine("Copyright (C) Microsoft Corporation 2004. All rights reserved.");
|
||||
Console.WriteLine();
|
||||
}
|
||||
if (this.showHelp)
|
||||
{
|
||||
Console.WriteLine(" usage: MsgGen.exe [-?] [-nologo] sourceFile destClassFile [destResourcesFile]");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(" -? this help information");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("For more information see: http://wix.sourceforge.net");
|
||||
return; // exit
|
||||
}
|
||||
|
||||
// load the schema
|
||||
XmlReader reader = null;
|
||||
XmlSchemaCollection schemaCollection = null;
|
||||
try
|
||||
{
|
||||
reader = new XmlTextReader(msgGenAssembly.GetManifestResourceStream("WixBuildTools.MsgGen.Xsd.messages.xsd"));
|
||||
schemaCollection = new XmlSchemaCollection();
|
||||
schemaCollection.Add("http://schemas.microsoft.com/genmsgs/2004/07/messages", reader);
|
||||
}
|
||||
finally
|
||||
{
|
||||
reader.Close();
|
||||
}
|
||||
|
||||
// load the source file and process it
|
||||
using (StreamReader sr = new StreamReader(this.sourceFile))
|
||||
{
|
||||
XmlParserContext context = new XmlParserContext(null, null, null, XmlSpace.None);
|
||||
XmlValidatingReader validatingReader = new XmlValidatingReader(sr.BaseStream, XmlNodeType.Document, context);
|
||||
validatingReader.Schemas.Add(schemaCollection);
|
||||
|
||||
XmlDocument errorsDoc = new XmlDocument();
|
||||
errorsDoc.Load(validatingReader);
|
||||
|
||||
CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
|
||||
|
||||
using (ResourceWriter resourceWriter = new ResourceWriter(this.destResourcesFile))
|
||||
{
|
||||
GenerateMessageFiles.Generate(errorsDoc, codeCompileUnit, resourceWriter);
|
||||
|
||||
GenerateCSharpCode(codeCompileUnit, this.destClassFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the actual C# code.
|
||||
/// </summary>
|
||||
/// <param name="codeCompileUnit">The code DOM.</param>
|
||||
/// <param name="destClassFile">Destination C# source file.</param>
|
||||
public static void GenerateCSharpCode(CodeCompileUnit codeCompileUnit, string destClassFile)
|
||||
{
|
||||
// generate the code with the C# code provider
|
||||
CSharpCodeProvider provider = new CSharpCodeProvider();
|
||||
|
||||
// obtain an ICodeGenerator from the CodeDomProvider class
|
||||
ICodeGenerator gen = provider.CreateGenerator();
|
||||
|
||||
// create a TextWriter to a StreamWriter to the output file
|
||||
using (StreamWriter sw = new StreamWriter(destClassFile))
|
||||
{
|
||||
using (IndentedTextWriter tw = new IndentedTextWriter(sw, " "))
|
||||
{
|
||||
CodeGeneratorOptions options = new CodeGeneratorOptions();
|
||||
|
||||
// code generation options
|
||||
options.BlankLinesBetweenMembers = true;
|
||||
options.BracingStyle = "C";
|
||||
|
||||
// generate source code using the code generator
|
||||
gen.GenerateCodeFromCompileUnit(codeCompileUnit, tw, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse the commandline arguments.
|
||||
/// </summary>
|
||||
/// <param name="args">Commandline arguments.</param>
|
||||
private void ParseCommandLine(string[] args)
|
||||
{
|
||||
for (int i = 0; i < args.Length; ++i)
|
||||
{
|
||||
string arg = args[i];
|
||||
if (null == arg || "" == arg) // skip blank arguments
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('-' == arg[0] || '/' == arg[0])
|
||||
{
|
||||
string parameter = arg.Substring(1);
|
||||
if ("nologo" == parameter)
|
||||
{
|
||||
this.showLogo = false;
|
||||
}
|
||||
else if ("?" == parameter || "help" == parameter)
|
||||
{
|
||||
this.showHelp = true;
|
||||
}
|
||||
}
|
||||
else if ('@' == arg[0])
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(arg.Substring(1)))
|
||||
{
|
||||
string line;
|
||||
ArrayList newArgs = new ArrayList();
|
||||
|
||||
while (null != (line = reader.ReadLine()))
|
||||
{
|
||||
string newArg = "";
|
||||
bool betweenQuotes = false;
|
||||
for (int j = 0; j < line.Length; ++j)
|
||||
{
|
||||
// skip whitespace
|
||||
if (!betweenQuotes && (' ' == line[j] || '\t' == line[j]))
|
||||
{
|
||||
if ("" != newArg)
|
||||
{
|
||||
newArgs.Add(newArg);
|
||||
newArg = null;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// if we're escaping a quote
|
||||
if ('\\' == line[j] && '"' == line[j])
|
||||
{
|
||||
++j;
|
||||
}
|
||||
else if ('"' == line[j]) // if we've hit a new quote
|
||||
{
|
||||
betweenQuotes = !betweenQuotes;
|
||||
continue;
|
||||
}
|
||||
|
||||
newArg = String.Concat(newArg, line[j]);
|
||||
}
|
||||
if ("" != newArg)
|
||||
{
|
||||
newArgs.Add(newArg);
|
||||
}
|
||||
}
|
||||
string[] ar = (string[])newArgs.ToArray(typeof(string));
|
||||
this.ParseCommandLine(ar);
|
||||
}
|
||||
}
|
||||
else if (null == this.sourceFile)
|
||||
{
|
||||
this.sourceFile = arg;
|
||||
}
|
||||
else if (null == this.destClassFile)
|
||||
{
|
||||
this.destClassFile = arg;
|
||||
}
|
||||
else if (null == this.destResourcesFile)
|
||||
{
|
||||
this.destResourcesFile = arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(String.Format("Unknown argument '{0}'.", arg));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net461</TargetFramework>
|
||||
<IsTool>true</IsTool>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="build\WixBuildTools.MsgGen.targets" PackagePath="build\" />
|
||||
<Content Include="buildCrossTargeting\WixBuildTools.MsgGen.targets" PackagePath="buildCrossTargeting\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Xsd\messages.xsd" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Nerdbank.GitVersioning" Version="2.0.37-beta" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
|
||||
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="http://schemas.microsoft.com/genmsgs/2004/07/messages"
|
||||
xmlns="http://schemas.microsoft.com/genmsgs/2004/07/messages">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
Schema for describing any kind of messages.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
|
||||
<xs:element name="Messages">
|
||||
<xs:complexType>
|
||||
<xs:sequence maxOccurs="unbounded">
|
||||
<xs:element ref="Class"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Namespace" type="xs:string" use="required">
|
||||
<xs:annotation><xs:documentation>Namespace of the generated class.</xs:documentation></xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="Resources" type="xs:string" use="required">
|
||||
<xs:annotation><xs:documentation>Resources stream for messages. Will get namespace prepended to it.</xs:documentation></xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<xs:element name="Class">
|
||||
<xs:complexType>
|
||||
<xs:sequence minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element ref="Message"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Name" type="xs:string" use="required">
|
||||
<xs:annotation><xs:documentation>Name of the generated class.</xs:documentation></xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="ContainerName" type="xs:string" use="required">
|
||||
<xs:annotation><xs:documentation>Name of the generated container class.</xs:documentation></xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="BaseContainerName" type="xs:string" use="required">
|
||||
<xs:annotation><xs:documentation>Name of the base container class.</xs:documentation></xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="Level" type="MessageLevelType">
|
||||
<xs:annotation><xs:documentation>Optional message level for this container class and derivative classes.</xs:documentation></xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<xs:element name="Message">
|
||||
<xs:complexType>
|
||||
<xs:sequence maxOccurs="unbounded">
|
||||
<xs:element ref="Instance"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Id" type="xs:string" use="required">
|
||||
<xs:annotation><xs:documentation>Name of the message type.</xs:documentation></xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="Number" type="xs:integer" use="required">
|
||||
<xs:annotation><xs:documentation>Override the number for this message type.</xs:documentation></xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="SourceLineNumbers" type="YesNoType">
|
||||
<xs:annotation><xs:documentation>Associate SourceLineNumbers with this message. The default value is "yes".</xs:documentation></xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<xs:element name="Instance">
|
||||
<xs:complexType mixed="true">
|
||||
<xs:sequence minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element ref="Parameter"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<xs:element name="Parameter">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="Type" type="xs:string" use="required">
|
||||
<xs:annotation><xs:documentation>Type of the parameter.</xs:documentation></xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="Name" type="xs:string" use="required">
|
||||
<xs:annotation><xs:documentation>Name of the parameter.</xs:documentation></xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<xs:simpleType name="YesNoType">
|
||||
<xs:annotation><xs:documentation>Values of this type will either be "yes" or "no".</xs:documentation></xs:annotation>
|
||||
<xs:restriction base="xs:NMTOKEN">
|
||||
<xs:enumeration value="no"/>
|
||||
<xs:enumeration value="yes"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="MessageLevelType">
|
||||
<xs:annotation><xs:documentation>The message level for this message which corresponds to the WixToolset.MessageLevel enumeration.</xs:documentation></xs:annotation>
|
||||
<xs:restriction base="xs:NMTOKEN">
|
||||
<xs:enumeration value="Verbose"/>
|
||||
<xs:enumeration value="Information"/>
|
||||
<xs:enumeration value="Warning"/>
|
||||
<xs:enumeration value="Error"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:schema>
|
|
@ -0,0 +1,102 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
|
||||
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!--Provide support for setting type (BuildAction) from VS-->
|
||||
<AvailableItemName Include="MsgGenSource" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<MsgGenPath Condition=" '$(MsgGenPath)'=='' ">$(MSBuildThisFileDirectory)..\tools\</MsgGenPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
================================================================================================
|
||||
MsgGen
|
||||
|
||||
Generates a .cs class file and a .resx file from an XML file.
|
||||
|
||||
[IN]
|
||||
@(MsgGenSource) - The items to run through the MsgGen tool.
|
||||
|
||||
[OUT]
|
||||
$(IntermediateOutputPath)%(Filename).cs - The generated .cs files to include in the compilation.
|
||||
$(IntermediateOutputPath)%(MsgGenSource.ResourcesLogicalName) - The generated .resources file to embed in the assembly.
|
||||
================================================================================================
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<MsgGenDependsOn>
|
||||
PrepareMsgGen
|
||||
</MsgGenDependsOn>
|
||||
<PrepareResourcesDependsOn>
|
||||
MsgGen;
|
||||
$(PrepareResourcesDependsOn)
|
||||
</PrepareResourcesDependsOn>
|
||||
</PropertyGroup>
|
||||
<Target
|
||||
Name="MsgGen"
|
||||
BeforeTargets="PrepareResources"
|
||||
DependsOnTargets="$(MsgGenDependsOn)"
|
||||
Condition=" '@(MsgGenSource)' != '' "
|
||||
Inputs="@(MsgGenSource)"
|
||||
Outputs="$(IntermediateOutputPath)%(MsgGenSource.Filename).cs;
|
||||
$(IntermediateOutputPath)%(MsgGenSource.ResourcesLogicalName)">
|
||||
|
||||
<Exec Command=""$(MsgGenPath)WixBuildTools.MsgGen.exe" -nologo "%(MsgGenSource.FullPath)" "$(MsgGenCsFile)" "$(MsgGenResourcesFile)""
|
||||
Outputs="$(MsgGenCsFile);$(MsgGenResourcesFile)" />
|
||||
|
||||
<ItemGroup>
|
||||
<!-- This will tell MSBuild to clean up the .cs and .resources file during a Clean build -->
|
||||
<FileWrites Include="$(MsgGenCsFile);$(MsgGenResourcesFile)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
================================================================================================
|
||||
PrepareMsgGen
|
||||
|
||||
Creates properties and Include items for MsgGen. This must be separate from the MsgGen target
|
||||
to workaround an MSBuild bug: AdditionalMetadata is ignored when the target is up-to-date.
|
||||
|
||||
================================================================================================
|
||||
-->
|
||||
<Target
|
||||
Name="PrepareMsgGen"
|
||||
Condition=" '@(MsgGenSource)' != '' ">
|
||||
|
||||
<CreateProperty Value="$(IntermediateOutputPath)%(MsgGenSource.Filename).cs">
|
||||
<Output TaskParameter="Value" PropertyName="MsgGenCsFile" />
|
||||
</CreateProperty>
|
||||
|
||||
<CreateProperty
|
||||
Value="$(IntermediateOutputPath)%(MsgGenSource.ResourcesLogicalName)"
|
||||
Condition=" '%(MsgGenSource.ResourcesLogicalName)' != '' ">
|
||||
|
||||
<Output TaskParameter="Value" PropertyName="MsgGenResourcesFile" />
|
||||
</CreateProperty>
|
||||
|
||||
<!-- Add the generated .cs file to the list of source files to compile -->
|
||||
<CreateItem
|
||||
Include="$(MsgGenCsFile)"
|
||||
AdditionalMetadata="Link=%(MsgGenCsFile.Filename)%(MsgGenCsFile.Extension)">
|
||||
|
||||
<Output TaskParameter="Include" ItemName="Compile" />
|
||||
</CreateItem>
|
||||
|
||||
<!-- Add the generated .resources file to the list of resources to embed -->
|
||||
<CreateItem
|
||||
Include="$(MsgGenResourcesFile)"
|
||||
AdditionalMetadata="Link=%(MsgGenResourcesFile.Filename)%(MsgGenResourcesFile.Extension);
|
||||
LogicalName=%(MsgGenSource.ResourcesLogicalName)"
|
||||
Condition=" '$(MsgGenResourcesFile)' != '' ">
|
||||
|
||||
<Output TaskParameter="Include" ItemName="EmbeddedResource" />
|
||||
</CreateItem>
|
||||
</Target>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
|
||||
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<Import Project="..\build\WixBuildTools.MsgGen.targets" />
|
||||
</Project>
|
Загрузка…
Ссылка в новой задаче