Re: .NET versioning




"Frans Bouma [C# MVP]" <perseus.usenetNOSPAM@xxxxxxxxx> wrote in message
news:xn0eammdh73778000@xxxxxxxxxxxxxxxxxxxxx
> David Levine wrote:
>> "Frans Bouma [C# MVP]" <perseus.usenetNOSPAM@xxxxxxxxx> wrote in
>> message news:xn0eal98h44ao3000@xxxxxxxxxxxxxxxxxxxxx
>>
>> If this isn't dll hell then it's awfully close. What would you then
>> do if it turned out that the "bugfixed" version was buggy itself, but
>> with different bugs? You could not roll it back because the original
>> version was overwritten.
>
> Agreed, but you take it out of context. My context was clearly
> defined:
> 1) above all: keep the dlls locally to the application, so you have
> xcopy deployment, which thus means avoid the GAC if possible.
> 2) if required, and if you really have to, copy the files to the GAC.
>

My statement is completely within the context of your proposal, as your
restatement makes clear; you propose overwriting assemblies in the GAC when
you think it is warranted. It is correct to try to keep DLLs local to the
app, but you immediately follow that by stating that if required (and who
determines when that is, and what criteria do they use?) you will overwrite
DLLs in the GAC, and without even going through the GAC API.

It is my position that this is worse then not fixing the bug; at least then
you know what you are dealing with. If you overwrite assemblies in the GAC
then there is no easy way to determine which version of the assembly you are
dealing with; this would quickly turn into a support nightmare. You would
need to examine something other then the assembly's baked-in version number
to determine the "real" version of the assembly. This is something no one
with any .net experience would be expecting, it is arcane and not obvious,
and there is no guarantee that any method you used to mark the assemblies
(such as set the VERSIONINFO to a different value) would be handled
correctly, or even consistently, between multiple sub-versions of the
assembly version. Would the info in the VERSIONINFO field be correct and
different? Would we compare the file size or time-date stamps? Inspect it to
look at the mvid? A combination of all these?

There's nothing in your proposal that indicates this would be limited to a
single assembly; presumably you could have many assemblies that have been
updated in this manner. This creates a situation that becomes increasingly
difficult to support, because if a customer has a problem you may need to
duplicate their environment...how do you do that? The number of different,
untested combinations of assemblies will increase exponentially.

Automated tools would not be expecting this, so it would be difficult or
impossible to use management tools to help you manage these assemblies. For
example, I've written a small app that compares the contents of the GAC on
different machines and allows you to copy assemblies from one machine to
another; this would confuse it because it would think the assemblies were
identical when in fact they were different.

What would happen when that assembly had been processed by ngen.exe? Would
the system use the new version or the ngen'd version?

This will also affect applications that were using that assembly but which
did not experience a problem - you may now break apps that were working just
fine.

I really think you ought to reconsider your prosal.

> As microsoft states: the GAC should be avoided if possible.

We are in complete agreement on this.

>
>> This also creates a situation where different versions of the same
>> dll can exist without any way to tell them apart (well, any good
>> way). Relying on the timedate stamp or the VERSIONINFO block to tell
>> them apart it is not a good way to handle it either. Typically the
>> assembly version and the VERSIONINFO contain the same version number,
>> but the runtime does not evaluate the VERSIONINFO information for
>> binding purposes, so the app will bind to the copy of the file that
>> runtime evaluates first. A support person will have a hard time
>> distinguishing between the different versions of the same assembly,
>> and this really isn't a story I'd want to tell a customer ("yes I
>> know it 'says' its the same version, but trust me, it's a different
>> version...")
>
> so, you're hereby claiming that what Microsoft is doing with their
> service packs for .NET is bad practise? hmm.
>

There are vast differences between your proposal and a service pack. If you
update the entire GAC to a new, known-good configuration I would be less
opposed (still oppposed but not as much). One of the problems with your
proposal is that it is piecemeal...update an assembly here, try it out,
ooops that wasn't it, try another one, etc. When MSFT does a service pack
they update the entire operating system to that service pack level, and when
it is done all files are working with other files that they have been tested
with.

I made no claims about how good or bad previous practice has been; don't put
words in my mouth.

>> Even if using publisher policy is ugly (I don't like it much myself)
>> it is still better then this.
>
> strange, MS doesn't use that feature themselves, even if they can
> perfectly do so.

They update the entire runtime, not one assembly at a time. Just because
they have not already done so does not mean that they will never do so.

>
> The resemblance of DLL hell is not going away with a policy file btw.
> There you too direct calls to one single dll, for all versions of the
> range defined in the policy file. DLL hell is the phenomenon where you
> install an app and it overwrites an existing dll with an OLDER version
> (or different version) and existing applications which expect a newer
> version (because the dll overwritten contains a COM object not defined
> in the now existing dll). That can't happen here, as the GAC prevents
> that. Unless you do a bad job versioning your interfaces of course (by
> adding a lot of code and not increasing the assembly version).

Agreed. Any code change at all should result in a new version number.

>> Are you suggesting that an install program manually copy the new
>> "fixed" versions directly over the existing files in the GAC? whew...
>
> No, I suggest that you should read better. I defined a context in
> which I suggested a manually copy. Manual copy: you put the files in
> the GAC. I also stated that the GAC should be avoided, because MS says
> so themselves. IF possible, keep the files locally to the application.
>

Seems to me like I read it just fine. You want it both ways; avoid the GAC
(which we agree on) but abuse it when it suits your purpose.

>> This is really going to get even more complicated when 64 bit gacs
>> are in used, along with other variants of the gac, along with all the
>> distinctions in naming conventions used for the subdirectories. There
>> are already multiple system gacs installed on systems. Also, how will
>> this work on a system with both v1.1 and v2.0 installed? Which gac
>> will you overwrite?
>
> Why would I care? The user puts the files in the gac
> (c:\windows\assembly) and not something/one else. Keep the files
> locally to the application, not in the GAC and you don't have this mess.
>
You need to care; the point is that the user wont know which GAC to put the
files into. You can either not use the gac at all, or you can use it
correctly. You are trying to fix one problem but you are creating a far
worse problem in its place.


>> Even an update that contains only bugfixes
>> is still a new assembly that may destabilize applications that use
>> them. I've experienced far too many updates that did more damage then
>> they fixed to be willing to overwrite a previous version...I may need
>> it back again.
>
> That's up to the developer and the software vendor. If a version has a
> spec and the spec says "if you specify 'true' for that parameter, ABC
> happens" and just AB happens, it's a bug. If the user of that version
> RELIES on the fact AB happens and not ABC, who's fault is that? The
> vendor can't withhold a bugfix so fixes it, and by kicking the version
> number, the vendor REQUIRES a policy file.

This does not address my statement.

>
> Now, what will that do to 'xcopy deployment' ? You can't simply upload
> a new assembly to the website's bin folder and be done with it, you
> have to recompile everything, OR use a redirect in your own .config
> file.

I use xcopy deployment and if I needed to I could install an updated
assembly in the gac as well as a policy file. I don't use click-once, I
wrote my own.

>
> OR you have to use the GAC. Which Microsoft says you should avoid, and
> you perhaps need to avoid because you don't have access to the gac
> (shared hosting environments for example)
>
I do have access to the gac, but I still avoid it because I think the gac is
more trouble then it is worth, not because I can't write code to access it.

>
> the assembly file version doesn't require a recompile nor a policy
> file. Just a new dll. With xcopy deployment, that's the most efficient
> way to do it.

No it is not, it gets you right back in the mess we had before .net
versioning. Creating a different mess does not clean up the original mess.

>
> I agree with avoiding the GAC, which is also what MS states and what I
> also said in my posting and which you apparently ignored.

I did not ignore it, I resonded to your proposal about when you do use it.

>
>> I prefer to avoid using the system GAC. I wrote my own version of a
>> local GAC that is deployed with my app and is xcopy deployable; it's
>> mainly a mechanism to ensure that shared assemblies get loaded
>> correctly. It doesn't do all the things that the global GAC does, but
>> it does not need to. Updates will only affect that application.
>
> so to solve it is to re-invent the wheel? I prefer spending time on
> solving other problems than to re-solve problems which are already
> solved.

No, I invented a mechanism that solved the problem I had to deal with and
for which MSFT did not provide a solution. It's called engineering.

Click-once works only with a limited set of applications, it does not solve
the general problem of installing applications. It also requires the 2.0
runtime.

> It also depends on your release policy of course. We have a release
> often/release plenty policy because we don't want our customers to wait
> 3/4 months for a bugfix rollup. So if builds increase each time, you
> have a bit of a problem with that policy. I'm not sure if you use a lot
> of 3rd party gui controls, but it can be a real pain if controls are
> updated regularly with different buildnumbers each time and vs.net
> doesn't update the licenses.licx file etc.

We do use 3rd party controls and libraries; I can't think of a serious
development effort that doesn't.

>
> I don't want to store stuff in the gac, though I do provide signed
> assemblies. We don't install our runtimes in the GAC because microsoft
> states you should avoid the GAC. I also want to avoid that our
> customers have to recompile their code or have to fiddle around with
> assembly redirects when a new build is released, because it will affect
> THEIR customers as well.
>
> So, signed assembly, not using a GAC and you don't want to make your
> customers' life a nightmare, what is YOUR solution to that problem?
> (besides writing your own GAC system...)

I did write my own gac system (lgac)...we never install assemblies into the
gac. All our assemblies are signed.

For our assemblies we follow these rules:
1. If a type is shared then the assembly it is defined in must be in the
local gac (a common folder). If a type is not shared then one or more copies
of it can be placed into subdirectories as needed (e.g. a plugin's folder).
This also puts restrictions on these assemblies such that they must be
uniquely named so there is no confusion about it.
2. All assemblies that reference it will always be redirected to the current
version in the lgac; this allows them to share types within the
application's process space.
3. All shared assemblies ***must*** always be backwardly compatible with
previous versions.
4. The application controls which version of the assembly is in the lgac -
it cannot be a later version then the one the main application was compiled
against. If a plugin needs a later version then either the main application
must be updated or the plugin will not be used. If the application does not
use it, then the plugins can update the assembly.

These are some of the rules - there are others. These are restrictive and
will not work for all apps, but we were not trying to create a general
system, only one that suits our own purposes.


MSFT is good at creating a system that is good enough that people want to
use it, but which has warts, limitations, etc.,and the tools to manage it
are never good enough. This creates problems but it also creates
opportunities for 3rd parties to plug the gaps. Part of the problem is that
this is still a fairly new environment and we are still going through its
shakedown period, finding out what works and what doesn't, and what else is
needed.

Here are some ideas:
Create a gac management tool that allows you to explore the gac in great
detail, filter and sort it, etc., allows comparisons between gacs on
different machines, copy assemblies around, make the GAC's equal, etc. As I
mentioned, I wrote a simple crude app 1 or 2 years ago (it's in the got dot
net sample area) that does some of this.

There should be a way (a class, assembly, or application block) that allows
you to create a local gac, one that can be deployed along with an
application using xcopy deployment. I wrote the equivalent of one, but it is
non-trivial.

Other then system libraries (the BCL) assemblies should never (or rarely) be
shared. I don't care if it solves the deployment problems of component
vendors, the ruler of the software jungle should be the application, not the
component. The application should be able to control its own environment. If
all assemblies are local then only that app will be affected by changes to
the assemblies it is using. Hard disk space due to duplicated assemblies is
not a valid issue - if you have to ask, get a bigger hard drive.

Never (or rarely) update assemblies piecemeal; it should be all or none, so
that when the update is done the system has a collection of assemblies that
have been tested against each other. In essence, all updates should be the
equivalent of a service pack.

A lot more theoretical work needs to be done on the versioning problem
space. There probably needs to be distinctions made between types of
assembles and how they are used. It short, a taxonomy of software; you can't
figure out how to deal with it unless you know what the hierarchal
relationship is. The control and deployment mechanisms need to be different
based on their differing requirements. Currently all .net assemblies are
treated equally, and that is part of the problem.

This leads directly to addressing the issues of compatiblity, both forward
and backward. Versioning is the mechanism by which we attempt to control
this. A lot more work needs to be done in this area as well.

These are extremently difficult problems to solve, especially given the wide
variance in requirements between component vendors, application developers,
users, support personnel, etc.

Dave


.



Relevant Pages

  • Re: How can I use a dll with several programs?
    ... with the GAC is the possibility of a new version of a .dll unintentionally ... Maintaining backwards compatibility of a .dll by keeping ... largely removed DLL Hell from the Windows programming radar. ... 50% based on incorrect registry entries and since .NET assemblies don't ...
    (microsoft.public.dotnet.languages.vb)
  • Re: How can I use a dll with several programs?
    ... The dll hell has everything to do with versioning of dll`s stored in one ... I don't think the DLL applies to the GAC or the Win32 Side-by-Side cache ... mechanism for Win32 assemblies. ... You should share assemblies by installing them into the global assembly ...
    (microsoft.public.dotnet.languages.vb)
  • Re: How can I use a dll with several programs?
    ... with the GAC is the possibility of a new version of a .dll unintentionally ... Maintaining backwards compatibility of a .dll by keeping its ... largely removed DLL Hell from the Windows programming radar. ... 50% based on incorrect registry entries and since .NET assemblies don't ...
    (microsoft.public.dotnet.languages.vb)
  • Re: Assembly Versioning for Multiple Frameworks and Platforms
    ... Does anyone happent to know if the 64-bit GAC is also ... version number for each framework build. ... what tool do you use to make your 1.0 assemblies? ... We use a naming scheme in the dll for the versions. ...
    (microsoft.public.dotnet.framework)
  • Re: GAC hell
    ... The only way to get at the GAC is by calling into the unmanaged fusion API's. ... Beware that the GAC uses fully qualified assembly names to store assembly references, because you don't know whether an assembly resides in the GAC, you also don't have a FQAN, this may result in false positives! ... But we've gotten so far off topic here, we're nowhere near my original question anymore, which had to do with determining which referenced assemblies are in the GAC and which are not. ... So, please if you have a small but complete sample that uses the Microsoft.Vsa namespace to generate/compile/Run "VBScript" and "JScript" scripting code, feel free to post it here. ...
    (microsoft.public.dotnet.languages.csharp)

Loading