Tuesday, May 15, 2012 12:33 PM
Did a search as well as looked at the suggested "Related Topics", but did not find a solution to this problem.
In VS 2010 Pro, we have 47 projects in a single solutions. These we inherited, and understand the history is they were converted from VS 2008. I've added a new project (class library), and referenced (as projects) two of the other projects - 'constants' and 'common'. My new project has caused the "Found conflicts between different versions of the same dependent assembly." message to start appearing, as well as preventing parts of the app from running at runtime.
I have identified the problem assemblies and they are the two references to 'common' and 'constants' in my new project. In the IDE, my new project's Reference Properties as well as Reference Properties in all other projects claim to be referencing the same version number (for 'constants' it would be 22.214.171.12456). However, at compile time (inspecting results in bin\Debug), my new project now seems to be pointed to a different version (126.96.36.199227), while all the rest point to the same version identified in the IDE.
I've added an removed references, both in the new and in existing projects, and get the same results every time. Only a problem with the new project. I can fix the problem by adding binding redirects, but should not have to do so and we do not want to do so.
How do I get the new project to use the same versions as the rest of the projects. Our understanding is that adding via project references within the same solution should have done that for us
Tuesday, May 15, 2012 1:53 PMModerator
Are you using project references or binary references for everything? If you are using project references then all projects will use the same version. If you are using binary references then each project could be using its own version which would cause problems.
Your assembly #s look like they are auto-generated (ie. 6.4.5.*). This is not recommended and has been deprecated in newer versions of VS. The problem with auto-generated versions is that if you build the version # changes. Generally not desired except for official/nightly builds.
But versions are generally irrelevant unless you're strongly naming your assemblies. If your assemblies aren't strongly named then redirection isn't required. If your assemblies are strongly named then you need to modify how you're doing versioning. In general the assembly version will be major.minor.0.0 or major.minor.revision.0. The only time the version # changes is if you are beginning a new release. The assembly file version is generally major.minor.build.revision or major.minor.revision.build (depends upon your process). If you are strongly naming your assemblies then every time you update the version for the strongly named assembly you're going to have to update the project references (or use a redirect which is generally not a good idea).
Michael Taylor - 5/15/2012
Tuesday, May 15, 2012 2:17 PM
As I stated before, we are using project references, and thought as you stated that all the projects will use the same version. This does not seem to be the case.
All projects are signed, so strong named, and all AssemblyInfo.cs contain:
This has been the setup since I've been on the project (8 months) and has never caused a need to update project references. It has only become a problem because I've added a new project to the solution. The existing projects are fine, not needing updated references.
As far as Reference Properties, all projects seem to be setup the same way...
Copy Local: True
Embed Interop Types: False
All other options are display only fields.
Tuesday, May 15, 2012 2:59 PMModerator
Strongly named assemblies cannot use the 6.4.5.* syntax (actually no project should). It might work for a while but it certainly won't work for subsequent versions. MSDN has an article or two on how to properly version strongly named assemblies. It is not as simple as regular assemblies.
The first thing you should do is change your assembly version (not file version) for strongly named assemblies to a static value. I would recommend that you go ahead and move up to 188.8.131.52 or 184.108.40.206 so it is a step up. Once you've done that you'll be able to build your assemblies without getting redirection errors (which is what will happen now and is the expected behavior).
Now here's where people get confused - VS does not pull assemblies from the GAC but at runtime they could be. Let me clarify. VS cannot reference assemblies from the GAC directly. Every assembly that goes into the GAC also has to have a copy in a regular directory structure. For .NET assemblies you'll generally find them in Windows\Microsoft.NET or Program Files\Reference Assemblies. Your strongly named assemblies have to work the same way. If Copy Local is set to True (which is not the default for GAC assemblies) then each project gets a local copy of the assembly and each project could (potentially) be referencing a different assembly. So normally, for strongly named assemblies, Copy Local = False, Path = shared directory, Specific Version = False.
At compile time the compiler determines the assembly is strongly named so it adds a reference to the exact (assembly) version of the assembly that it is using. At runtime when the CLR needs to load the assembly it goes through a 2 step process documented in MSDN. The short form is that it first determines the version of the assembly. For a strongly named assembly the version is baked into the metadata. That exact version (a.b.c.d) has to be available otherwise the loader will fail the call. After the version has been identified the loader tries to locate the assembly by first looking in the GAC (again, for strong named assemblies). Since the GAC supports multiple versions of the same assembly it will hopefully find it. If not then it follows standard path searching rules (but still requiring the same version). If it doesn't find an exact match it fails the call. This is the reason why you'd need a redirect in your config if you are using dynamically generated assembly versions. This could also be why it is working now as you might have a redirect that matches all 6.4.5.* versions to the latest or perhaps the required assemblies (with the correct version) are already in the GAC.
So, in summary:
1) Change the strongly named assemblies to use an explicit assembly version such as 220.127.116.11 that does not change unless you are working on a new release. This eliminates the need for redirects.
2) Consider putting the strongly named assemblies into a common directory and reference that common directory instead. This makes it easy to confirm versions and also mimics the runtime behavior.
3) Consider only strongly naming assemblies that actually need to go into the GAC. Early .NET adopters had a tendency to make everything strongly named but that is generally bad and requires way more work. Now it is generally recommended that you only strongly name shared components that need to go into the GAC.
If you follow the above you will ensure you are no longer targeting multiple versions of the same strongly named assembly and the compiler warning will go away. If you still can't figure out where the warning is coming from then enable MSBuild diagnostic logging and it will show you exactly where (and what) assemblies it is pulling so you'll be able to see what is going on.
Michael Taylor - 5/15/2012
Tuesday, May 15, 2012 3:54 PMThanks for that info. Will pass this around the team and see what happens next.
Tuesday, May 15, 2012 9:01 PM
Further input from team is that this problem has disappeared for them. They switched from x86 (in our attempt to enable Edit and Continue) to Any CPU and it went away. So, I deleted my copy, fetched fresh from SVN and now the problem has gone away for me as well. I can use both x86 and Any CPU.
In hindsight it would have been nice if I simply renamed the old so I could do a WinDiff to see what changed, but I didn't.
The only difference I noticed on the refresh is that in x86 mode, my new project was not checked to build in the Build Configurations.
Still, you have convinced me (us) that we need to do something about our versioning strategy. I've opened a ticket for the build crew to decide the direction they want to take.
Thanks again for the info.
Tuesday, May 15, 2012 9:29 PMModerator
The platform (Any CPU, x86, etc) are part of the build configuration. Each build consists of both a configuration (Debug, Release) and platform. Each unique combination generates a separate, different assembly. Each combination is configured separately in the solution as to what builds and what doesn't. In fact the solution has its own set of CPs. Each solution-level CP specifies what CP of each project is used and whether it builds or not. If this is messed up then the chaos is unreal. Unfortunately VS will auto-create platforms (Mixed Platform is popular) when it detects a mismatch when you are adding new projects.
Depending upon your OS bitness an Any CPU assembly may work with an x86 but an x86 won't work with x64. For DLLs it is recommended that you always build as Any CPU unless you have an explicit dependency on something that is x86-only (such as COM). For EXEs though it is recommended that you always compile for x86 unless you explicitly need x64 support. In all cases the generated binaries are different.
So in your case I would guess you were building for one platform and then at some point the platform switched to another (perhaps the solution CP was wrong). And since you probably didn't rebuild all on your solution it was using some assemblies from Any CPU and some from x86. Depending upon the platform the wrong assembly was being pulled althought it looked right. Bad situation and difficult to detect easily. Kudos for figuring it out.
Michael Taylor - 5/15/2012