public bool Initialize (string taskName, IDictionary<string, string> factoryIdentityParameters, IDictionary<string, TaskPropertyInfo> parameterGroup, string taskBody, IBuildEngine taskFactoryLoggingHost) { task_name = taskName; if (parameterGroup != null) parameter_group = new Dictionary<string, TaskPropertyInfo> (parameterGroup); List<string> references = new List<string> (); List<string> namespace_uses = new List<string> (); namespace_uses.Add ("Microsoft.Build.Framework"); string type = null, language = null, code = null; var xml = XmlReader.Create (new StringReader (taskBody), new XmlReaderSettings () { ConformanceLevel = ConformanceLevel.Fragment }); for (xml.MoveToContent (); !xml.EOF; xml.MoveToContent ()) { switch (xml.NodeType) { case XmlNodeType.Element: switch (xml.LocalName) { case "Reference": references.Add (xml.GetAttribute ("Include")); xml.Skip (); break; case "Using": namespace_uses.Add (xml.GetAttribute ("Namespace")); xml.Skip (); break; case "Code": // MSB3757: Multiple Code elements have been found, this is not allowed. if (code != null) throw new InvalidProjectFileException (null, "Multiple Code elements are not allowed", "MSB", "3757", null); type = xml.GetAttribute ("Type"); language = xml.GetAttribute ("Language"); code = xml.ReadElementContentAsString (); break; } break; default: xml.Skip (); break; } } if (language == "vb") throw new NotImplementedException (string.Format ("{0} is not supported language for inline task", language)); if (language != "cs") throw new InvalidProjectFileException (null, string.Format ("{0} is not supported language for inline task", language), "MSB", "4175", null); string gen = null; // The documentation says "ITask", but the very first example shows "Log" which is not in ITask! It is likely that the generated code uses Task or TaskExtension. string classTemplate = @"public class " + taskName + " : Microsoft.Build.Utilities.Task { @@EXECUTE@@ }"; foreach (var ns in namespace_uses) gen += "using " + ns + ";\n"; switch (type) { case "Class": gen += code; break; case "Method": gen += classTemplate.Replace ("@@EXECUTE@@", code); break; case "Fragment": gen += classTemplate.Replace ("@@EXECUTE@@", "public override bool Execute () { " + code + " return true; }"); break; } var cscParams = new CompilerParameters (); cscParams.ReferencedAssemblies.Add ("Microsoft.Build.Framework.dll"); cscParams.ReferencedAssemblies.Add ("Microsoft.Build.Utilities.v4.0.dll"); // since we use Task, it depends on this dll. var results = new CSharpCodeProvider ().CompileAssemblyFromSource (cscParams, gen); var errors = new CompilerError [results.Errors.Count]; results.Errors.CopyTo (errors, 0); if (errors.Any (e => !e.IsWarning)) { string msg = string.Format ("Invalid '{0}' source code of '{1}' type: {2}", language, type, string.Join (" ", errors.Where (e => !e.IsWarning).Select (e => e.ToString ()))); throw new InvalidProjectFileException (null, msg, "MSB", "3758", null); } assembly = results.CompiledAssembly; return true; }
bool Initialize(string taskName, IDictionary <string, string> factoryIdentityParameters, IDictionary <string, TaskPropertyInfo> parameterGroup, string taskBody, IBuildEngine taskFactoryLoggingHost) { task_name = taskName; if (parameterGroup != null) { parameter_group = new Dictionary <string, TaskPropertyInfo> (parameterGroup); } List <string> references = new List <string> (); List <string> namespace_uses = new List <string> (); namespace_uses.Add("Microsoft.Build.Framework"); string type = null, language = null, code = null; var xml = XmlReader.Create(new StringReader(taskBody), new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Fragment }); for (xml.MoveToContent(); !xml.EOF; xml.MoveToContent()) { switch (xml.NodeType) { case XmlNodeType.Element: switch (xml.LocalName) { case "Reference": references.Add(xml.GetAttribute("Include")); xml.Skip(); break; case "Using": namespace_uses.Add(xml.GetAttribute("Namespace")); xml.Skip(); break; case "Code": // MSB3757: Multiple Code elements have been found, this is not allowed. if (code != null) { throw new InvalidProjectFileException(null, "Multiple Code elements are not allowed", "MSB", "3757", null); } type = xml.GetAttribute("Type"); language = xml.GetAttribute("Language"); code = xml.ReadElementContentAsString(); break; } break; default: xml.Skip(); break; } } if (language != "cs" && language != "vb") { throw new InvalidProjectFileException(null, string.Format("{0} is not supported language for inline task", language), "MSB", "4175", null); } CodeCompileUnit ccu; if (type == "Class") // 'code' contains the whole class that implements the task { ccu = new CodeSnippetCompileUnit(code); } else // 'code' contains parts of the class that implements the task { ccu = new CodeCompileUnit(); var nsp = new CodeNamespace(); nsp.Imports.AddRange(namespace_uses.Select(x => new CodeNamespaceImport(x)).ToArray()); ccu.Namespaces.Add(nsp); var taskClass = new CodeTypeDeclaration { IsClass = true, Name = taskName, TypeAttributes = TypeAttributes.Public }; var parameters = new List <CodeMemberProperty> (); var parametersBackingFields = new List <CodeMemberField> (); // add a public property + backing field for each parameter foreach (var param in parameter_group) { var prop = new CodeMemberProperty { Attributes = MemberAttributes.Public | MemberAttributes.Final, Name = param.Value.Name, Type = new CodeTypeReference(param.Value.PropertyType) }; var propBf = new CodeMemberField { Attributes = MemberAttributes.Private, Name = "_" + prop.Name, Type = prop.Type }; // add getter and setter to the property prop.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), propBf.Name))); prop.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), propBf.Name), new CodePropertySetValueReferenceExpression())); parameters.Add(prop); parametersBackingFields.Add(propBf); } taskClass.Members.AddRange(parameters.ToArray()); taskClass.Members.AddRange(parametersBackingFields.ToArray()); taskClass.BaseTypes.Add("Microsoft.Build.Utilities.Task"); // The documentation says "ITask", but the very first example shows "Log" which is not in ITask! It is likely that the generated code uses Task or TaskExtension. if (type == "Method") // 'code' contains the 'Execute' method directly { taskClass.Members.Add(new CodeSnippetTypeMember(code)); } else if (type == "Fragment") // 'code' contains the body of the 'Execute' method { var method = new CodeMemberMethod { Attributes = MemberAttributes.Public | MemberAttributes.Override, Name = "Execute", ReturnType = new CodeTypeReference(typeof(bool)) }; // add the code and a 'return true' at the end of the method method.Statements.Add(new CodeSnippetStatement(code)); method.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(true))); taskClass.Members.Add(method); } else { throw new ArgumentException("Invalid type: " + type); } nsp.Types.Add(taskClass); } var cscParams = new CompilerParameters(); cscParams.ReferencedAssemblies.Add("Microsoft.Build.Framework.dll"); cscParams.ReferencedAssemblies.Add("Microsoft.Build.Utilities.v4.0.dll"); // since we use Task, it depends on this dll. cscParams.ReferencedAssemblies.AddRange(GetReferences(references, taskFactoryLoggingHost)); cscParams.GenerateInMemory = true; var results = CodeDomProvider.CreateProvider(language).CompileAssemblyFromDom(cscParams, ccu); var errors = new CompilerError [results.Errors.Count]; results.Errors.CopyTo(errors, 0); if (errors.Any(e => !e.IsWarning)) { string msg = string.Format("Invalid '{0}' source code of '{1}' type: {2}", language, type, string.Join(" ", errors.Where(e => !e.IsWarning).Select(e => e.ToString()))); throw new InvalidProjectFileException(null, msg, "MSB", "3758", null); } assembly = results.CompiledAssembly; return(true); }
bool Initialize (string taskName, IDictionary<string, string> factoryIdentityParameters, IDictionary<string, TaskPropertyInfo> parameterGroup, string taskBody, IBuildEngine taskFactoryLoggingHost) { task_name = taskName; if (parameterGroup != null) parameter_group = new Dictionary<string, TaskPropertyInfo> (parameterGroup); List<string> references = new List<string> (); List<string> namespace_uses = new List<string> (); namespace_uses.Add ("Microsoft.Build.Framework"); string type = null, language = null, code = null; var xml = XmlReader.Create (new StringReader (taskBody), new XmlReaderSettings () { ConformanceLevel = ConformanceLevel.Fragment }); for (xml.MoveToContent (); !xml.EOF; xml.MoveToContent ()) { switch (xml.NodeType) { case XmlNodeType.Element: switch (xml.LocalName) { case "Reference": references.Add (xml.GetAttribute ("Include")); xml.Skip (); break; case "Using": namespace_uses.Add (xml.GetAttribute ("Namespace")); xml.Skip (); break; case "Code": // MSB3757: Multiple Code elements have been found, this is not allowed. if (code != null) throw new InvalidProjectFileException (null, "Multiple Code elements are not allowed", "MSB", "3757", null); type = xml.GetAttribute ("Type"); language = xml.GetAttribute ("Language"); code = xml.ReadElementContentAsString (); break; } break; default: xml.Skip (); break; } } if (language != "cs" && language != "vb") throw new InvalidProjectFileException (null, string.Format ("{0} is not supported language for inline task", language), "MSB", "4175", null); CodeCompileUnit ccu; if (type == "Class") { // 'code' contains the whole class that implements the task ccu = new CodeSnippetCompileUnit (code); } else { // 'code' contains parts of the class that implements the task ccu = new CodeCompileUnit (); var nsp = new CodeNamespace (); nsp.Imports.AddRange (namespace_uses.Select (x => new CodeNamespaceImport (x)).ToArray ()); ccu.Namespaces.Add (nsp); var taskClass = new CodeTypeDeclaration { IsClass = true, Name = taskName, TypeAttributes = TypeAttributes.Public }; var parameters = new List<CodeMemberProperty> (); var parametersBackingFields = new List<CodeMemberField> (); // add a public property + backing field for each parameter foreach (var param in parameter_group) { var prop = new CodeMemberProperty { Attributes = MemberAttributes.Public | MemberAttributes.Final, Name = param.Value.Name, Type = new CodeTypeReference (param.Value.PropertyType) }; var propBf = new CodeMemberField { Attributes = MemberAttributes.Private, Name = "_" + prop.Name, Type = prop.Type }; // add getter and setter to the property prop.GetStatements.Add (new CodeMethodReturnStatement (new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), propBf.Name))); prop.SetStatements.Add (new CodeAssignStatement (new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), propBf.Name), new CodePropertySetValueReferenceExpression ())); parameters.Add (prop); parametersBackingFields.Add (propBf); } taskClass.Members.AddRange (parameters.ToArray ()); taskClass.Members.AddRange (parametersBackingFields.ToArray ()); taskClass.BaseTypes.Add ("Microsoft.Build.Utilities.Task"); // The documentation says "ITask", but the very first example shows "Log" which is not in ITask! It is likely that the generated code uses Task or TaskExtension. if (type == "Method") { // 'code' contains the 'Execute' method directly taskClass.Members.Add (new CodeSnippetTypeMember (code)); } else if (type == "Fragment") { // 'code' contains the body of the 'Execute' method var method = new CodeMemberMethod { Attributes = MemberAttributes.Public | MemberAttributes.Override, Name = "Execute", ReturnType = new CodeTypeReference (typeof (bool)) }; // add the code and a 'return true' at the end of the method method.Statements.Add (new CodeSnippetStatement (code)); method.Statements.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (true))); taskClass.Members.Add (method); } else { throw new ArgumentException ("Invalid type: " + type); } nsp.Types.Add (taskClass); } var cscParams = new CompilerParameters (); cscParams.ReferencedAssemblies.Add ("Microsoft.Build.Framework.dll"); cscParams.ReferencedAssemblies.Add ("Microsoft.Build.Utilities.v4.0.dll"); // since we use Task, it depends on this dll. cscParams.ReferencedAssemblies.AddRange (GetReferences (references, taskFactoryLoggingHost)); cscParams.GenerateInMemory = true; var results = CodeDomProvider.CreateProvider (language).CompileAssemblyFromDom (cscParams, ccu); var errors = new CompilerError [results.Errors.Count]; results.Errors.CopyTo (errors, 0); if (errors.Any (e => !e.IsWarning)) { string msg = string.Format ("Invalid '{0}' source code of '{1}' type: {2}", language, type, string.Join (" ", errors.Where (e => !e.IsWarning).Select (e => e.ToString ()))); throw new InvalidProjectFileException (null, msg, "MSB", "3758", null); } assembly = results.CompiledAssembly; return true; }
bool Initialize(string taskName, IDictionary <string, string> factoryIdentityParameters, IDictionary <string, TaskPropertyInfo> parameterGroup, string taskBody, IBuildEngine taskFactoryLoggingHost) { task_name = taskName; if (parameterGroup != null) { parameter_group = new Dictionary <string, TaskPropertyInfo> (parameterGroup); } List <string> references = new List <string> (); List <string> namespace_uses = new List <string> (); namespace_uses.Add("Microsoft.Build.Framework"); string type = null, language = null, code = null; var xml = XmlReader.Create(new StringReader(taskBody), new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Fragment }); for (xml.MoveToContent(); !xml.EOF; xml.MoveToContent()) { switch (xml.NodeType) { case XmlNodeType.Element: switch (xml.LocalName) { case "Reference": references.Add(xml.GetAttribute("Include")); xml.Skip(); break; case "Using": namespace_uses.Add(xml.GetAttribute("Namespace")); xml.Skip(); break; case "Code": // MSB3757: Multiple Code elements have been found, this is not allowed. if (code != null) { throw new InvalidProjectFileException(null, "Multiple Code elements are not allowed", "MSB", "3757", null); } type = xml.GetAttribute("Type"); language = xml.GetAttribute("Language"); code = xml.ReadElementContentAsString(); break; } break; default: xml.Skip(); break; } } if (language == "vb") { throw new NotImplementedException(string.Format("{0} is not supported language for inline task", language)); } if (language != "cs") { throw new InvalidProjectFileException(null, string.Format("{0} is not supported language for inline task", language), "MSB", "4175", null); } string gen = null; // The documentation says "ITask", but the very first example shows "Log" which is not in ITask! It is likely that the generated code uses Task or TaskExtension. string classTemplate = @"public class " + taskName + " : Microsoft.Build.Utilities.Task { @@EXECUTE@@ }"; foreach (var ns in namespace_uses) { gen += "using " + ns + ";\n"; } switch (type) { case "Class": gen += code; break; case "Method": gen += classTemplate.Replace("@@EXECUTE@@", code); break; case "Fragment": gen += classTemplate.Replace("@@EXECUTE@@", "public override bool Execute () { " + code + " return true; }"); break; } var cscParams = new CompilerParameters(); cscParams.ReferencedAssemblies.Add("Microsoft.Build.Framework.dll"); cscParams.ReferencedAssemblies.Add("Microsoft.Build.Utilities.v4.0.dll"); // since we use Task, it depends on this dll. var results = new CSharpCodeProvider().CompileAssemblyFromSource(cscParams, gen); var errors = new CompilerError [results.Errors.Count]; results.Errors.CopyTo(errors, 0); if (errors.Any(e => !e.IsWarning)) { string msg = string.Format("Invalid '{0}' source code of '{1}' type: {2}", language, type, string.Join(" ", errors.Where(e => !e.IsWarning).Select(e => e.ToString()))); throw new InvalidProjectFileException(null, msg, "MSB", "3758", null); } assembly = results.CompiledAssembly; return(true); }
public void CompileExecutable(string csPath, string dllPath, string outFileName, string outFilePath) { //var uid = csPath.GetHashCode() ^ dllPath.GetHashCode(); List <string> csFiles = new FileHelper(csPath, "*.cs").GetAllFiles(); List <string> csFileNames = new FileHelper(csPath, "*.cs").GetAllFileNames(); List <string> dllFiles = new FileHelper(dllPath, "*.dll").GetAllFiles(); provider = CodeDomProvider.CreateProvider("CSharp"); if (provider != null) { CompilerParameters cp = new CompilerParameters() { CompilerOptions = "/optimize", GenerateExecutable = false, GenerateInMemory = true, IncludeDebugInformation = false, TreatWarningsAsErrors = false, OutputAssembly = Path.Combine(outFilePath, outFileName), WarningLevel = 4 }; var prefix = outFileName.Remove(outFileName.IndexOf('.'), 1); var resName = "CSNames"; string xmlResource = Path.Combine(Logger.ServiceLogPath, prefix + resName); SerializeHelper.SerializeToXML ( Logger.ServiceLogPath, new CSFiles() { CSFileNames = csFileNames }, prefix + resName, false ); if (File.Exists(xmlResource + ".xml")) { if (provider.Supports(GeneratorSupport.Resources)) { cp.EmbeddedResources.Add(xmlResource + ".xml"); } } cp.ReferencedAssemblies.AddRange(Libraries.CommonFrameworkLibraries); dllFiles.ForEach( a => { var name = new FileInfo(a).Name; if (!Libraries.CommonFrameworkLibraries.Contains(name, new CustomStrComparer())) { cp.ReferencedAssemblies.Add(a); } //The follow can do the same thing as above... //if (!Array.Exists(Libraries.CommonFrameworkLibraries,s=>string.Equals(s.ToUpper(),name.ToUpper()))) // cp.ReferencedAssemblies.Add(a); }); CompilerResults cr = provider.CompileAssemblyFromFile(cp, csFiles.ToArray()); CompileResult results; LogModel model; if (cr.Errors.Count > 0) { var errorArray = new CompilerError[cr.Errors.Count]; cr.Errors.CopyTo(errorArray, 0); var warnings = errorArray.Where(e => e.IsWarning).ToList(); var errors = errorArray.Where(e => !e.IsWarning).ToList(); results = new CompileResult() { IsBuildSuccess = errors.Count > 0 ? false : true, Warnings = warnings, Errors = errors }; } else { results = new CompileResult() { IsBuildSuccess = true, Warnings = null, Errors = null }; } model = new LogModel() { CurrentFolder = csPath, DllPath = dllPath, CompileTime = DateTime.Now, CSFileNames = csFileNames, Results = results }; SerializeHelper.SerializeToXML(outputFolder, model, prefix, true); } }