原本我是使用批处理调用 MSBuild 完成解决方案编译的,新版的 MSBuild 在 Visual Studio 2015 会自带安装.

当然在Visual Studio 2015 中,MSBuild 是一个独立的安装包,可以单独安装,而无须安装 Visual Studio 2015.

刚开始,我在 Windows Server 2008 R2 上使用 MSBuild 编译使用 .NET Framework 4.5.2 版本 开发的项目,也不是那么顺利的.

期间,遇到并且解决了很多问题,依次顺序为:

1. Windows Server 2008 R2 没有安装 .NET Framework 4.5.2 ,这个安装 .NET Framework 4.5.2 就解决了.

2. Windows Server 2008 R2 上没有可以编译 .NET Framework 4.5.2 版本项目的  MSBuild .

原因是 MSBuild 的版本问题,因为 .NET Framework 4.0 自带的 MSBuild 不能识别 C# 6.0 语法特性.

对于这个问题,当时很纠结,因为那时我还不知道 MSBuild 有了独立安装包,以为想要用新版的 MSBuild 必须在服务器上安装 Visual Studio 2015.

后来我在visualstudio.com上找到了 MSBuild 独立安装包, 名为 Microsoft Build Tools 2015, 所以这个问题也算是解决了.

3. 在Windows Server 2008 R2 上用 MSBuild 2015 居然要安装 .NET Framework 4.5.2 SDK ?

这个也是安装 .NET Framework 4.5.2 Developer Pack 就可以解决了, 不过我没安装, 而是直接从本机上拷贝一份到服务器上, 存放位置和本机的路径一样.

只要安装了 Visual Studio 2015 ,那么 SDK 的位置一般在(x86系统)C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2 ,

(x64系统)C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2.

4. 由于在项目中引用了第三方组件,而第三方组件又引用了一些 .NET Framework 4.0 的 dll, 而在引用第三方组件的项目中没有引用第三方组件中引用了的 .NET Framework 4.0 的 dll.

一般情况下,用 Visual Studio 2015 进行编译是没有问题的. 当使用批处理进行编译的时候, 问题就来了, 抛出了一对错误, 诸如 System.Object, Object 之类的错误, 比如:

error CS0012: The type 'Object' is defined in an assembly that is not referenced.
    You must add a reference to assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral,
    PublicKeyToken=b03f5f7f11d50a3a'.

The type 'System.Object' is defined in an assembly
    that is not referenced. You must add a reference to assembly 'System.Runtime,
    Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

发现同一依赖程序集的不同版本之间存在冲突

解决办法就是在引用了第三方组件的项目中, 引用第三方组件中引用了的 .NET Framework 4.0 的 dll. 这样批处理是可以成功执行完成编译的了. 但 Visual Studio 2015 编译却报错了.

于是折腾了一番, 敲定解决办法是:

1.拷贝System.Runtime.dll到解决方案目录(随意, 我的是Library目录)下.

2.直接打开需要引用的csproj文件,向其中添加:

<Reference Include="System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"><HintPath>..\..\Library\System.Runtime.dll</HintPath><Private>True</Private>
</Reference>

3.向 Web.Config 的 runtime --> assemblyBinding 节添加:

<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>

到这里, VS 编译 和 批处理编译都没问题了.

MSBuild 批处理编译 .NET Framework 4.5.2 项目的命令行:

ECHO 初始化变量
SET ProgramPath="C:\Program Files"
IF EXIST %windir%\SysWOW64 SET ProgramPath="C:\Program Files (x86)"
SET MsBuildExe="%ProgramPath%\MSBuild\14.0\Bin\MSBuild.exe" /t:rebuild /verbosity:q /p:Configuration=Release;FrameworkPathOverride="%ProgramPath%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2" /l:FileLogger,Microsoft.Build.Engine;verbosity=normal;encoding=utf-8;append=true;logfile=Build.logECHO 编译解决方案
%MsBuildExe% "C:\work\CRM\CRM.VS2015.sln"

大功告成, 这样就可以编译 .NET Framework 4.5.2 项目了.

可是后来我为什么要换成 roslyn 编译呢? 这也是有原因的!

经过上面的折腾,我成功用批处理编译 .NET Framework 4.5.2 项目后, 我并未满足, 我想要更方便的, 无须安装那么多操蛋的东西, 只需要有运行时环境就可以了, 行不行?

答案当然是可以的, 那便是近年渐火的 roslyn 开源项目.

接下来, 我尝试使用 roslyn 帮助我完成编译 .NET Framework 4.5.2 项目.

首先, 用 Visual Studio 2015 Update 1 新建一个目标框架为 .NET Framework 4.5.2 的控制台 C# 项目, 为什么一定要 Update 1, 不解释, 照做就对了.

然后对这项目右键属性, 更改程序集名称为 RBuild .

其次, 在 Visual Studio 菜单栏中 工具 --> NuGet 包管理器  --> 程序包管理器控制台.

在控制台输入指令: Install-Package Microsoft.CodeAnalysis 以及 Install-Package Microsoft.Net.Compilers.

安装成功后,在项目中会有个包管理文件 packages.config

内容如下:

<?xml version="1.0" encoding="utf-8"?>
<packages><package id="Microsoft.CodeAnalysis" version="1.1.1" targetFramework="net452" /><package id="Microsoft.CodeAnalysis.Analyzers" version="1.1.0" targetFramework="net452" /><package id="Microsoft.CodeAnalysis.Common" version="1.1.1" targetFramework="net452" /><package id="Microsoft.CodeAnalysis.CSharp" version="1.1.1" targetFramework="net452" /><package id="Microsoft.CodeAnalysis.CSharp.Workspaces" version="1.1.1" targetFramework="net452" /><package id="Microsoft.CodeAnalysis.VisualBasic" version="1.1.1" targetFramework="net452" /><package id="Microsoft.CodeAnalysis.VisualBasic.Workspaces" version="1.1.1" targetFramework="net452" /><package id="Microsoft.CodeAnalysis.Workspaces.Common" version="1.1.1" targetFramework="net452" /><package id="Microsoft.Composition" version="1.0.27" targetFramework="net452" /><package id="Microsoft.Net.Compilers" version="1.1.1" targetFramework="net452" developmentDependency="true" /><package id="System.Collections" version="4.0.0" targetFramework="net452" /><package id="System.Collections.Immutable" version="1.1.37" targetFramework="net452" /><package id="System.Diagnostics.Debug" version="4.0.0" targetFramework="net452" /><package id="System.Globalization" version="4.0.0" targetFramework="net452" /><package id="System.IO" version="4.0.0" targetFramework="net452" /><package id="System.Linq" version="4.0.0" targetFramework="net452" /><package id="System.Reflection" version="4.0.0" targetFramework="net452" /><package id="System.Reflection.Extensions" version="4.0.0" targetFramework="net452" /><package id="System.Reflection.Metadata" version="1.1.0" targetFramework="net452" /><package id="System.Reflection.Primitives" version="4.0.0" targetFramework="net452" /><package id="System.Resources.ResourceManager" version="4.0.0" targetFramework="net452" /><package id="System.Runtime" version="4.0.0" targetFramework="net452" /><package id="System.Runtime.Extensions" version="4.0.0" targetFramework="net452" /><package id="System.Runtime.InteropServices" version="4.0.0" targetFramework="net452" /><package id="System.Text.Encoding" version="4.0.0" targetFramework="net452" /><package id="System.Text.Encoding.Extensions" version="4.0.0" targetFramework="net452" /><package id="System.Threading" version="4.0.0" targetFramework="net452" />
</packages>

接着, 在 Program类 敲代码:

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.MSBuild;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;namespace WebAPI.Build.Roslyn
{class Program{/// <summary>/// 待写入文件的log列表/// </summary>static List<string> Logs = new List<string>();/// <summary>/// 输出文件,成功与否/// </summary>static Dictionary<string, bool> OutputFiles = new Dictionary<string, bool>();static void Main(string[] args){//命令行参数解析器CommandLineArgumentParser arguments = CommandLineArgumentParser.Parse(args);if (arguments.Has(ConfigInfo.Help) || arguments.Has(ConfigInfo.Question)){string helpFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "help.txt");string[] contents = File.ReadAllLines(helpFile);foreach (string content in contents){Console.WriteLine(content);}return;}//解决方案路径string solutionUrl;if (arguments.Has(ConfigInfo.SolutionUrl)){solutionUrl = arguments.Get(ConfigInfo.SolutionUrl).Next;}else{solutionUrl = GetAppSetting(ConfigInfo.SolutionUrl);}//输出目录string outputDir;if (arguments.Has(ConfigInfo.OutputDir)){outputDir = arguments.Get(ConfigInfo.OutputDir).Next;}else{outputDir = GetAppSetting(ConfigInfo.OutputDir);}//编译属性string properties;if (arguments.Has(ConfigInfo.Properties)){properties = arguments.Get(ConfigInfo.Properties).Next;}else{properties = GetAppSetting(ConfigInfo.Properties);}Dictionary<string, string> keyValues;if (!string.IsNullOrEmpty(properties)){keyValues = new Dictionary<string, string>();IEnumerable<string> props = properties.Split(';').Where(t => !string.IsNullOrWhiteSpace(t));foreach (var item in props){string[] prop = item.Split('=');keyValues.Add(prop[0], prop[1]);}}else{keyValues = null;}string logFile;if (arguments.Has(ConfigInfo.LogFile)){logFile = arguments.Get(ConfigInfo.LogFile).Next;}else{logFile = GetAppSetting(ConfigInfo.LogFile);}if (!File.Exists(solutionUrl)){AddFormatPrint("The file specified does not exist.");AddFormatPrint("FileName:" + solutionUrl);}else{AddFormatPrint("Start building solutions");AddFormatPrint();AddFormatPrint("Check output directory exists");if (!Directory.Exists(outputDir)){AddFormatPrint("Create output directory:");AddFormatPrint(outputDir);Directory.CreateDirectory(outputDir);AddFormatPrint("Output directory has been created successfully");}else{AddFormatPrint("Output directory already exists");}AddFormatPrint();AddFormatPrint("Start compilation solution");AddFormatPrint();bool success = CompileSolution(solutionUrl, outputDir, keyValues);AddFormatPrint();if (success){AddFormatPrint("Compilation completed successfully.");}else{AddFormatPrint("Compilation failed.");}}foreach (string fullPathName in OutputFiles.Where(t => t.Value == false).Select(t => t.Key)){try{File.Delete(fullPathName);}catch{}}File.WriteAllLines(logFile, Logs);#if DEBUGAddFormatPrint("Press the any key to exit.");Console.ReadKey();
#endif}/// <summary>/// 编译解决方案和输出项目bin文件/// </summary>/// <param name="solutionUrl"></param>/// <param name="outputDir"></param>/// <param name="keyValues"></param>/// <returns></returns>private static bool CompileSolution(string solutionUrl, string outputDir, Dictionary<string, string> keyValues = null){bool success = true;MSBuildWorkspace workspace;if (keyValues != null && keyValues.Any()){workspace = MSBuildWorkspace.Create(keyValues);}else{workspace = MSBuildWorkspace.Create();}Solution solution = workspace.OpenSolutionAsync(solutionUrl).Result;ProjectDependencyGraph projectGraph = solution.GetProjectDependencyGraph();foreach (ProjectId projectId in projectGraph.GetTopologicallySortedProjects()){Project project = solution.GetProject(projectId);AddFormatPrint("Building: {0}", project.FilePath);try{Compilation projectCompilation = project.GetCompilationAsync().Result;if (null != projectCompilation && !string.IsNullOrEmpty(projectCompilation.AssemblyName)){string fileName = string.Format("{0}.dll", projectCompilation.AssemblyName);string fullPathName = string.Format("{0}\\{1}", outputDir, fileName);if (!OutputFiles.ContainsKey(fullPathName)){OutputFiles.Add(fullPathName, true);}var diagnostics = projectCompilation.GetDiagnostics();var warnDiagnostics = diagnostics.Where(x => x.Severity == DiagnosticSeverity.Warning).ToArray();var errorDiagnostics = diagnostics.Where(x => x.Severity == DiagnosticSeverity.Error).ToArray();foreach (var e in errorDiagnostics.Concat(warnDiagnostics).ToArray()){AddFormatPrint("{0}: {1}", e.Severity.ToString(), e.ToString());}if (errorDiagnostics.Any()){OutputFiles[fullPathName] = false;AddFormatPrint("Build failed.");success = false;}else{AddFormatPrint("Build successfully.");using (var stream = new MemoryStream()){EmitResult result = projectCompilation.Emit(stream);AddFormatPrint("{0}  -->  {1}", project.Name, fullPathName);if (result.Success){using (FileStream file = File.Create(fullPathName)){stream.Seek(0, SeekOrigin.Begin);stream.CopyTo(file);}AddFormatPrint("Output successfully.");}else{OutputFiles[fullPathName] = false;AddFormatPrint("Output failed.");success = false;}}}AddFormatPrint();}else{AddFormatPrint("Build failed. {0}", project.FilePath);success = false;}}catch (AggregateException ex){foreach (var ie in ex.InnerExceptions){AddFormatPrint(ie.Message);}success = false;}catch (Exception ex){AddFormatPrint(ex.Message);success = false;}AddFormatPrint();}return success;}/// <summary>/// 添加消息记录和打印消息/// </summary>/// <param name="format"></param>/// <param name="args"></param>private static void AddFormatPrint(string format = "", params object[] args){if (format == string.Empty){Logs.Add(string.Empty);Console.WriteLine();}else{string log = string.Format(format, args);Logs.Add(log);Console.WriteLine(log);}}/// <summary>/// 获取配置值/// </summary>/// <param name="key"></param>/// <returns></returns>private static string GetAppSetting(string key){return ConfigurationManager.AppSettings[key] ?? ConfigurationManager.AppSettings[ConfigInfo.KeyValues[key]];}}public struct ConfigInfo{/// <summary>/// 解决方案路径/// </summary>public const string SolutionUrl = "-s";/// <summary>/// 输出目录/// </summary>public const string OutputDir = "-o";/// <summary>/// 编译属性/// </summary>public const string Properties = "-p";/// <summary>/// 日志文件名称/// </summary>public const string LogFile = "-l";/// <summary>/// 帮助/// </summary>public const string Help = "-h";/// <summary>/// 提问/// </summary>public const string Question = "-?";/// <summary>/// 全称键值对/// </summary>public static readonly Dictionary<string, string> KeyValues = new Dictionary<string, string> { { SolutionUrl, "solutionUrl" }, { OutputDir, "outputDir" }, { Properties, "properties" }, { LogFile, "logFile" } };}
}

编译完成后, 就可以在 CMD 命令行提示符用了.

这是 help.txt 内容以及用法:

Provide help information for commands.RBuild  [-s] [-o] [-p]-s —— Solution Path, required. Use: -s "C:\work\CRM\CRM.VS2015.sln"-o —— Output Directory, required. Use: -o "E:\work\CRM\Build\WebAPI\bin"-p —— Build Properties, required. Use: -p Configuration=Release;FrameworkPathOverride=C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2;key=value-l —— Output Log Path, not required. Use: -l "log.txt"

目前我只知道 roslyn 可以编译项目, 但编译后拷贝相关的非代码文件到相应目录这个功能却没有发现哪里有, 只能通过批处理自己拷贝了.

我的用法

ECHO 开始编译解决方案
BuildTools\RBuild.exe -s "..\..\CRM\src\CRM.VS2015.sln" -o "CRM\bin" -p Configuration=Release -l Build.log

安装包下载:

.NET Framework 4.5.2(运行时环境):https://www.microsoft.com/zh-cn/download/details.aspx?id=42642

.NET Framework 4.5.2 Language Pack(可选):https://www.microsoft.com/zh-cn/download/details.aspx?id=42641

.NET Framework 4.5.2 Developer Pack(SDK):https://www.microsoft.com/zh-CN/download/details.aspx?id=42637

Microsoft Build Tools 2015(MSBuild):https://www.microsoft.com/zh-cn/download/details.aspx?id=48159

引用资料:

http://www.cnblogs.com/walkerwang/p/3368986.html

http://yangpei.appsp0t.com/post/aglzfnlhbmdwZWlyDAsSBUVudHJ5GKEfDA

http://stackoverflow.com/questions/13280008/how-do-i-compile-a-c-sharp-solution-with-roslyn

http://www.cnblogs.com/linxuanchen/p/c-sharp-command-line-argument-parser.html

https://msdn.microsoft.com/zh-cn/library/ms164311.aspx

https://github.com/dotnet/roslyn

使用roslyn代替MSBuild完成解决方案编译相关推荐

  1. win10 uwp 使用 msbuild 命令行编译 UWP 程序

    原文:win10 uwp 使用 msbuild 命令行编译 UWP 程序 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http:// ...

  2. MSBuild + MSILInect实现编译时AOP-改变前后对比

    实现静态AOP,就需要我们在预编译时期,修改IL实现对代码逻辑的修改.Mono.Cecil就是一个很好的IL解析和注入框架,参见编译时MSIL注入--实践Mono Cecil(1). 我的思路为:在编 ...

  3. VS2017 Pro未能找到路径“……\bin\roslyn\csc.exe”的解决方案

    VS2017 Pro未能找到路径"--\bin\roslyn\csc.exe"的解决方案 参考文章: (1)VS2017 Pro未能找到路径"--\bin\roslyn\ ...

  4. VS2015和VS2017运行项目时,未能找到路径“……\bin\roslyn\csc.exe”的解决方案

    问题: 项目运行时出现未能找到路径"--\bin\roslyn\csc.exe". 运行截图: 描述: 有时在我们做项目时或者从SVN上拉取项目运行后,会出现未能找到路径" ...

  5. msbuild 语法_MSBuild 编译asp.net 命令写法

    本人使用的是framework4.5 visual studio 2015开发的项目 build命令如下 cd /d D:\work\Test C:\Windows\Microsoft.NET\Fra ...

  6. MSBuild 命令行编译Delphi

    为了构建项目,IDE现在使用MSBuild而不是以前的内部生成系统.IDE中的build.compile和make命令调用Microsoft的新生成引擎:MSBuild,它提供了全面的依赖性检查.MS ...

  7. Win10 OpenCV3.3.0+VS2013配置大坑,OpenCV解决方案编译报错“找不到python36_d.lib”错误...

    今天因为想要用OpenCV做图像识别,小白一个,在网上找到一个教程,但是需要配置OpenCV3.3.0的环境,于是又在网上找OpenCV3.3.0+VS2013(因为我之前已经安过了VS2013),前 ...

  8. 使用基于Roslyn的编译时AOP框架来解决.NET项目的代码复用问题

    理想的代码优化方式 团队日常协作中,自然而然的会出现很多重复代码,根据这些代码的种类,之前可能会以以下方式处理 方式 描述 应用时可能产生的问题 硬编码 多数新手,或逐渐腐坏的项目会这么干,会直接复制 ...

  9. Roslyn导致发布网站时报错-编译失败

    最近新升级了Visual Studio 2017,创建的Web项目Bin目录中多了一个叫roslyn的文件夹,该文件夹导致网站在某些服务器上发布出错 从网上搜索了一下,Roslyn是新出的动态编译工具 ...

最新文章

  1. 【亲测有效】如何安装屏幕录制工具ScreenPresso
  2. Struts2 method=get方法乱码
  3. SQL Server 审核(Audit)-- 创建服务器级别的审核
  4. 实现在CentOS7环境下搭建个人github博客
  5. jQuery表单对象属性过滤选择器
  6. 以太坊私有链 使用dev模式
  7. laravel邮件服务
  8. CPU不支持非地址对齐访问的原因
  9. 用好Visual Studio 2010进行层架构设计
  10. iPhone和SSH
  11. Kafka学习之二 Kafka安装和使用
  12. 解决IDEA 中git 无法自动push 提交问题 Push failed: Failed with error: Could not read from remote repository.
  13. 网络工程师的python之路pdf下载_网络工程师的Python之路:网络运维自动化实战
  14. atheros ar9285 wireless network Adaper设备的驱动器正防止机器进入待机状态
  15. C语言程序每个语句都必须有行号,2012年计算机二级C语言程序设计基本概念考点归纳...
  16. linux 如何安装whl文件,linux安装whl文件
  17. 钟道隆逆向英语学习法—学习SpeciaI English的三个阶段
  18. Hyperlegder Fabric监控:blockchain-explorer
  19. php seekdir,C++_详解C语言中telldir()函数和seekdir()函数的用法,C语言telldir()函数:取得目录流 - phpStudy...
  20. stm32 MPU6050 姿态解算 Mahony互补滤波算法

热门文章

  1. java transient关键字_小伙子,你真的搞懂 transient 关键字了吗?
  2. iphone相册怎么加密_iphone相册加密码锁,保护隐私
  3. Java项目:酒店管理系统(java+Springboot+Mybatis+Beetl+Layui)
  4. adg oracle 架构_云化双活的架构演进,宁夏银行新核心搭载Oracle 19c投产上线
  5. c 应用程序多语言版本,c – 在win32 API应用程序中实现全球化/多语言功能
  6. 【数据库】数据库基本操作
  7. Angular7中引用外部JS文件
  8. Java中的拆箱与装箱
  9. 移动端自动播放音视频实现代码
  10. js base64 解码