views:

103

answers:

1

I have one solution with a .NET 4.0 project (C#) that produces a delayed signed dll, that I dotfuscate and sign.

EDIT: This is how I version the dll:

[assembly: AssemblyVersion("0.7.0.*")]
[assembly: AssemblyFileVersion("0.7.0.0")]

I have another solution with a .NET 4.0 project (C++/CLI) that references the signed dll and produces a signed dll (actually, delayed signed and signed in a post build because of a flaw in the C++ build system).

The problem is that the reference to the dll contains a specific version number, which includes even the build number (I want to have a build number).

Every time I build the referenced dll, I have to change the project settings file (.vcxproj) so it reference the new version dll. Since I work with source control, this is very inconvenient (different computers might have different build numbers since each computer build its own referenced dll - the referenced dll is not in the source control).

If I don't change the reference, I get a warning:

warning MSB3245: Could not resolve this reference. Could not locate the assembly...

And many errors like this:

error C3083: 'Foo': the symbol to the left of a '::' must be a type

These are resolved once I change the reference.

How do I make the reference ignore the build number or even the entire version number?

+1  A: 

The C# IDE has an option for that, "Specific Version = False". Not available in the C++/CLI IDE. Frankly, this is not a real problem. You are probably using the [AssemblyVersion] attribute incorrectly. That version is associated with the publicly visible classes in the assembly. If you make any changes in the public members of those classes then you've got a potentially breaking change that can make code that has a dependency on those classes fail.

At that point should you change the [AssemblyVersion]. And any project that uses the assembly must get their reference assembly updated and must be recompiled.

An otherwise non-breaking change, like a bug fix or a tweak in the non-visible classes produces a new file that is otherwise completely compatible with any project that uses it. You should update the [AssemblyFileVersion] number. Which in a C++/CLI project requires updating the unmanaged Version resource. Changing the corresponding .rc file could be automated, or you could use a #define.

Note how the .NET base assemblies in version 2.0 behaved the same way. Their [AssemblyVersion] stayed at 2.0.0.0 throughout the 3.0, 3.5 and 3.5 SP1 releases. Their file version started at 2.0.50727.42. And got incremented many times over the past 5 years, up to 2.0.50727.4927, give or take.

For the record, that VS2010 bug you linked to is not a bug. It just never worked before, failure was silent. It is a flaw in the C++ build system, mt.exe embeds the manifest after the assembly is strong named. And breaks the strong name in the process because that changes the file hash. VS2010 is actually an improvement, it warns about it rather than silently letting a broken strong name go through. You don't have to delay-sign, only resign with -Ra in a post build event.

Hans Passant
+1. Thanks. I've edited my question to include the way I version the assemblies and to mention that its a flaw in the build and not a bug in VS2010. I want every build to make a new version and this can only be done using the [AssemblyVersion] and not with the [AssemblyFileVersion]. Should I not use "*" in the [AssemblyVersion]?
brickner
Yes, using * in the [AssemblyVersion] causes the problem.
Hans Passant
Thanks @Hans Passant. By the way, it's true that I don't have to delay-sign. But I get a warning if I don't. warning 810100b3: ... is a strong-name signed assembly and embedding a manifest invalidates the signature. You will need to re-sign this file to make it a valid assembly.
brickner