Version control and updating of AssemblyInfo files - c#

I'm maintaining an application of (mostly) C# code using subversion. I'm wondering what is the best practice for when and where to update the AssemblyInfo.cs files to reflect the version number of the product as it ships.
Let's say I have a trunk, and some maintenance branches for previous versions and tags to tag each release when it happens.
If I update the AssemblyInfo files in the branch or trunk before tagging (this is my current approach), it means I can look down the log of that branch to see when releases happened which is quite useful, but it gives me spurious merge conflicts when merging between branches. For instance say I make a bug fix in the version 4 branch which updates version 4.7 to 4.8; when I try to merge that fix into the version 5 branch, the AssemblyInfo is bound to conflict.
I have also considered updating the AssemblyInfo files in the tag itself. this avoids the merge conflict problem but means you can't see the releases when looking down the history of trunk or a maintenance branch, and it also seems to violate the principle that a tag should be read-only.
From what I gather, some people like to update the AssemblyInfo files on-the-fly during the build process, and not store them in SVN at all. Although on the face of it, it seems like a good idea to automate the version numbering, I think I'd feel a lot more comfortable if the AssemblyInfo files are checked in immediately prior to performing the build so that there is a direct correlation between the version number on the assembly and the source it came from.

Just sharing experience: I do this on the build server only in the automated fashion. I've configured it once and not touching it any more, apart from infrequently incrementing major and minor version. Here is an outline:
AssemblyInfo.cs is committed to source control
AssemblyInfo.cs is not manually changed by developers
Build server picks up source on any change to source control
Build server changes AssemblyInfo automatically
Build server produces artefacts with correct version
When I tag/branch I create a tag with the build version from Build Server
Modern build servers will have features that will automate the whole process of changing this file, for example see AssemblyInfo patcher in TeamCity
The version strategy I use is:
major.minor.build_number.svn_revision_number
Where major and minor are manually hardcoded as configuration parameter on the build server. build_number is automatically incremented by the build server. svn_revision_number is picked up from the svn commit number.

Related

MSI wix upgrade - getting FileNotFoundException from time to time

I have a WIX installer running upgrade.
it completes successfully the vast majority of times. but in some cases I'm getting:
"IO.FileNotFoundException: Could not load file or assembly.... or one of its dependencies. The system cannot find the file specified."
the actual file not being found is not consistent and changes between errors.
Note: I have a WIX installation that wraps several MSIs together. the error I'm getting happens during the upgrade process itself where I run some custom c# code (to configure the machine and the environment). this code is NOT run as a custom action, rather it runs after all the inner MSIs complete (and they complete successfully).
Since the same installer completes successfully almost all the time I'm inclined to think this is an environmental issue but I cannot come up with a plausible theory to even start and test this.
this upgrade process can run on windows server 2008 r2 to the latest windows server.
The installer makes sure all .net framework prerequisites are already installer before proceeding.
Any clue on a possible reason for this to happen will be greatly appreciated.
Quick Brainstorm: 1) You could have downgraded files? 2) you have mismatched component GUIDs? 3) you have removed files without realizing? (could work if older setup version had file set permanent) 4) you have missing pre-requisites? 5) custom actions can have deleted files? 6) virus scanners can have quarantined files?
There are edge and fringe cases. Right now I can only think of transitive conditions for components (msidbComponentAttributesTransitive => component conditions are re-evaluated on reinstall potentially removing the file), but that should not affect major upgrades I think.
Downgraded Binary: It could be an issue of a downgraded binary. Downgrading a binary in your upgrade setup (including a lower version file to replace a higher version from the original setup) can result in files being missing after the installation. Try to run repair from Add / Remove Programs and launch the application again. If this solves the problem and the application launches you very likely have this problem on your hands. An ugly fix that I have recommended for this is to update the version number of an old binary to a higher version using File => Open as resource in Visual Studio. There are other ways, but I use that approach for pragmatic reasons.
Logging: There are several other possibilities. The first thing you should do is to make a proper log file:
msiexec.exe /i C:\Path\Your.msi /L*v C:\Your.log
and then look for entries like these:
MSI (s) (0C:5C) [16:13:25:890]: Disallowing installation of component: {015A4DC1-56F4-562B-96B5-B3BE0D45FA5F} since the same component with higher versioned keyfile exists
MSI (s) (0C:5C) [16:13:25:890]: Disallowing installation of component: {4B6A1404-3892-5BEF-AB47-8FE3149211A4} since the same component with higher versioned keyfile exists
See this old answer from Rob Mensching himself. And here is more from Chris Painter.
Logging How-To: Here is an answer on MSI logging. I would just enable the global logging policy so all MSI operations create a log file in the TEMP folder.
Mismatched Component GUIDs: You should keep component GUIDs stable between setups unless you move files to another location (in the source media - in other words install to a different absolute target path). If you sequence the RemoveExistingProducts action to run late your component referencing errors might cause files to be missing after major upgrade as the setup enforces component rules in this scenario (with early sequencing these rules can be bent).
If you use mismatched component GUIDs - in other words you don't keep the component GUIDs stable for files targeting the same absolute path AND you use late sequencing for the .
When should you change component GUIDs? (recommended).

How to make an MSI Minor Upgrade and How to apply it?

I want to create an Minor Upgrade for a product, I already define a WIX project that generates the MSI installer .
Directions from Microsoft states that in a Minor Upgrade, the ProductCode should not be changed, but ProductVersion must be changed.
Furthermore I change the AssemblyInfo of my application in order to match the ProductVersion. The change in the AssemblyInfo involves change for the AssemblyVersion and AssemblyFileVersion.
After these changes I generate another installer, and now I have two installers:
Installer_1.0.1.msi (A)
Installer_1.0.2.msi (B)
I installed A (double click) then proceed to Install B (double click), but I got this:
Microsoft states that to apply a minor upgrade I should see how to apply a Small Update, I choose to try Reinstalling the product :
The steps described suggest to use the command
msiexec /I Installer_1.0.2.msi REINSTALL=ALL REINSTALLMODE=vomus
Checking the msiexec command line reference I found that:
v: Runs from source and re-caches the local package
o: Reinstalls if file is missing or if an older version is installed
m: Rewrites all required computer-specific registry entries
u: Rewrite all required user-specific registry entries
s: Overwrites all existing shortcuts
That's what I need!!! (I thought to my self).
Tried the command, the result was:
No file was changed
The version in control panel/Programs changed
The installer cache change and I was not able to uninstall the product from Control Panel/Programs/Uninstall
I proceed to change the command parameter o for a because it Forces all files to be reinstalled.
Same result.
My objective is to be able to change the files without having to manually uninstall the product (This can be achieve with a MajorUpgrade, but it implies the change of the ProductCode).
What am I missing in this process?
UPDATE:
If I setup the ProductCode to be dynamic it works as expected, but it would become the minor upgrade in a major upgrade (According to the technical library).
The question is somewhat older, but the correct answer is:
What you have done, works, if done right, the two main points are:
Package Id should be different of new version (minor upgrade)
(but) use REINSTALLMODE=vemus instead of vamus in a production environment , the latter is a worst practice pattern, and if you use it, then only for a quick test ("all files overwritten, no matter which version").
So the command line is:
msiexec /I Installer_1.0.2.msi REINSTALL=ALL REINSTALLMODE=vemus
This surely works. "Only" (yes) files which have been changed after the first installation (by manual edit or changed with a program) will not be updated (for safety). You will need other methods for this (look for "companion file(s)").
But the described way of a minor upgrade though feasible is not to recommend for a production environment, maybe only for MSI experts.
1.
At least, update the file versions of all files in the setup, then you don't have to rely on "vemus" (or vamus), and moreover, you don't loose the overview and error possibilities are highly minimized.
2.
It is recommended by most sources (and I would agree) to not use Minor Upgrades because Major Upgrades work smoother, especially for non experts.
If install performance is a point, you can even use the uninstall old version after install pattern there (means "only", the action "RemoveExistingProducts" is at the final part of the setup (see MSDH help for this)).
3.
Next step of complexity (but you have to deal with) is using Patches (.msp files) as non full updates.
For Minor Upgrades you have to have same ProductCode and UpgradeCode. But you have change the ProductVersion, Package GUID and also the versions of the binaries (DLL & EXE files) in the MSI package should be greater than the previous version

Versioning software without having to edit lots of config files

We have a project that uses a couple of assemblies.
Is there an easy way of handling the version of all those assemblies at once?
We have a version like
major.minor.patch.revision
Most of the times on a release, just the minor version gets a change.
A critical part is the revision which is the fileversion in the repository.
At the moment I think this makes impossible to use one AssemblyInfo.cs for all assemblies.
How can I avoid to change the AssemblyInfo.cs of all those assemblies?
If you want all of the assemblies to have the same version, you can make a single .cs file for the versioning in one of your libraries, and add it as a link to the other projects.
This will cause the single file to be part of all three assemblies, and keep the version constant across them all.
I've found that this is easiest to do when you're going to create your build artifacts. From a process standpoint, you would:
1. Tag/Label Source
2. Get by Tag/Label
3. Edit AssemblyInfo files
4. Build, Test, Etc
5. Capture Build Artifact
This is all pretty easy to do in BuildMaster(disclaimer: I work for Inedo as a set of actions. In this case it'd be just using the Write Assembly Versions action after doing a Get Latest action.
You can see this pattern used a lot in the specifics libraries. When we build ProGet, for example, you'll notice that Write Assembly Versions shortly after comparing the directories for changings, and right before running msbuild.

How to configure build numbers in Visual Studio to enable dll comparison

I am building a C# solution in Visual Studio 2008 that has several projects and project dependencies. I am looking for a way to change dll version numbers ONLY when the code that builds the project changes. I currently use Beyond Compare to compare my locally built version to the production file system. The goal is to ONLY deploy updated dlls. I am using autoincrementing version numbers, and each time you open visual studio and do a build, all dll version numbers increment. The same goes for a full solution rebuild and when a different developer does a build and tries to deploy. Is there a way that i can configure Visual Studio to ONLY increment the build number based on changed file contents? Is there an add in that will do this?It seems a binary comparison of these files will also fail because of the different version numbers within the dlls. Does anyone know of a better tool compare only the contents of dlls?Thanks in advance.
One option is to move to a continuous integration solution such as Cruise Control .Net this allows builds to be triggered on check in to a source control system.
Regarding assembly versioning what I usually do is create a single SolutionVersion.cs (to replace the default assembly version cs) that is linked to each project (use the add existing item but change the button to add as link)
Then I use a NAnt or MSBuild task to take the cruise control build label number and overwrite the SolutionVersion.cs verison numbers before the solution gets built
That way I can take an assembly and trace it back to the code via CruiseControl build version (even better I usually get CC.net to label the source with the same number in source control)
Its not quite what you are asking, but I found this helpful in dealing with large solutions: Versioning Controlled Build. According to its doc it detects the changes you are interested in :
"If there is a file with a more recent timestamp (which means that the source code has been modified after the previous version change), the project will be marked for version update."
The recommended, supportable solution would be for your project to NOT auto-increment the build number using the visual studio way. Then you would need to manually, or write a pre-build script/ MS Build Task to do the increment.
There is an interesting sample in this codeproject article which you should check it out... it involves a prebuild task which does the task of updating the build number based on the day of the year
I would suggest that you look into options that your revision control system provides to embed revision information into source files. I've had enough problems with auto-increment in the past that I promised myself never again. These days I prefer something a little more concrete than a build number though and embed unique identifiers into every product of the build system.
I describe my own system in Embedding mercurial revision information in Visual Studio c# projects automatically. While my solution probably isn't right for you, there were other interesting options suggested in response to my question, so some of the solutions I rejected may, nevertheless, be useful to you, even if you have to adapt them to whatever VCS you use.

How to keep the installer's version number in sync with the installed assemblies' version numbers?

In my current project, I'm producing weekly releases. I've been using the technique described in this post to keep the version numbers of all of the assemblies in my project in sync. (I don't presently have any good reason to track the assemblies' version numbers separately, though I'm sure that day will eventually come.)
When I push out a release, I build a new version of the installer. Unlike all of the assemblies, which can get their version numbers from a shared SolutionInfo.cs file, the version number of the installer isn't, as best I can tell, an assembly property. So my release process includes manually advancing the version number in the setup project.
Or, I should say, usually includes doing that. I'd like to turn that into something I can't screw up. I'm finding the documentation of setup and deployment projects to be surprisingly opaque (it was quite a bit harder to find out how to make it possible for the MSI to uninstall properly if the user installed it to a non-default path, which is a pretty freaking common use case to be undocumented) and have no idea if it's even possible to do this.
Any ideas?
Edit:
Just to clarify, this is a Visual Studio setup and deployment project I'm talking about.
CodeProject has a script to set the version number of an MSI file, which you could run in the pre-built step of the setup project. You find it here:
http://www.codeproject.com/KB/install/NewSetupVersion.aspx
More Details
Be aware that with Windows Installer things are a bit more complicated. MSI files (as the one that you create using a VS Setup and Deployment project) not only have a version number but also a product code which is a GUID value. This product code is used by Windows Installer to uniquely identify your product e.g. in Control Panel -> Add Or Remove programs where you can decide to uninstall or repair a product.
However, when changing you MSI version number, this product code must also be changed in a number of cases. MSI technology is poorly documented but you can find some recommendations when to also change the product code on the following MSDN page: http://msdn.microsoft.com/en-us/library/aa367850(VS.85).aspx.
In my projects I always generate a new product code for every new version. The script on CodeProject will also change the product code for you.
And one more thing: Windows Installer only checks the first three places of the version number afaik, anything in the forth place will be ignored, i.e. 2.3.0.1234 is considered equal to 2.3.0.5678. (ProductVersion)
(There is a related article on CodeProject which might also be interesting to you: http://www.codeproject.com/KB/install/VersionVDProj.aspx)
Its going to depend on the installer toolkit you are using.
We use TFS Team Build and WiX v3. I have a custom build task that increments the build number in Team build (5.0.0.X for example), then this version number is pushed to the common AssemblyInfo.cs AssemblyFileVersion field. It is also passed by MSBuild to our solutions/projects as a property which is then passed into WiX and used to update the installer version as well.
We probably will need to do better with the assembly versioning someday as well, but right now this has been working pretty well for us.
I use a workaround for VS2010 Setup projects (.MSI + setup.exe). Open the .vdproj in Notepad and edit the ProductVersion assignment value (3.2.1 in the example below). Save the file and launch VS2010 by double-clicking on the .vdproj file.
"Product"
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "..."
...
"ProductVersion" = "8:3.2.1"
"Manufacturer" = "..."
...
}

Categories