在没有安装Visual Studio的情况下,以编程方式动态创建一个csproj

本文关键字:创建 动态 方式 csproj 一个 编程 安装 Visual Studio 情况下 | 更新日期: 2023-09-27 18:11:23

我正在尝试使用MSBuild名称空间以编程方式生成一个.csproj文件,但由于缺乏代码示例,这是一个繁琐且容易出错的过程。

到目前为止,我已经得到了以下代码,但我不确定如何添加类,引用等项目。

public void Build()
{
    string projectFile = string.Format(@"{0}'{1}.csproj", Common.GetApplicationDataFolder(), _project.Target.AssemblyName);
    Microsoft.Build.Evaluation.Project p = new Microsoft.Build.Evaluation.Project();
    ProjectCollection pc = new ProjectCollection();
    Dictionary<string, string> globalProperty = new Dictionary<string, string>();
    globalProperty.Add("Configuration", "Debug");
    globalProperty.Add("Platform", "x64");
    BuildRequestData buildRequest = new BuildRequestData(projectFile, globalProperty, null, new string[] { "Build" }, null);
    p.Save(projectFile);
    BuildResult buildResult = BuildManager.DefaultBuildManager.Build(new BuildParameters(pc), buildRequest);
}

谢谢。

在没有安装Visual Studio的情况下,以编程方式动态创建一个csproj

如果你真的想用MSBuild API创建一个项目文件,你必须使用Microsoft.Build.Construction命名空间。您需要的大多数类型都在microsoft . build .dll程序集中。下面是一个简短的示例,它创建了一个包含一些属性和项组的项目文件:

class Program
{
    static void Main(string[] args)
    {
        var root = ProjectRootElement.Create();
        var group = root.AddPropertyGroup();
        group.AddProperty("Configuration", "Debug");
        group.AddProperty("Platform", "x64");
        // references
        AddItems(root, "Reference", "System", "System.Core");
        // items to compile
        AddItems(root, "Compile", "test.cs");
        var target = root.AddTarget("Build");
        var task = target.AddTask("Csc");
        task.SetParameter("Sources", "@(Compile)");
        task.SetParameter("OutputAssembly", "test.dll");
        root.Save("test.csproj");
        Console.WriteLine(File.ReadAllText("test.csproj"));
    }
    private static void AddItems(ProjectRootElement elem, string groupName, params string[] items)
    {
        var group = elem.AddItemGroup();
        foreach(var item in items)
        {
            group.AddItem(groupName, item);
        }
    }
}

注意,这只是创建了项目文件。它不能运行它。此外,像"Configuration"answers"Platform"这样的属性只有在Visual Studio生成的项目文件中才有意义。在这里,它们不会真正做任何事情,除非你像Visual Studio那样自动添加更多带有条件的属性组。

就像我在评论中指出的那样,我认为这是错误的处理方式。您只需要动态编译源代码,这可以通过CodeDom:

获得。
using System.CodeDom.Compiler;
class Program
{
    static void Main(string[] args)
    {
        var provider = CodeDomProvider.CreateProvider("C#");
        string[] sources = {
                               @"public abstract class BaseClass { public abstract void Test(); }",
                               @"public class CustomGenerated : BaseClass { public override void Test() { System.Console.WriteLine(""Hello World""); } }"
                           };
        var results = provider.CompileAssemblyFromSource(new CompilerParameters() {
            GenerateExecutable = false,
            ReferencedAssemblies = { "System.dll", "System.Core.dll" },
            IncludeDebugInformation = true,
            CompilerOptions = "/platform:anycpu"
        }, sources);
        if (results.Errors.Count > 0)
        {
            Console.WriteLine("{0} errors", results.Errors.Count);
            foreach(CompilerError error in results.Errors)
            {
                Console.WriteLine("{0}: {1}", error.ErrorNumber, error.ErrorText);
            }
        }
        else
        {
            var type = results.CompiledAssembly.GetType("CustomGenerated");
            object instance = Activator.CreateInstance(type);
            type.GetMethod("Test").Invoke(instance, null);
        }
    }
}