Beispiel #1
0
		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;
		}
Beispiel #2
0
        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);
        }
Beispiel #3
0
		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;
		}
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
            }
        }