<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
WindowsFormsApplication\WindowsFormsApplication.csproj
You can also include additional tasks in the build process in the included Target nodes for
BeforeBuild and AfterBuild events. However, these actions will not appear in the Visual Studio
2010 Build Events dialog discussed earlier. The alternative is to use a PropertyGroup node that
includes PreBuildEvent and PostBuildEvent entries. For instance, if you wanted to execute the
application after it was successfully built, you could include the following XML block immediately
before the closing </Project> tag:
<PropertyGroup>
<PostBuildEvent>"$(TargetDir)$(TargetFileName)"</PostBuildEvent>
</PropertyGroup>
Once you’ve finished editing the project file’s XML, you need to re-enable it in the solution by
right-clicking the project’s entry in the Solution Explorer and selecting the Reload Project command.
If you still have the project file open, Visual Studio asks if you want to close it to proceed.
the Msbuild schema
An extended discussion on the MSBuild engine is beyond the scope of this book. However, it’s
useful to understand the different components that make up the MSBuild project file so you can
look at and update your own projects.
924 .
chaPter 45 build cuSTomizATion
Four major elements form the basis of the project file: items, properties, targets, and tasks. Brought
together, you can use these four node types to create a configuration file that describes a project in
full, as shown in the previous sample C# project file.
items
Items are those elements that define inputs to the build system and project. They are defined as
children of an ItemGroup node, and the most common item is the Compile node used to inform
MSBuild that the specified file is to be included in the compilation. The following snippet from a
project file shows an Item element defined for the Form1.cs file of a WindowsApplication project:
<ItemGroup>
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
</ItemGroup>
Properties
PropertyGroup nodes are used to contain any properties defined to the project. Properties are
typically key/value pairings. They can only contain a single value and are used to store the project
settings you can access in the Build and Compile pages in the IDE.
PropertyGroup nodes can be optionally included by specifying a Condition attribute, as shown in
the following sample listing:
<PropertyGroup Condition=" ’$(Configuration)|$(Platform)’ == ’Release|x86’ ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
This XML defines a PropertyGroup that will only be included in the build if the project is being
built as a Release for the x86 platform. Each of the six property nodes within the PropertyGroup
uses the name of the property as the name of the node.
Targets
Target elements enable you to arrange tasks (discussed in the next section) into a sequence.
Each Target element should have a Name attribute to identify it, and it can be called directly, thus
enabling you to provide multiple entry points into the build process. The following snippet defines
a Target with a name of BeforeBuild:
<Target Name="BeforeBuild">
</Target>
MsBuild .
925
Tasks
Tasks define actions that MSBuild will execute under certain conditions. You can define your own
tasks or take advantage of the many built-in tasks, such as Copy. Shown in the following snippet,
Copy can copy one or more files from one location to another:
<Target Name="CopyFiles">
<Copy
SourceFiles="@(MySourceFiles)"
DestinationFolder="\\PDSERVER01\SourceBackup\"
/>
</Target>
assembly Versioning via Msbuild tasks
One aspect of most automated build systems is planning application versioning. In this section,
you see how you can customize the build process for your project so that it can accept an external
version number. This version number will be used to update the AssemblyInfo file, which will
subsequently affect the assembly version. Start by looking at the AssemblyInfo.cs file, which
typically contains assembly version information such as the following.
[Assembly: AssemblyVersion("1.0.0.0")]
CustomizedBuild\Properties\AssemblyInfo.cs
What the build customization needs to do is replace the default version number with a number
supplied as part of the build process. To do this we have elected to use a third-party MSBuild
library entitled MSBuildTasks, which is a project on Tigris (http://msbuildtasks.tigris.org/).
This includes a FileUpdate task that can be used to match on a regular expression. Before we can
use this task, we need to import the MSBuildTasks Targets file. This file is installed into the default
MSBuild extensions path by the MSBuildTasks MSI.
<Project ToolsVersion="4.0" DefaultTargets="Build"
xmlsn="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Required Import to use MSBuild Community Tasks -->
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\
MSBuild.Community.Tasks.Targets"/>
<PropertyGroup>
...
CustomizedBuild\CustomizedBuild.csproj
Because we want to update the AssemblyInfo file before the build, we could add a call to the
FileUpdate task in the BeforeBuild target. This would make it harder to maintain and debug later
on. A much better approach is to create a new target for the FileUpdate task and then make the
BeforeBuild target depend upon it, as follows:
926 .
chaPter 45 build cuSTomizATion
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="BeforeBuild" DependsOnTargets="UpdateAssemblyInfo">
</Target>
<Target Name="UpdateAssemblyInfo">
<Message Text="Build Version: $(BuildVersion)" />
<FileUpdate Files="Properties\AssemblyInfo.cs"
Regex="\d+\.\d+\.\d+\.\d+"
ReplacementText="$(BuildVersion)" />
</Target>
CustomizedBuild\CustomizedBuild.csproj
You will notice here that we are using a property called $(BuildVersion), which doesn’t yet
exist. If we run MSBuild against this project now, it will replace the version numbers in our
AssemblyInfo file with a blank string. This unfortunately will not compile. We could simply
define this property with some default value like this:
<PropertyGroup>
<BuildVersion>0.0.0.0</BuildVersion>
<Configuration Condition=" ’$(Configuration)’ == ’’ ">Debug</Configuration>
This will work but it means that when building our project in Visual Studio 2010 it will always have
the same version. Luckily the MSBuildTasks library has another task called Version, which will
generate a version number for us. Here is the code:
<Target Name="BeforeBuild" DependsOnTargets="GetVersion;UpdateAssemblyInfo">
</Target>
…
<Target Name="GetVersion" Condition=" $(BuildVersion) == ’’">
<Version BuildType="Automatic" RevisionType="Automatic" Major="1" Minor="3" >
<Output TaskParameter="Major" PropertyName="Major" />
<Output TaskParameter="Minor" PropertyName="Minor" />
<Output TaskParameter="Build" PropertyName="Build" />
<Output TaskParameter="Revision" PropertyName="Revision" />
</Version>
<CreateProperty Value="$(Major).$(Minor).$(Build).$(Revision)">
<Output TaskParameter="Value" PropertyName="BuildVersion" />
</CreateProperty>
</Target>
CustomizedBuild\CustomizedBuild.csproj
The new GetVersion target will only be executed if $(BuildVersion) is not specified. It calls
into the Version task from MSBuildTasks, which sets the major version number to 1 and the
minor version number to 3 (you could, of course, configure these instead of hard-coding them).
The Build and Revision numbers are automatically generated according to a simple algorithm.
These components of the version are then put together in a CreateProperty task, which comes
summary .
927
with MSBuild, to create the full $(BuildVersion) that we need. Finally, this task has been added
to the list of targets that BeforeBuild depends on.
Now when we build the project in Visual Studio 2010, we will get an automatically generated
version number as per usual. In your automated build process you can specify the version number as
an argument to the MSBuild call. For example:
MSBuild CustomizedBuild.csproj /p:BuildVersion=2.4.3154.9001
suMMary
The default build behavior can be customized with an enormous range of options in Visual Studio
2010 thanks to the power and flexibility of the MSBuild engine. Within the project file you can
include additional actions to perform both before and after the build has taken place, as well as
include additional files in the compilation.
46
assembly Versioning and
signing
what’s in this chaPter?
.
Versioning Assemblies
.
Signing an Assembly to give it a Strong Name
.
Managing Strongly Named Assemblies in the Global
Assembly Cache
When you create a .NET assembly, you can optionally sign it to provide it with a strong name.
An assembly without a strong name is identified by its filename, which often is not enough
to uniquely identify it. This means that other projects that depend on your assembly cannot
be guaranteed to consume the correct version. A strongly named assembly can be uniquely
identified by dependent projects and even system administrators, who can apply a security
policy to your assembly.
In this chapter, you learn how to use Visual Studio 2010 to set the assembly version number,
and how you can use a digital signature to sign your assembly so that it can’t be tampered
with. This will also result in a strongly named assembly, which can be added to the Global
Assembly Cache.
asseMbly naMinG
Every .NET assembly, whether it is an executable or a class library, contains a manifest that
has information about the assembly’s identity. Primarily this includes the name and version
number of the assembly, but also includes culture and public key if it is a strongly named
assembly. This information can be easily viewed by opening an assembly in Red Gate’s .NET
Reflector, as shown in Figure 46-1.
930 .
chaPter 46 ASSembly VerSioning And Signing
fiGure 46-1
In Figure 46-1, the assembly AssemblyInformationApplication.exe does not have a public key.
Other assemblies, such as System.Data, have a full name such as:
System.Data, Version=2.0.0.0, Culture=neutral, PublicKeytoken=b77a5c561934e089
You specify the name of your assembly in Visual Studio 2010 via the project properties editor, as
shown in Figure 46-2. You can see in this figure the Assembly Name field on the main Application
tab and the Assembly Version in the inset, which is accessible via the Assembly Information button.
fiGure 46-2
The following snippet illustrates the AssemblyVersion and AssemblyFileVersion assembly
attributes that are used to defi ne the version and fi le version of the assembly:
Vb
‘ Version information for an assembly consists of the following four values:
‘
‘ Major Version
‘ Minor Version
‘ Build Number
‘ Revision
‘
‘ You can specify all the values or you can default the Build and Revision Numbers
‘ by using the ‘*’ as shown below:
‘ <Assembly: AssemblyVersion(“1.0.*”)>
<Assembly: AssemblyVersion(“1.0.0.0”)>
<Assembly: AssemblyFileVersion(“1.0.0.0”)>
c#
// Explanatory comments removed
[assembly: AssemblyVersion(“1.0.0.0”)]
[assembly: AssemblyFileVersion(“1.0.0.0”)]
In case you were wondering what the difference is between the version and fi le version of an
assembly, it comes down to usage. The assembly version information is used by the .NET
Framework when resolving assembly and type information. On the other hand, the fi le version is
what is displayed in Windows Explorer when you look at the fi le properties.
If you are using a C# project, you can fi nd the AssemblyInfo.cs fi le by
expanding the Properties item found underneath the project in Solution
Explorer. If you are using VB, you can fi nd the AssemblyInfo.vb fi le under My
Project but only once Show All Files has been checked for the project.
assembly naming . 931
The assembly properties that are presented in the inset dialog in Figure 46 - 2 all appear in the
AssemblyInfo fi le that is added to your project by default.
There is much debate over whether the assembly version and fi le version number
should be in sync, but essentially it is up to you. Some developers prefer keeping