Build visual studio solution from code - c#

I'm writing a console application to get a solution from a tfs server, build it and publish on iis, but I'm stuck at building...
I found this code, which works like a charm
public static void BuildProject()
{
string solutionPath = Path.Combine(#"C:\MySolution\Common\Common.csproj");
List<ILogger> loggers = new List<ILogger>();
loggers.Add(new ConsoleLogger());
var projectCollection = new ProjectCollection();
projectCollection.RegisterLoggers(loggers);
var project = projectCollection.LoadProject(solutionPath);
try
{
project.Build();
}
finally
{
projectCollection.UnregisterAllLoggers();
}
}
but my solution it's pretty big and contains multiple projects which depends from each other (e.g. project A has a reference to project B)
how to get the correct order to build each project?
is there a way to build the entire solution from the .sln file?

Try using the following code to load a solution and compile it:
string projectFilePath = Path.Combine(#"c:\solutions\App\app.sln");
ProjectCollection pc = new ProjectCollection();
// THERE ARE A LOT OF PROPERTIES HERE, THESE MAP TO THE MSBUILD CLI PROPERTIES
Dictionary<string, string> globalProperty = new Dictionary<string, string>();
globalProperty.Add("OutputPath", #"c:\temp");
BuildParameters bp = new BuildParameters(pc);
BuildRequestData buildRequest = new BuildRequestData(projectFilePath, globalProperty, "4.0", new string[] { "Build" }, null);
// THIS IS WHERE THE MAGIC HAPPENS - IN PROCESS MSBUILD
BuildResult buildResult = BuildManager.DefaultBuildManager.Build(bp, buildRequest);
// A SIMPLE WAY TO CHECK THE RESULT
if (buildResult.OverallResult == BuildResultCode.Success)
{
//...
}

Related

Running .NUnit files programmatically

.nunit files are not running when using NUNIT in C#
I have tried running below code, but the error returned is that the file is not supported. All the examples on the internet use .dll as the path for a testpackage, not .unit.
According to below sites, it is possible to run .unit files:
https://github.com/nunit/docs/wiki/Writing-Engine-Extensions and
https://github.com/nunit/nunit-project-loader/tree/master/src/extension
var path = #"path to nunit file";
var package = new TestPackage(path);
var engine = TestEngineActivator.CreateInstance();
using (var runner = engine.GetRunner(package))
{
var result = runner.Run(this, TestFilter.Empty);
}
}
I have tried the following by referencing nunitprojectloader dll:
var path = #"C:\Users\Administrator\Desktop\nunit-project-loader-master\nunit-project-loader-master\ConsoleApplication1\bin\Debug\DEV.nunit";
NUnitProjectLoader pl = new NUnitProjectLoader();
pl.LoadFrom(path);
var package = pl.GetTestPackage(path);
var engine = TestEngineActivator.CreateInstance();
using (var runner = engine.GetRunner(package))
{
// execute the tests
var result = runner.Run(this, TestFilter.Empty);
}
There is a new error by doing this:
It tries running NBi.NUnit.Runtime.dll which is referenced in the nunit file.
Everythings works fine using the console.

Roslyn / MSBuildWorkspace Does Not Load Documents on Non-Dev Computer

MSBuildWorkspace does now show documents on computers other than the one I'm using to build the application.
I have seen Roslyn workspace for .NET Core's new .csproj format, but in my case, it works fine on the development computer (Documents is populated), but it is empty for the same project on a different computer.
So I am not sure why it would work on my development computer, but not on my other computer...?
This is the code :
public static IReadOnlyList<CodeFile> ReadSolution(string path)
{
List<CodeFile> codes = new List<CodeFile>();
using (MSBuildWorkspace workspace = MSBuildWorkspace.Create())
{
var solution = workspace.OpenSolutionAsync(path).Result;
foreach (var project in solution.Projects)
{
//project.Documents.Count() is 0
foreach (var doc in project.Documents)
{
if (doc.SourceCodeKind == SourceCodeKind.Regular)
{
StringBuilder sb = new StringBuilder();
using (var sw = new StringWriter(sb))
{
var source = doc.GetTextAsync().Result;
source.Write(sw);
sw.WriteLine();
}
codes.Add(new CodeFile(doc.FilePath, sb.ToString()));
}
}
}
}
return codes;
}
It turns out that the newer versions of MSBuildWorkspace no long throw exceptions on failures, instead raising an event, WorkspaceFailure. (https://github.com/dotnet/roslyn/issues/15056)
This indicated that the required build tools (v15 / VS2017) were not available. The new 2017 Build Tools installer is both too complicated for our end users and much slower to install than the 2015 build tools installer was.
Instead, I came up with this less robust method to avoid that dependency:
public static IReadOnlyList<CodeFile> ReadSolution(string path)
{
List<CodeFile> codes = new List<CodeFile>();
var dirName = System.IO.Path.GetDirectoryName(path);
var dir = new DirectoryInfo(dirName);
var csProjFiles = dir.EnumerateFiles("*.csproj", SearchOption.AllDirectories);
foreach(var csProjFile in csProjFiles)
{
var csProjPath = csProjFile.Directory.FullName;
using (var fs = new FileStream(csProjFile.FullName, FileMode.Open, FileAccess.Read))
{
using (var reader = XmlReader.Create(fs))
{
while(reader.Read())
{
if(reader.Name.Equals("Compile", StringComparison.OrdinalIgnoreCase))
{
var fn = reader["Include"];
var filePath = Path.Combine(csProjPath, fn);
var text = File.ReadAllText(filePath);
codes.Add(new CodeFile(fn,text));
}
}
}
}
}
return codes;
}
I had same problem
I was using a .Net Core Console App.
I noticed that Microsoft.CodeAnalysis.Workspaces.MSBuild had the warning:
Package Microsoft.CodeAnalysis.Workspaces.MSBuild 2.10.0 was restored using '.Net Framework,version=v4.6.1' instead of the project target framework '.NetCoreApp,Version=v2.1'. this package may not be fully compatible with your project.
I changed to a .Net Framework Console App and I could access the documents.

Microsoft.Build.Framework specify tools version

I have a target project that uses c# 6.0 I need to programatically build it.
I have the code below:
var pc = new ProjectCollection();
pc.DefaultToolsVersion = "14.0" //set tools version
var globalProperty = new Dictionary<string, string>
{
{"Configuration", "Release"},
{"Platform", "Any CPU"},
{"OutputPath", Utils.GetGaugeBinDir()}
};
var buildRequestData = new BuildRequestData(solutionFullPath, globalProperty, "14.0", new[] {"Build"}, null); //Set tools version here as well
var errorCodeAggregator = new ErrorCodeAggregator();
var buildParameters = new BuildParameters(pc) {Loggers = new ILogger[] {consoleLogger, errorCodeAggregator}};
var buildResult = BuildManager.DefaultBuildManager.Build(buildParameters, buildRequestData);
No matter where I set the tools version (of the two options above), it does not build C# 6.0.
On command line, I can do this:
msbuild foo.csproj /tv:14.0 /t:rebuild
I invoke this from MSBuild 12.0 bin directory, and it works. If I drop the /tv:14.0 flag, it fails as expected.
So, question is, what is the programatic way of specifying /tv flag to BuildManager ?
var buildRequest = new BuildRequestData(_solutionPath, globalProperties, null, new[] {"Build"},
When creating your BuildRequestData, pass null for the toolsVersion.
Then make sure the Microsoft.Build*.dll's referenced by your project are the correct version.
By default, VS will add the ones from inside it's own install directory. The updated ones should exist at "C:\Program Files (x86)\MSBuild\14.0\Bin"

Compile again MVC4 solution on run time

I'm update some values on .config files and I'm reloading that sections but is not refreshing on my bin folder, until I rebuild the solution I think that I can use this CodeDomProvider.CreateCompiler but I don't know how to do it for mvc solution. Some advices for me please.
This is my code
config.Save();
ConfigurationManager.RefreshSection("configuration");
Properties.Settings.Default.Reload();
using (Microsoft.CSharp.CSharpCodeProvider foo =new Microsoft.CSharp.CSharpCodeProvider())
{
var res = foo.CompileAssemblyFromSource(
new System.CodeDom.Compiler.CompilerParameters()
{
GenerateInMemory = true
}
);
}

Build and Publish (ASP.NET Web Application) using Microsoft.Build.Engine using c#

I want to Build a VS2008 project (ASP.NET Web Application) and then publish using Microsoft.Build.Engine.
I have so far successfully managed to BUild the project.
But i am unable to Publish it to a specified directory.
My build method is:
private void BuildProject()
{
Engine engine = new Engine();
FileLogger logger = new FileLogger();
logger.Parameters = #"logfile=C:\temp\build.log";
engine.RegisterLogger(logger);
BuildPropertyGroup bpg = new BuildPropertyGroup();
bpg.SetProperty("Configuration", "Debug");
bpg.SetProperty("Platform", "AnyCPU");
bool success = engine.BuildProjectFile(GetProjectFileName(), null, bpg);
if (success)
Console.WriteLine("Success!");
else
Console.WriteLine("Build failed - look at c:\temp\build.log for details");
engine.UnloadAllProjects();
engine.UnregisterAllLoggers();
}
And my publish method is:
private void PublishProject()
{
//no idea what goes here ... please help !!!
}
Any ideas ???
private void PublishProject()
{
Engine engine = new Engine();
FileLogger logger = new FileLogger();
logger.Parameters = #"logfile=C:\temp\publish.log";
engine.RegisterLogger(logger);
BuildPropertyGroup bpg = new BuildPropertyGroup();
bpg.SetProperty("OutDir", #"C:\outdir\");
bpg.SetProperty("Configuration", "Debug");
bpg.SetProperty("Platform", "AnyCPU");
bpg.SetProperty("DeployOnBuild", "true");
bpg.SetProperty("DeployTarget", "Package");
bpg.SetProperty("PackageLocation", #"$(OutDir)\MSDeploy\Package.zip");
bpg.SetProperty("_PackageTempDir", #"C:\temp\");
bool success = engine.BuildProjectFile(GetProjectFileName(), null, bpg);
if (success)
Console.WriteLine("Success!");
else
Console.WriteLine(#"Build failed - look at c:\temp\publish.log for details");
engine.UnloadAllProjects();
engine.UnregisterAllLoggers();
}
These are the properties I set to publish a project of mine.
DeployOnBuild=true;
DeployTarget=Package;
_PackageTempDir=$(PackagePath)

Categories