How to build multiple projects from same solution with .bat script? - c#

i need to build three projects from same solution.
Project Structure
Above image shows the current solution. I want to build only 3 three of them; mainly .Web(ASP.NET), .Server(C# Console), Client.Browser(Winforms).
I want to build them by creating a XML script. We have found this on Stackoverflow :
<?xml version="1.0" encoding="utf-8"?>
<PropertyGroup>
<OutputDir>C:\TESTMSBUILDOUTPUT</OutputDir>
</PropertyGroup>
<ItemGroup>
<ProjectToBuild Include="XXXXbook2.sln" >
<Properties>OutputPath=$(OutputDir);Configuration=MSBuildRelease;Platform=x86</Properties>
</ProjectToBuild>
</ItemGroup>
<Target Name="Build">
<MSBuild Projects="#(AllFiles)"/>
</Target>
This is for building for the whole projects inside solution. But we want to specify only three of them. What is the right format for this? Is there any tools to generate such a script.
Thanks in advance.

Related

How to execute msbuild /t:updateuid for all projects in a solution?

is there an easy way to execute msbuild /t:updateuid <project file> for all projects in a solution?
I have a huge solution with more than 150 projects and want to set Uids to all *.xaml files in all projects in the solution. I don't want to add this line to every project, but execute it from one place. Thus I can easilly control the execution of the command.
For example during the development phase I would like to disable the command to make the build process faster and just before the test phase i would like to enable it from one place. Any suggestions are wellcomed.
Regards
I managed to solve my problem using the information on the this blog.
The idea is to inject a custom .targets file, which will be processed by msbuild for every project. Imagine we have the following solution structure:
SolutionFolder
MySolution.sln
after.MySolution.sln.targets
UpdateAutomationIds.targets
The after.MySolution.sln.targets file will be processed by the msbuild. It will inject our UpdateAutomationIds.targets file to be executed for every project in the solution. Just replace MySolution with the name of your solution.
after.MySolution.sln.targets
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CustomAfterMicrosoftCommonTargets>$(MSBuildThisFileFullPath)</CustomAfterMicrosoftCommonTargets>
<SolutionPath>$(SolutionPath);CustomAfterMicrosoftCommonTargets=$(MSBuildThisFileDirectory)UpdateAutomationIds.targets</SolutionPath>
</PropertyGroup>
</Project>
UpdateAutomationIds.targets
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="UpdateAutomationIds" Condition="'$(MSBuildProjectExtension)'=='.csproj'" BeforeTargets="Build">
<Message Text="Updates automation ids. Project: $(MSBuildProjectFullPath)" Importance="high"/>
<Exec Command=""$(MSBuildToolsPath)\msbuild.exe" /t:updateuid "$(MSBuildProjectFullPath)""/>
<Exec Command=""$(MSBuildToolsPath)\msbuild.exe" /t:checkuid "$(MSBuildProjectFullPath)""/>
</Target>
</Project>

Custom settings in MSBuild for Windows Phone

I have a Jenkins server that executes MSBuild for me.
There's a whole bunch of builds that need to be done, they all use the same solution file but for every build some custom settings need to change.
The app needs to be able to read these settings.
For example if I'd build like this:
msbuild MyProject.sln /p:MyVar=SomeValue
Then when the app launches, it should be able to retrieve what the value is of MyVar.
For example, the app should be able to show a messagebox when it starts with the title 'SomeValue'.
I know I can define properties as described here by Microsoft, but I can't figure out how to read those properties when the app starts.
Or maybe I'm just looking at a completely wrong way of doing it.
Any ideas?
You would need msbuild to create a text file with the value inside of it. For that you can use the TemplateFile task of the MSBuild.Community.Tasks.Target in your msbuild file.
CreateAppVarFile.targets file:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildCommunityTasksPath>$(SolutionDir)\.build</MSBuildCommunityTasksPath>
</PropertyGroup>
<Import Project="$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.Targets" />
<Target Name="CreateAppVarFile">
<ItemGroup>
<TemplateContext Include="MyVar">
<ReplacementValue>$(MyVar)</ReplacementValue>
</TemplateContext>
</ItemGroup>
<TemplateFile Template="$(MSBuildThisFileDirectory)appvar.txt" OutputFilename="$(ProjectDir)appvar.txt" Tokens="#(TemplateContext)"/>
</Target>
</Project>
This target would then be included in your project file
<Import Project=".\build\CreateAppVarFile.targets" />
<Target Name="BeforeBuild" DependsOnTargets="CreateAppVarFile">
and your .\build\appvar.txt template file in the folder where your CreateAppVarFile.targets file is located can look just like this:
$(MyVar)
and be read from your app during runtime. Don't forget to include the appvar.txt in your project. It will contain:
SomeValue

Customizations on MSBuild (like version) for a C# solution

I'm thinking that the final result is going to be "it can't be that easily done", but just seems like it should be. I have a personal project I am working on. I'd hate to have to manually (or even in script) change versions, company, copyright, and all that on ALL the assembly.cs files and would like all that to be either in a script or in a file I can change (so the script stays the same mostly) when I want to update the version. But it seems like MSBuild is mostly a "build as is specified in Visual Studio". I'd just hate to have all that history of these files where I change just the version and possibly even make a mistake as this project will continue to get bigger and bigger. I'd like to just be able to add a new project to Visual studio and have whatever command line in my powershell script just say "compile this, but give it this company name and this file version instead of whatever is listed in the code file".
Google has NOT proven fruitful in this. I've even found it difficult to build my files to a specific folder. I've had to so far make sure all my projects are 2 folders deep and was able to say to build them at ....\, but I would like to be able to change that randomly if I like and have them built elsewhere if I so desire.
Is MSBuild perhaps not the way to go? Is there someway else to build visual studio that would be better from command line? Eventually I also want to auto build the install with wix and be able to match its version with the binary versions.
thank you
Since csproj is xml, you can use XmlUpdate "helpers" to modify the values inside the csproj file before you do your build.
For other files, you can use some other Tasks to do the job.
Here is one helpful target:
http://msbuildtasks.tigris.org/ and/or https://github.com/loresoft/msbuildtasks has the ( FileUpdate (and SvnVersion task if that is your Source-Control) ) tasks.
<Target Name="BeforeBuild_VersionTagIt_Target">
<ItemGroup>
<AssemblyInfoFiles Include="$(ProjectDir)\**\*AssemblyInfo.cs" />
</ItemGroup>
<!--
<SvnVersion LocalPath="$(MSBuildProjectDirectory)" ToolPath="$(SVNToolPath)">
<Output TaskParameter="Revision" PropertyName="MyRevision" />
</SvnVersion>
-->
<PropertyGroup>
<MyRevision>9999</MyRevision>
</PropertyGroup>
<FileUpdate Files="#(AssemblyInfoFiles)"
Regex="AssemblyFileVersion\("(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText="AssemblyFileVersion("$1.$2.$3.$(MyRevision)" />
</Target>
Below is an example of manipulating the csproj(xml).
How to add a linked file to a csproj file with MSBuild. (3.5 Framework)
But basically, when you build, you can put all the repetative stuff in a msbuild definition file (usually with the extension .proj or .msbuild)...and call msbuild.exe MyFile.proj.
Inside the .proj file, you will reference your .sln file.
For example:
$(WorkingCheckout) would be a variable (not defined here)...that has the directory where you got a copy of hte code from your source-control.
<Target Name="BuildIt" >
<MSBuild Projects="$(WorkingCheckout)\MySolution.sln" Targets="Build" Properties="Configuration=$(Configuration)">
<Output TaskParameter="TargetOutputs" ItemName="TargetOutputsItemName"></Output>
</MSBuild>
<Message Text="BuildItUp completed" />
</Target>
So below is the more complete example.
You would save this as "MyBuild.proj" and then call
"msbuild.exe" "MyBuild.proj".
Start .proj code. (Note, I did not import the libraries for the FileUpdate Task)
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="AllTargetsWrapped">
<PropertyGroup>
<!-- Always declare some kind of "base directory" and then work off of that in the majority of cases -->
<WorkingCheckout>.</WorkingCheckout>
</PropertyGroup>
<Target Name="AllTargetsWrapped">
<CallTarget Targets="BeforeBuild_VersionTagIt_Target" />
<CallTarget Targets="BuildItUp" />
</Target>
<Target Name="BuildItUp" >
<MSBuild Projects="$(WorkingCheckout)\MySolution.sln" Targets="Build" Properties="Configuration=$(Configuration)">
<Output TaskParameter="TargetOutputs" ItemName="TargetOutputsItemName"></Output>
</MSBuild>
<Message Text="BuildItUp completed" />
</Target>
<Target Name="BeforeBuild_VersionTagIt_Target">
<ItemGroup>
<AssemblyInfoFiles Include="$(ProjectDir)\**\*AssemblyInfo.cs" />
</ItemGroup>
<!--
<SvnVersion LocalPath="$(MSBuildProjectDirectory)" ToolPath="$(SVNToolPath)">
<Output TaskParameter="Revision" PropertyName="MyRevision" />
</SvnVersion>
-->
<PropertyGroup>
<MyRevision>9999</MyRevision>
</PropertyGroup>
<FileUpdate Files="#(AssemblyInfoFiles)"
Regex="AssemblyFileVersion\("(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText="AssemblyFileVersion("$1.$2.$3.$(MyRevision)" />
</Target>
</Project>
To enhance the above, you would create a new target that would run before "BeforeBuild_VersionTagIt_Target", that would pull your code from source-control and put it in the $(WorkingCheckout) folder.
The basic steps would then be: 1. Checkout code from Source-Control. 2. Run the targets that alter the AssemblyVersion (and whatever else you want to manipulate) and 3. Build the .sln file.
That's the basics of a .proj file. You can do much more. Usually by using helper libraries that already exists.

How do I specify common source files and properties and have them appear in Visual Studio

I have a solution with many projects that would like to share source files and properties. If I put the sources files in, for instance, a common .props file, the source files affect the build but don't show up in Visual Studio. A short example is:
Scratch.csproj:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<ItemGroup>
<Compile Include="Program.cs"/>
</ItemGroup>
<Import Project="a.props" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
A.props:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Compile Include="a.cs"/>
</ItemGroup>
</Project>
a.cs, Program.cs:
namespace Scratch
{
public class A {}
}
This code will not compile because class A has been declared twice. However, the file a.cs appears nowhere in the visual studio solution. Is there a good fix for this so that we can have shared properties and source files that also appear in the solution? I saw one possibility being instead of a.props, using a.csproj and adding it as well to the solution. However, that too has problems. If you only instead on using some of the properties from that project (depending on conditions set), it won't be clear which source file or property goes to which project.
Visual Studio doesn't deal with the full flexibility of MSBuild files. Builds work because Visual Studio invokes MSBuild libraries but the project designers, Solution Explorer, etc can't represent things they haven't been designed for.
The common way to include shared source (that is, if you don't make a separate project of it), is to add files to the project as links: Add Exiting Item..., select the files, and instead of clicking the button, click the arrow on the right side of the button and adds links. Solution Explorer is designed to recognize linked files.
Properties should be fine in a shared Import file but note that Visual Studio doesn't recognize changes to Imports; you have to reload the project manually.

MS Build Import Question Path

Quick question about MSBuild. I have the following MSBuild file in directory d:\MyDirectory
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
<Import Project="d:\MyDirectory\BuildTest\BuildTest\BuildTest.csproj"></Import>
</Project>
When I run this the build fails because BuildTest.csproj can't find the .cs source files and it seems to be looking in d:\MyDirectory. I was expecting the working directory to be set to that of the BuildTest.csproj and thus be able to resolve the references. What am I doing wrong?
I think ,the import element is used to import other MSBuild projects into this one (see here).
If you want to specify C# projects to build, you should do it like this:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
<ItemGroup>
<ProjectReferences Include="d:\MyDirectory\BuildTest\BuildTest\BuildTest.csproj" />
<!--more-->
</ItemGroup>
Then if you want to build all referenced projects, you can for example do this:
<Target Name="BuildAllProjects">
<MSBuild ContinueOnError="False" Projects="#(ProjectReferences)"
Targets="Clean;ReBuild">
</MSBuild>
</Target>
Remember though, that this is just 1 of many ways of doing things with MSBuild. There are a lot of good articles on MSDN on this topic, should you require more customization.

Categories