Build Test
This is a test to build a project which has code generation (the generation is omitted here). The core code is based on Msdn, to programmatically build projects, useful in other scenarios. For Visual Studio 2008 I had to do some things that weren't in the Msdn.
- Set references to Microsoft.Build.Engine and Microsoft.Build.Framework (3.5 versions)
- In .Net 4.0, reference Microsoft.Build.
- In .Net 3.5, App.config must have a bindingRedirect for Microsoft.Build.Framework from any version to 3.5 (see below)
- In the code below, there is a compiler directive to mark .Net 4.0 code. Microsoft.Build.BuildEngine.Engine is deprecated and replaced by Microsoft.Build.Evaluation.Project.
- DeploymentItem specifies a project folder in the test project. This contains a csproj, various cs files and dll dependencies, all set as Build Action= content, Copy To Output Directory = copy always.
//#define NET4
using System;
using System.IO;
using Microsoft.Build.BuildEngine;
#if NET4
using Microsoft.Build.Evaluation; //reference Microsoft.Build.dll v4.0
#endif
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Testing
{
/// <summary>
/// Tests a project builds correctly
/// </summary>
[TestClass]
public class TestBuild
{
[TestMethod]
[DeploymentItem(@"Project", @"Project")]
public void BuildProject()
{
var workingDirectory = Path.Combine(Environment.CurrentDirectory, @"Project\");
var csproj = Path.Combine(workingDirectory, @"MyProject.csproj");
if (!File.Exists(csproj))
Assert.Inconclusive("Sources were not deployed");
BuildProject(csproj);
}
/// <summary>
/// Builds the project - based on http://msdn.microsoft.com/en-us/library/microsoft.build.buildengine.engine.aspx. Asserts success.
/// </summary>
/// <param name="projectPath">The project (csproj) path</param>
/// <returns>True if builds okay</returns>
private static bool BuildProject(string projectPath)
{
var logPath = Path.Combine(Path.GetDirectoryName(projectPath), "build.log");
#if NET4
//.Net 4 Microsoft.Build.Evaluation.Project and ProjectCollection
var engine = new ProjectCollection();
#else
// Instantiate a new Engine object
var engine = new Engine();
#endif
// Point to .NET Framework 2.0 CLR (not needed in 3.5 apparently)
//engine.BinPath = RuntimeEnvironment.GetRuntimeDirectory();
// Instantiate a new FileLogger to generate build log
var logger = new FileLogger();
// Set the logfile parameter to indicate the log destination
logger.Parameters = @"logfile=" + logPath;
// Register the logger with the engine
engine.RegisterLogger(logger);
// Build a project file
#if NET4
bool success = engine.LoadProject(projectPath).Build();
#else
bool success = engine.BuildProjectFile(projectPath);
#endif
//Unregister all loggers to close the log file
engine.UnregisterAllLoggers();
//if fails, put the log file into the assert statement
string txt = "Should have built";
if (!success && File.Exists(logPath))
txt = File.ReadAllText(logPath);
//assert succeeded
Assert.IsTrue(success, txt);
return success;
}
}
}
App.Config with binding redirect
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<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="3.5.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>