Scenario : I have a multi-project solution which has just been migrated to VS2005. I rebuild the whole solution successfully (plus a few warnings about obsolete methods of calling and signing assemblies) and everything continues to work as normal. I make a few changes to remove some of the obsolete methods and recompile. The solution now exhibits the serializer bug described in ‘Migration Woes Part 2’ but only in the release build. Debug build continues to work fine. I finish removing obsolete calls from the solution and the serializer bug is now present in both debug and release builds. By retracing each change I made, I realised that I could switch the bug on and off in debug build by varying the way in which I signed that project.
If I signed it in the ‘NET 1.1 style’ whereby I added the following to assemblyinfo.cs in the project, the debug build worked correctly.
If I signed it in the ‘NET 2.0 style’ where I remove that line from assemblyinfo.cs, right click the project in Solution Explorer, hit the Signing tab and select the key to sign the project with from there, the debug build shows the bug. Release builds are buggy with both methods of signing.
The killer is that if I now revert all obsolete methods corrections back to their original calls as they were immediately after migrating to VS2005, the bug still manifests itself in release build but not in debug build. It should be noted that none of the code being changed at this time had anything to do with the serialization code at all with the exception of how the project containing the serialization code was signed.
Steps to diagnosis so far : Hard to know where to start with this one. It's almost as if VS had cached a set of release DLLs for my permanent befuddlement fund. The general approach was to replicate the serializer bug in a single project solution and work upwards.
Eventually we did replicate this bug and got it verified by Microsoft as mentioned previously. But there were differences.
- No matter what we tried the bug either appeared in both debug and release build or neither.
- We could only turn the bug on in our reproductions whereas our original multi-project solution seemed to provide a way to turn it off, at least in Debug build anyway.
Learning the bug had an arbitrary behaviour explains away some of the mystery but it did bring up some interesting things to check in the meantime as we looked for possible reasons to explain the reasons why the bug switched on in certain cases.
Scott Hanselman provided some insight into the actual differences between debug and release builds. mcdeeis added some further clarification in Phil Haack's link to Scott's original post. However, in our particular case, our project has no #if debug statements to change its behavior in that fashion and turn off compilation optimisation in release build did not switch the bug off either.
Perhaps, as noted earlier, .NET was caching a copy of DLLs somewhere with the bug switched on? The CLR resolves DLLs by looking in the same directory as the calling application, then the GAC, then a subdirectory of the calling application. You can check the GAC using the .NET Framework Configuration Admin tool for the appropriate version of the framework and selecting ‘Manage The Assembly Cache’. Use Windows Explorer to check subdirectories for copied DLLs and then use VS2005’s solution explorer to right-click the solution and Clean Solution to make sure there are no DLLs hanging about anywhere. You can even change the version number of the solution assemblies as well if you are strong naming them. Then rebuild and see if the results are any different.
So what about the on\off switch caused by the way the project with the serialization code was signed? Did this in any way affect the version of the .NET framework running the project? Well, no. Unless the solution file states otherwise, a solution in VS2005 is compiled under .NET 2.0. What does seem to be true though is that if some projects in a multi-project are signed in the ‘NET 1.1 style’ and others are signed in the ‘NET 2.0 style’ the solution still works but some feathers are ruffled somewhere under the covers. Explicitly forcing the solution to run under the .NET 2.0 using the following additon to app.config and rebuilding caused a runtime error to occur stating that there was an error in the type initializer for one of the classes in a ‘NET 1.1 style’ signed project.
<configuration> <startup> <supportedRuntime version="v2.0.50727"/> </startup> </configuration>
Out of curiosity, I switched the version number to that of .NET 1.1 and tried to recompile in VS2005. I got an error saying the app may not be fully signed with a private key. Presumably as not all projects were signed in exactly the same way.
Current Conclusion : I've now brought the solution back to the stage where all warnings of obsolete methods in .NET 2.0 have been addressed and all projects are signed in the ‘NET 2.0 style’ which at least produces a consistent response from the arbitrary bug in the serializer. Bug aside, this case does emphasize the need to sign your projects in a consistent fashion across a solution lest it come back to bite you at a later stage.
NB. Note that it’s only my current conclusion. As and when the bug is resolved, I may well revisit the debug vs release build issue and see if I can replicate it again.