C#使用Microsoft.Build完成项目处理和编译
1、使用Microsoft.Build
进行项目编译
static void Build()
{
// 项目文件路径
string projectFilePath = @"C:\Users\97460\source\repos\ConsoleApp1\ConsoleApp1\ConsoleApp1.csproj";
// 方式1
Project project = new Project(projectFilePath);
if (project.Build())
{
Console.WriteLine("编译成功!");
}
else
{
Console.WriteLine("编译失败");
}
// 方式2
using (ProjectCollection projectCollection = new ProjectCollection())
{
// 编译结果日志输出文件
string buildResultFilePath = @"logfile=C:\\1.txt";
ILogger logger = new Microsoft.Build.Logging.FileLogger()
{
Parameters = buildResultFilePath,
};
// 编译全局全量
var globalProperty = new Dictionary<string, string>();
globalProperty.Add("Configuration", "Debug");
globalProperty.Add("Platform", "AnyCPU");
// 编译
var buidlRequest = new BuildRequestData(projectFilePath, globalProperty, null, new string[] { "Build" }, null);
var buildResult = BuildManager.DefaultBuildManager.Build(new BuildParameters(projectCollection)
{
Loggers = new Collection<ILogger> { logger }
},buidlRequest);
if (buildResult.OverallResult == BuildResultCode.Success)
{
Console.WriteLine("编译成功!");
}
else
{
Console.WriteLine("编译失败");
}
}
}
2、使用devenv命令行进行编译
static void BuildCmd()
{
// 添加devenv环境变量
string vs2022 = "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\IDE\\";
var envirPaths = Environment.GetEnvironmentVariable("Path").Split(';');
if (envirPaths.FirstOrDefault(e => e == vs2022) == null)
{
var newPath = $"{Environment.GetEnvironmentVariable("Path")};{vs2022}";
Environment.SetEnvironmentVariable("Path", newPath);
}
// 项目文件路径
string solutionFilePath = "C:\\Users\\97460\\source\\repos\\ConsoleApp1\\ConsoleApp1.sln";
string projectFilePath = @"C:\Users\97460\source\repos\ConsoleApp1\ConsoleApp1\ConsoleApp1.csproj";
var log = $"{Path.GetDirectoryName(visionMasterPath)}\\{Path.GetFileNameWithoutExtension(projectFilePath)}_Build.log";
// 启动编译命令
Process process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.WorkingDirectory = Path.GetDirectoryName(solutionFilePath);
process.StartInfo.FileName = "cmd.exe";
// 编译解决方案(Debug编译)
process.StartInfo.Arguments = "/c " + $"devenv {solutionFilePath} /Build Debug";
// 编译项目(Release|x86编译并输出编译日志)
process.StartInfo.Arguments = "/c " + $"devenv \"{visionMasterPath}\" /build \"release|x86\" /project \"{projectFilePath}\" /out \"{log}\"";
process.StartInfo.RedirectStandardOutput = true;
process.Start();
var buildResultInfo = process.StandardOutput.ReadToEnd();
process.WaitForExit();
process.Close();
Console.WriteLine(buildResultInfo);
}
更多的devenv
命令可阅读 Devenv 命令行开关 - Visual Studio (Windows) | Microsoft Learn
如果使用Relase|x86或者Relase|x64编译报错“命令无效”,请先检查待编译的工程是否配置该解决方案平台。
3、添加引用
static void AddRefence()
{
// 项目文件.csproj路径
string prjectFilePath = @"C:\Users\97460\source\repos\WpfApp1\WpfApp1\WpfApp1.csproj";
var project = new Project(prjectFilePath);
Console.WriteLine("获取所有的DLL引用");
var references = project.GetItems("Reference");
Console.WriteLine(string.Join("\r\n", references.Select(p=>p.EvaluatedInclude)));
Console.WriteLine("移除DLL引用");
var dllProjectItem = references.FirstOrDefault(p => p.EvaluatedInclude == "ClassLibrary1");
if (dllProjectItem != null)
{
references.Remove(dllProjectItem);
}
Console.WriteLine("添加新的DLL引用");
var metadata = new List<KeyValuePair<string, string>>();
// DLL文件相对于项目的相对路径
metadata.Add(new KeyValuePair<string, string>("HintPath", "..\\ClassLibrary3\\bin\\Debug\\ClassLibrary2.dll"));
// 是否复制本地
metadata.Add(new KeyValuePair<string, string>("Private", "True"));
project.AddItem("Reference", "ClassLibrary2", metadata);
Console.WriteLine("获取所有的项目引用");
var projectReferences = project.GetItems("ProjectReference");
Console.WriteLine(string.Join("\r\n", projectReferences.Select(p => p.EvaluatedInclude)));
Console.WriteLine("移除项目引用");
var projectItem = references.FirstOrDefault(p => p.EvaluatedInclude == "ClassLibrary1");
if (projectItem != null)
{
references.Remove(projectItem);
}
Console.WriteLine("添加新的项目引用");
var metadata1 = new List<KeyValuePair<string, string>>();
// 添加项目的GUID
var addProject = new Project(@"C:\\Users\\97460\\source\\repos\\WpfApp1\\ClassLibrary3\ClassLibrary3.csproj");
var guid = addProject.GetProperty("ProjectGuid").EvaluatedValue;
metadata1.Add(new KeyValuePair<string, string>("Project", guid));
// 项目名称
metadata1.Add(new KeyValuePair<string, string>("Name", "ClassLibrary3"));
project.AddItem("ProjectReference", "ClassLibrary3", metadata1);
// 保存到本地
project.Save();
}
4、多次初始化Project遇到的问题
static void TestProject()
{
try
{
string prjectFilePath = @"C:\Users\97460\source\repos\WpfApp1\WpfApp1\WpfApp1.csproj";
var project0 = new Project(prjectFilePath);
var project1 = new Project(prjectFilePath);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
使用以上测试代码进行测试会报错:在项目集合中已有等效项目(全局属性和工具版本相同的项目),路径为“C:\Users\97460\source\repos\WpfApp1\WpfApp1\WpfApp1.csproj”。若要向此项目集合中加载等效项目,请先卸载此项目。
测试可以使用以下两种方式进行处理:
static void TestProject()
{
try
{
string prjectFilePath = @"C:\Users\97460\source\repos\WpfApp1\WpfApp1\WpfApp1.csproj";
var project0 = new Project(prjectFilePath);
var projects = ProjectCollection.GlobalProjectCollection.LoadedProjects;
Console.WriteLine("获取全局项目集合");
Console.WriteLine(string.Join("\r\n", projects.Select(p => p.GetProperty("AssemblyName").EvaluatedValue)));
var newProject = projects.FirstOrDefault(p => p.GetProperty("AssemblyName").EvaluatedValue == "WpfApp1");
if (newProject != null)
{
ProjectCollection.GlobalProjectCollection.UnloadProject(newProject);
}
var project1 = new Project(prjectFilePath);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
此方法卸载的是本地缓存,重新加载后还是使用的是缓存里面的文件,因此此时外部文件更新,但加载的信息不会更新,没有特殊要求,可以使用下面第二种方法:
static void TestProject1()
{
try
{
string prjectFilePath = @"C:\Users\97460\source\repos\WpfApp1\WpfApp1\WpfApp1.csproj";
var project0 = new Project(prjectFilePath,null,null,new ProjectCollection());
var project1 = new Project(prjectFilePath, null, null, new ProjectCollection());
Console.WriteLine("连续多次加载成功!");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}