由于自己项目需要,但是之前对于这块完全没有经验,各种百度和bing,花了几个小时才勉强搞定。
本来想用CSharpCodeProvider的但是不知道能不能编译xaml.,于是直接用msbuild
我的电脑里的msbuild的版本好像是4.0,之前运行各种提示我ToolsVersion是15.0但是最大只能是4.0. 花了好久通过bing才知道
原来最新的msbuild需要通过nuget安装..
于是..注意右边的版本号
安装好之后,大致上只需要添加这些引用
using Microsoft.Build.Evaluation;
using Microsoft.Build.Framework;
using Microsoft.Build.Logging;
using System;
using System.Collections.Generic;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Framework;
using Microsoft.Build.Logging;
using System;
using System.Collections.Generic;
static class Program
{
static void Main(string[] args)
{
//项目集合
ProjectCollection collection = new ProjectCollection();
//csproj文件路径
string projectFileName = @"f:\Projects\CSharp\CsyGame\CsyGame\Game.Runtime.csproj";
//加载一个项目 也可以直接Project project =new Project(projectFileName)
Project project = collection.LoadProject(projectFileName);
//创建一个新的实例,
//project.CreateProjectInstance();
//重新评估,用于刷新,比如设置输出目录之后
//project.ReevaluateIfNecessary();
//项目集合设置为release模式
collection.SetGlobalProperty("Configuration", "Release");
//这个应该是单独设置工程的编译模式
//project.SetProperty("Configuration", "Release");
//里面很多属性,比如输出目录,输出的类型(dll,exe)都可以设置 project.SetProperty()就可以
//project.Properties;
//logger 可以显示编译的过程 有好多.都位于Microsoft.Build.Logging,比如FileLogger...
//这个是打印到控制台
ConsoleLogger logger = new ConsoleLogger();
List<ILogger> loggers = new List<ILogger>
{
//添加
logger
};
try
{
//开始编译,有个返回值返回成功或者失败
//第一个参数是target,可以有多个target,调试的时候看project.targets就知道了
// 也可以不填 project.Build(loggers);
//Rebuild 表示重新生成,跟vs里是一样的
project.Build("Rebuild",loggers);
}
finally
{
}
collection.Dispose();
Console.ReadKey(true);
}
}
输出结果 0 warnings 0 errors
ProjectItem
//获取所有需要编译的文件
var NewCompile = project.GetItems("Compile");
//获取所有dll引用
var NewReference = project.GetItems("Reference");
//获取项目引用(比如你的项目引用了你的另一个项目就可以获取到)
var NewProjectReference = project.GetItems("ProjectReference");
//如果有项目引用但是编译失败的话
//我的解决办法是获取引用的csproj文件,再通过new Project("路径") 加载,然后编译它
//再获取到编译成功的dll,然后添加dll的绝对路径(debug或者release下的dll)
//把引用的dll路径添加到Reference下
//如果dll路径为空
if(string.IsNullOrEmpty(DllPath))
{
return;
}
//设置metadata
List<KeyValuePair<string, string>> refmetadata = new List<KeyValuePair<string, string>>
{
//只有一个 HintPath 这个key是固定(可以用notepad打开csproj文件看看),value就是dll的绝对路径
new KeyValuePair<string, string>("HintPath", DllPath)
};
//添加item "Reference" 是固定的表示添加引用,"CsyApi"是dll程序集名字,
project.AddItem("Reference", "CsyApi", refmetadata);
//添加cs文件 "Compile"是固定的 RunningCsPath是cs文件的绝对路径(也可以是相对路径)
project.AddItem("Compile", RunningCsPath);
//移除一个item
//比如移除program.cs文件,在 Compile 里,先获取
var ProgramCsItem = project.GetItems("Compile").FirstOrDefault(item => item.EvaluatedInclude.Equals("Program.cs"));
//移除
project.RemoveItem(ProgramCsItem);
移除Property也是类似操作 但是是调用RemoveProperty函数
因为我的项目需要编译xaml,还需重定向
在app.config里面,runtime 重定向 Microsoft.Build.Framework和Microsoft.Build
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="CsyGameEditor.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="15.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Build" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
<bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="15.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>