MSBuild copy web project references without building - c#

I'd like to have a web project in a solution that is set to "not build" in the solution configuration, however I would still like the project's references (and their dependencies) to be copied into that project's bin folder. There are class library projects in the sln that are actually built, and the web project references those.
Our current "build" just calls devenv, which does exactly this. For obvious reasons, I'd rather use MSBuild.
I am not looking for methods to do manual file copying (either individually or *.dll). There are many ways to do this. I am looking specifically for a way to replicate the behaviour that devenv.exe gives us - automatically copy references (and their dependencies) based on what is in the project section in the solution file (below).
These references come from the solution in this section:
Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}")="TheWebProjectName",
"Web\Project\Folder",
"{1CBD1906-0C2E-4C92-A81D-63C2AD816EA1}"
ProjectSection(WebsiteProperties) = preProject
TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0"
ProjectReferences = "{B125568E-E80C-4080-B8D3-5602B604734C}|Some.Reference.dll;
{117E8B0A-F0D6-47D0-BB51-71099969566D}|Some.OtherRef.dll;"
...
EndProjectSection
EndProject

MSBuild uses target files to determine it's build steps. Take a look at the relevant target files and determine how MSBuild copies those files, create your own target file and modify your build configuration to use the new target.
Relevant target files:
Location: C:\Windows\Microsoft.NET\Framework\v$(version)
Microsoft.CSharp.targets
Microsoft.Common.targets
Relevant documentation:
MSBuild
Specifying Targets

You can do build operations such as this using MSBuild Tasks: http://msdn.microsoft.com/en-us/library/ms171466(v=vs.80).aspx
In your specific case you'll probably be interested in the built in Copy Task: http://msdn.microsoft.com/en-us/library/3e54c37h(v=vs.80).aspx

Try using powershell instead of msbuild!! Ria services also relies strongly on powershell commandlets.
Cheers..

Call devenv.exe using an Exec task - we do it all the time for BizTalk solutions because old versions of MSBuild do not support the BizTalk project files...

Related

TFS 2012 Team Build Get Solution Configuration

We have built a customized TFS build template that builds all the projects in a solution file in their own folders. We have, let's say, two solution-level configurations SOLConf1 and SOLConf2 as well as two project-level configurations PROJConf1 and PROJConf2. In the Build Definition, I select a .sln solution file and the SOLConf1 configuration.
Now in the Configuration Manager window, when I select SOLConf1 as the Active Solution Configuration, I see 5 projects selected, and they all have the PROJConf1 configuration. So far so good.
We have modified the project files so that the TFS Team Build output directory is customized:
<PropertyGroup>
<_PackageTempDir>
$(TeamBuildOutDir)\$(SolutionName)\$(Configuration)\$(MSBuildProjectName)
</_PackageTempDir>
</PropertyGroup>
I would expect $(Configuration) to return the solution-level configuration (i.e. SOLConf1), instead, it returns the project-level configuration (i.e. PROJConf1). I couldn't find a property from the list of MSBuild Reserved and Well-Known Properties that would give the solution-level configuration. Inside the template, the variable passed in to MSBuild for configuration is called platformConfiguration.Configuration, which is the configuration I selected in the build definition (i.e. SOLConf1).
Now my question is: is there a way to get this variable using MSBuild macros, such that I will have something like
$(TeamBuildOutDir)\$(SolutionName)\$(platformConfiguration.Configuration)\$(MSBuildProjectName)
If not, how would one access the solution-level configuration inside MSBuild using MSBuild macros?
We have built a customized TFS build template that builds all the
projects in a solution file in their own folders.
This is a common issue with many possible solutions. When I ran into this problem I used the advice on this blog, but with .NET 4.5 this is handled via an MsBuild property.
/p:GenerateProjectSpecificOutput=true
I really love avoiding having to edit the TFS Build Templates.

How do you organise open-source Visual Studio projects with open-source dependencies?

I've started an open source MVC4 project that is using some other open source project as a dependency. I've forked the other project and will be modifying it according to my needs. The problem I'm facing is how to keep these projects depending on each other, but maintained separately. Yet people who git pull my project, would get the dependency project as well?
I can slam all the related code from other project into my repository, but this way I won't be able to contribute to a fork of dependent project. I'll just become a part of my repository. Not really want to do that.
I can maintain other project completely separately and copy *.dll files into my project. And commit dependent dll files into git. This is nice, but I loose ability to develop two projects at the same time, along with stepping into dependent code on debug (well, maybe not if copy *.pdb files along)
Similar to point 2, I can build nuget packages from dependent project and add them to my main project - again, can't really develop both projects at the same time, need to switch contexts.
With some magic have a solution file that combines projects from my repository and from dependent repository. On every build, copy dependent dll files to /lib folder and commit them. This way I don't need to switch contexts between separate projects. But the drawback is when other contributors git pull my project, they don't get dependent project, and solution files will likely be broken for them, because it'll reference project that is not in the repo.
How do you organise your code in this case?
Usually I use nuget for all my dependencies. When I fork a project I will deploy it on nuget and also on symbol source. In this way you can step inside the dependency source without problems.
For more information on symbol source and nuget see also:
Creating and Publishing a Symbol Package.
To enable symbol source debug see http://www.symbolsource.org/Public/Home/VisualStudio.
You must also remember to enable Nuget package restore.
With this solution you can't modify source code but at least you can debug it.
I use something similar in concept to CMake, but entirely within Visual Studio. There's the relatively unknown feature of property files, which can be included by solutions. This allows you to create a file containing only paths to dependencies, include the libraries you can and set relative paths, and then require people to set the appropriate paths for the other dependencies you can't/don't want to include.
With a little bit of work, it comes out fairly clean, and is super easy to automate through TeamCity and other similar tools (each build agent can set the variables to indicate where it keeps dependencies).
For small dependencies and ones that have been tweaked to work with my project, I keep an archive or the loose files in the repository, and use the properties file to reference those. Others have instructions on where to find them and how to edit the paths.
If you're interested in such an approach, I can go into some more detail. It took a bit of work to figure out, as property files aren't super well documented, but is working pretty neatly.
In case you are not creating circular dependencies, following is an idea:
add a new Class Library project with a unique name, say ClassLibrary1, to the solution
in the Build page of its project settings, config Output path to application output path
in the Build Events page, add the following line to Post-build event command line block:
del "$(TargetPath)"
repeat step 1 to 3 but giving another name, say ClassLibrary2, and config Output path to the source path of ClassLibrary1
set Project Dependancies of ClassLibrary1, check on ClassLibrary2
add all other project as project reference to ClassLibrary2, leave Copy Local with default value true
build ClassLibrary2 once, and all DLLs now are in the source path of ClassLibrary1
add them to references of ClassLibrary1 and leave Copy Local with default value true
set Project Dependancies of application and all other projects which are not cause circular dependencies, check on ClassLibrary1
add references of other projects, from the path the DLLs were put in ClassLibrary1
set Copy Local of all these added DLLs in other projects to false
Thus, the project ClassLibrary1 be a central control of the external libraries of your solution. Each time you Rebuild Solution(or just build the application), ClassLibrary1 copies the latest DLLs add to its references to the application output folder, and deletes the DLL it generated itself named ClassLibrary1.DLL. The application and dependencies at either compile time or runtime would use the same version of DLLs, you don't need to do extra deploying or check each deployments.

Post build events in Script#

I'm trying to create post build events to copy the final .js and .debug.js files for my script# projects into the proper directories. I can't use the regular output folder, since I have more than one project that references another project, and that always results in a build error (Unable to copy referenced script because it is being used by another process).
The problem is that the C# compiler appears to run the post build events BEFORE it writes the actual .js files, so they don't exist when the post build event happens.
Is there any other solution to make this work?
You can set up a DeploymentPath property in your csproj and the generated scripts will be copied there.
All of the logic is in here: https://github.com/nikhilk/scriptsharp/blob/cc/src/Core/Build/Tasks/ScriptCompilerTask.cs ... so another option is to customize the build task to exactly your requirements.
The latest work if you check out the github repo, also has the script# part of the build process done during the build step of an msbuild project, so that should free up the post-build step for you to do what you'd like with the generated scripts. See https://github.com/nikhilk/scriptsharp/blob/cc/src/Core/Build/ScriptSharp.targets. Again, its just msbuild stuff, so you could potentially customize the .targets file to your liking as well if it doesn't fit your needs.
I got around this by adding the "copy" command as a pre build step on the projects that were using the script# project output, then adding a dependency so that the script# project would be built first.

Programmatically build Solution using MSBuild

I am writing a utility for my company that will batch build a number of solutions in a one-click fashion. There are about 8 solutions in all, and each one has an average of 20 projects. The utility needs to be able to capture the build log and the total number of errors for each solution, just as is done when you build at the command line. I know I this is the command to accomplish that
msbuild mysolution.sln /t:build /verbosity:minimal /maxcpucount:xx
However, I would like to make use of the Microsoft.Build.Evaluation API's if possible. I know the Project object can load a single project, but is there anyway to build an entire solution? I intend to build this utility to make use of the all cpus/cores on the system and build multiple solutions simultaneously. I've looked at the MSDN page for Microsoft.Build.Evaluation, though the documentation is (still) abysmal.
Thanks for any help you can offer!
Jason
You do not need a Visual Studio solution file (sln) to build multiple projects. As you may know, Visual Studio project files are just MSBuild XML files and they can fall other project files. Therefore, build a project file that builds the other projects as required. This can be done in one of two ways.
First, solution files are just MSBuild XML so anything that can generate XML can generate a solution. See the MSBuild XML Schema for more information.
Second, construct a Microsoft.Build.Evaluation.Project programmatically using the constructor that takes an Microsoft.Build.Construction.ProjectRootElement instance then call Project.Build(). The ProjectRootElement has methods for adding common element types such as CreateTaskElement(), CreatePropertyElement() and CreateTargetElement().
See also:
Replace .sln with MSBuild and wrap contained projects into targets
Generating an MSBUILD project file from a visual studio solution file and project files.

How to merge multiple assemblies into one?

I consuming my service stack using EXE project (startup task for azure application) in that I have copied following service stack's DLL & some Azure's DLLs in to EXE project.
When I build this EXE project then Azure DLLs will be bundled with my EXE but service stack's DLL will not be bundled with EXE, because to run my EXE on any machine I need to copy all service stack's DLL manually.
I have used this service stack's dll to use
JsonServiceClient client = new JsonServiceClient(servicepath);
What should I have to do to bundled all these DLLs in to my EXE?
You have several options:
use ILMerge (free)
For howto see here and here
OR
use some tool like SmartAssembly (commercial)
it can embed and merge among other things (no need to change your source code)
OR
code that yourself in less than 10 lines (free but minimal source code change)
mark all needed dependencies as "embedded resource" - this way they are included in the EXE file... you need to setup an AssemblyResolve handler which at runtime reads from Resources and returns the needed DLLs to the .NET runtime...
A great tool to include referenced assemblies as embedded resources is Costura (a Fody add-in). The author Simon Kropp describes it as follows:
[...] a combination of two methods:
Jeffrey Richter's suggestion of using embedded resources as a method of merging
assemblies
Einar Egilsson's suggestion using cecil to create module initializers
The result is a super simple solution which merely requires to fetch Costura.Fody from NuGet.
Features:
Including debug symbols
Compression of embedded assemblies
Including/excluding specific assemblies
Others (see Readme)
The tool you are looking for is called ILMerge .
It is a command line tool and can be used like this:
ilmerge /target:winexe /out:MyApp.exe
MyExe.exe ServiceStack.dll ServiceStack.Interfaces.dll ServiceStack.ServiceInterface.dll ServiceStack.Text.dll
There is also an article that describes how to include ILMerge into your VS project setup here
Try ILMerge-GUI, the .NET merger.
It's a GUI based Ilmerge which avoids all command line work.
If you have WPF dependencies your options may be more limited..... ILMerge doesn't appear to deal with these. Costura.Fody (as mentioned by Codefox above) worked perfectly for us however and took about 5 minutes to get going... a very good experience.
Install with Nuget (selecting the correct default project in the Package Manager Console).
It merges the all DLLs marked "Copy Local" = true and produces a merged .EXE (alongside the standard output, most of which is now not necessary) which is also compressed. This can then be used standalone.
The license is MIT as so you can modify/distribute as required.
https://github.com/Fody/Costura/
.net core 3 introduces two new options in the project configuration, called single file publish and trimming.
You can find more details on docs here, project configuration copied here for reference.
Project Configuration:
<PropertyGroup>
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
<PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>
<PropertyGroup>
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
Using CLI:
dotnet publish -r win10-x64 -p:PublishSingleFile=true
dotnet publish -r <rid> -c Release
It is fully supported to combine the two options together to get a trimmed single assembly for your application.
Checkout the ServiceStack.Gap project which shows several examples of howto ILMerge ServiceStack into a single cross-platform .exe.
ServiceStack also includes a number of other features that's particularly well suited for these creating embedded apps where it:
Allows your services to be self-hosted using .NET's HTTP Listener
Supports pre-compiled Razor Views
Supports Embedded Resources
Supports an embedded database in Sqlite and OrmLite
Can be ILMerged into a single .exe

Categories

Resources