Same source, multiple targets with different resources (Visual Studio .Net 2008)
- by Mike Bell
A set of software products differ only by their resource strings, binary resources, and by the strings / graphics / product keys used by their Visual Studio Setup projects. What is the best way to create, organize, and maintain them?
i.e. All the products essentially consist of the same core functionality customized by graphics, strings, and other resource data to form each product. Imagine you are creating a set of products like "Excel for Bankers", Excel for Gardeners", "Excel for CEOs", etc. Each product has the the same functionality, but differs in name, graphics, help files, included templates etc.
The environment in which these are being built is: vanilla Windows.Forms / Visual Studio 2008 / C# / .Net.
The ideal solution would be easy to maintain. e.g. If I introduce a new string / new resource projects I haven't added the resource to should fail at compile time, not run time. (And subsequent localization of the products should also be feasible).
Hopefully I've missed the blindingly-obvious and easy way of doing all this. What is it?
============ Clarification(s) ================
By "product" I mean the package of software that gets installed by the installer and sold to the end user.
Currently I have one solution, consisting of multiple projects, (including a Setup project), which builds a set of assemblies and create a single installer.
What I need to produce are multiple products/installers, all with similar functionality, which are built from the same set of assemblies but differ in the set of resources used by one of the assemblies. What's the best way of doing this?
------------ The 95% Solution -----------------
Based upon Daminen_the_unbeliever's answer, a resource file per configuration can be achieved as follows:
Create a class library project ("Satellite").
Delete the default .cs file and add a folder ("Default")
Create a resource file in the folder "MyResources"
Properties - set CustomToolNamespace to something
appropriate (e.g. "XXX")
Make sure the access modifier for the resources is "Public". Add
the resources. Edit the source code.
Refer to the resources in your code
as XXX.MyResources.ResourceName)
Create Configurations for each product variant ("ConfigN")
For each product variant, create a folder ("VariantN")
Copy and Paste the MyResources file into each VariantN folder
Unload the "Satellite" project, and edit the .csproj file
For each "VariantN/MyResources" <Compile> or <EmbeddedResource> tag,
add a Condition="'$(Configuration)' == 'ConfigN'" attribute.
Save, Reload the .csproj, and you're done...
This creates a per-configuration resource file, which can (presumably) be further localized. Compile error messages are produced for any configuration that where a a resource is missing. The resource files can be localized using the standard method (create a second resources file (MyResources.fr.resx) and edit .csproj as before).
The reason this is a 95% solution is that resources used to initialize forms (e.g. Form Titles, button texts) can't be easily handled in the same manner - the easiest approach seems to be to overwrite these with values from the satellite assembly.