Richard said:
The OP should recompile, period. Your 'solution' is bad and will
cause problems.
Ok, let's get one thing straight first: I don't *like* the 'solution'
I proposed any more than you do. However there's a problem and if
you're confronted with that problem (and doing a search on
assemblyfileversion or assembly versioning on google reveals I'm
definitely not alone) you want to solve it.
I'll briefly describe it here and I hope you then understand that 'you
should recompile' isn't an option.
Library A, which is signed. A is referenced by library B, also signed.
A and B are from different vendors. Application C is written by
referencing B. All are version 1.0.0.0.
The developer of C discovers that B behaves weird. This developer
contacts the developer of B and explains the behavior. It turns out the
bug is in A. The developer of A is contacted and A is updated to
v1.0.0.1.
Ok, now your proposed situation: no policy files. The developer of C
installs A v1.0.0.1. Nothing works anymore, because B can't load A
v1.0.0.1. B has to be updated as well to refer to this new reference
version. So B is recompiled as well to v1.0.0.1.
Now the developer of C recompiles his application with the new B and
it now works again.
Though, B is updated. The latest build of B is now 1.0.0.1. Perhaps
the vendor of B has thousands of customers. This opens up a big problem:
B v1.0.0.0 works with A v1.0.0.0
B v1.0.0.1 works with A v1.0.0.1
B perhaps uses other 3rd party libraries as well. This increases this
list.
Ok, the vendor of B is of course not perfect and discovers a bug in B
as well. This is fixed. B v1.0.0.2 is released.
Which version of A does B v1.0.0.2 reference?
Pretty unclear from the position of the developer of C.
Ok, now WITH policy files.
A gets a policy file, because it is always installed in the GAC. Due
to the bugfix, v1.0.0.1 is released and a new policy file which
redirects 1.0.0.0 references to 1.0.0.1.
No B recompilation has to be performed, as installing the bugfix
version of A (v1.0.0.1) is enough to fix the problem for C. C also
doesn't have to be recompiled, as C references the same B. This is
fortunate for the developer of C, because C is distributed to thousands
of customers and they can now simply update a KB article and refer to
the update of A.
As stated above, B also contains a bug and gets a bugfix. But because
B isn't installed in the GAC, it doesn't have a policy file as well.
Furthermore, because it's a library, it doesn't have a .config file as
well with accompanying assembly redirects.
So let's follow your policy again: no assemblyfileversion. B gets
version 1.0.0.1. The developer of C runs into the bug in B so the
developer of B has to use the new B. He copies the new B into the C's
bin folder and C fails to start... it can't load the assembly. The
developer of C scratches his head and asks B what's wrong? B's
developer tells the developer of C to put an assembly redirect in the
config file of C. This is new stuff for the developer of C so he needs
some guidance. As B has thousands of customers, this will give a lot of
problems for the support department of B, even with a KB article and
proper documentation.
What if B did use a file version? B then got a new assemblyfileversion
but kept its assembly version. C simply kept on running without a
problem. The developer of C doesn't have to recompile.
Now, I'm in the position of B. And with me a lot of other people. In
2003 we were confronted with the problem in the context of the first
example, namely we did use strong names and increasing build versions.
This became a maintenance nightmare for customers and ourselves because
which version references what exactly? This becomes complex when you
reference multiple 3rd party assemblies as we do. (3 oracle, 1 ibm, 1
corelab mysql, 1 firebird)
We first tried to tell our customers indeed, to recompile or to use an
assembly redirect. Now, the idea is of course OK in theory, but in
practise this doesn't work for several reasons, one being that people
simply don't read docs/KB's. Another reason is that it's
counter-intuitive: an application developer wants to just deal with the
problems writing the application, not with versioning problems inside a
3rd party dll used in the application.
The problems were gone since we kept our signed assembly version to a
static version per 'major version' (like 1.0.2005.1) and increase the
file version with each build.
It has disadvantages too, like click-once-esk technology doesn't work
and indeed, if you want to store the assembly in the gac (that's 'if',
not 'when') you can't have multiple versions inside the GAC. Though
because the GAC should be avoided anyway, the problems are really minor
compared to the problems with the alternative.
Now, you can say "you have to recompile", but that's easy from a
position where you don't have to deal with this problem. If you look at
the problem description above, you'll understand why Microsoft also
doesn't increase the version number with a hotfix. This is also how I
found out that assemblyfileversion was an option for dealing with the
problem, because I wondered how MS could update .net assemblies without
breaking compiled applications, which was exactly what we wanted to do
as well.
In the real world, if you're not writing the end application, you
can't simply state: "recompile". Well, you can, but it's likely that it
isn't an option for the person you're telling it to.
That's also why this whole strict assembly loading system is flawed to
the bone. In theory I fully agree with you and if I had a chance, I
definitely would do it differently, but I can't and with me a lot of
other people who write libraries which are effectively 'in the middle'.
If you always use an installer and always install your 'B' in the GAC,
you can use a policy file and be done with it. If you're not doing
that, you're effectively 'screwed'. As I said in my previous post: it
would be better if fusion would load the 'latest' build of a major
version. Major version being a.b.c and build being 'd' in a.b.c.d. Now
b and c and also d have semantical meaning but technically no meaning.
Well, at least I know that I am not 'advising' someone to do
something that is bad and will break.
Please read the problem description above and then re-state what
you're proposing isn't 'breaking' anything.
No. I said the OP has no choice but to recompile. Your 'solution' is
bad and will break.
my solution will keep applications up and running when a bugfix or
non-breaking change is made to 'B'. And the developer of B has always
the choice of issuing a new version if required (which then does
require a recompile).
Oh come on, it is just as relevant now as it was then. How old do you
think the documentation is at msdn.microsoft.com/library?
That's not the point. In general, people go to the msdn lib on their
HDD and check what's said in there. If some blogpost somewhere on the
web claims another thing than what's in the MSDN library on most dev's
HDDs, that's great, but IMHO not something you should consider
'essential material'.
Now you are straying from the point again. I never mentioned Oracle,
not IBM. Nor did I say that people should wade through MSDN blogs.
I mentioned them because they use policy files to solve the same
problem, i.e.: an example of how policy files for BUGFIX redirections
simply work IF the assembly is always (!) in the GAC. If they don't use
policy files, it would be a big problem for a lot of developers.
No. VERSIONINFO is for unmanaged files, the strong name is for
managed files. Yes, a managed file is a PE file and can have
unmanaged resources, but as far as .NET ignores the unmanaged
VERSIONINFO resource. That makes sense because the two resources have
equivalent items and so you will get problems if the two get out of
sync.
not entirely true: if you copy an assembly to the GAC and the assembly
you're trying to copy has a lower fileversion, it's not overwriting an
existing assembly with the same assemblyversion. Though if it has a
higher file version it IS overwriting the assembly in the GAC. So IMHO
that means the assemblyfileversion IS used by the GAC and IMHO thus by
..NET. NO, of course not by fusion.
Keep unmanaged resources in the unmanaged world, and managed
resources in the managed world.
I wished I could solve it differently. Though because MS uses the
exact same mechanism, something tells me the only way out of this mess
is sadly enough through assemblyfileversion, for the time being. I saw
in vs.net 2005 yesterday that there's a property for a reference so you
can state if it's an exact reference or not. As I couldn't find ANY
documentation on it I don't know what it does exactly. I hope it does
what I think it does, but as documentation is lacking, I don't know.
This whole problem is a truly sad part of the versioning system in
..NET. IMHO the designers of the system haven't thought long enough to
address this problem as well, but have simply assumed that it either
won't happen or that everyone would keep track of a myriad of version
dependencies in assembly redirects, either in .NET config settings set
by a sysadmin or in a .config file (as policy files are apparently also
off limits according to MS).
I get the feeling you think too light about this problem and what the
consequences are of 'recompiling', especially if you're B in an A<-B<-C
chain. But I disgress. Too much time wasted on this already, and this
discussion isn't going to solve it also.
FB
--