Build a Project with Resources
If you are going to build localized versions of a project, all user interface elements must be separated into resource files for the different languages. If the project uses only strings, the resource files can simply be text files. Alternatively, the resources can be placed in .resx files.
In this example, the "Hello" project contains two tasks: the Resgen task to compile resources and the Csc task to compile both the source code files and the compiled resources files. In the project file, the two tasks can be placed in the same target or different targets, and these two approaches are compared.
Resgen Task
The library of common tasks that is provided with
MSBuild includes a Resgen task that you can use to compile resources in either .resx or text files. This task includes the Sources attribute to specify which resource files to compile and the
OutputResources attribute to specify names for the output resource files. If you do not specify the
OutputResources attribute in the project file, the Resgen task appends a .resources file extension to the file name of the input files and puts the .resources files in the same directory as the input files.
In this example, the
Output element specifies that the
OutputResources attribute of the Resgen task (TaskParameter="
*OutputResources*") will contain the compiled resource files alpha.resources and beta.resources (
*OutputResources*="alpha.resources; beta.resources") and that those two files will be placed inside the Resources item collection (ItemName="Resources"). By identifying those .resources files as a collection of items of the same name, they can then be easily used as inputs for another task, such as Csc.
<Resgen
Sources="alpha.resx; beta.txt"
OutputResources="alpha.resources; beta.resources" >
<Output
TaskParameter="OutputResources"
Type="Resources"/>
</Resgen>
This
MSBuild task is equivalent to using the /compile switch for Resgen.exe:
Resgen.exe /compile alpha.resx,alpha.resources /compile beta.txt,beta.resources
Csc Task
Also provided with the library of common tasks is the Csc task, which compiles Visual C# source code files and compiled resources files to produce executables (.exe), dynamic-link libraries (.dll), or code modules (.netmodule). In this example, the Csc task will compile a Visual C# file (Sources="hello.cs") and a collection of compiled resource files that were output from the Resgen task (Resources="@(Resources)"):
<Csc
Sources="hello.cs"
Resources="@(Resources)"
OutputAssembly="hello.exe" />
Using the Resgen and Csc Tasks to Build a Project with Resources
One way of building a project with resources is to place the Resgen and Csc tasks in the same target, for example:
<Target Name="Build">
<Resgen
Sources="alpha.resx; beta.txt"
OutputResources="alpha.resources; beta.resources">
<Output
TaskParameter="OutputResources"
Type="Resources"/>
</Resgen>
<Csc
Sources="hello.cs"
Resources="@(Resources)"
OutputAssembly="hello.exe"/>
</Target>
Using this approach, the project builds as required, but the target is becoming large and inflexible. If you later wanted to add other tasks to run between Resgen and Csc, putting them all in one target would make the project file very difficult to read. Also, authoring such large targets with so many tasks makes it difficult to perform good incremental builds — builds in which only those targets that have not been built before or targets that are out of date are rebuilt.
A better way of authoring a project file is to use multiple targets and explicitly express dependencies between them. This approach also gives you the ability to run any of the targets separately and perform a smaller set of tasks rather than running a long list of tasks in one target every time you build. In this example, each task is in a separate target and the
DependsOnTargets attribute specifies that the Resources target must run before the Build target can run (Target Name="Build"
*DependsOnTargets*="Resources"):
<Target Name="Resources">
<Resgen
Sources="alpha.resx; beta.txt"
OutputResources="alpha.resources; beta.resources" >
<Output
TaskParameter="OutputResources"
Include=" "
Type="Resources"/>
</Resgen>
</Target>
<Target Name="Build" DependsOnTargets="Resources">
<Csc
Sources="hello.cs"
Resources="@(Resources)"
OutputAssembly="hello.exe"/>
</Target>
A target can depend on one or more other targets. To specify more than one target, use a semicolon to separate the list of targets.
Project Files
Visual C# example
Download code <Project
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
DefaultTargets = "Build">
<Target Name="Resources">
<Resgen
Sources="alpha.resx; beta.txt"
OutputResources="alpha.resources; beta.resources">
<Output
TaskParameter="OutputResources"
ItemName="Resources"/>
</Resgen>
</Target>
<Target Name="Build" DependsOnTargets="Resources">
<Csc
Sources="hello.cs"
Resources="@(Resources)"
OutputAssembly="hello.exe"/>
</Target>
</Project>