Date: | October 22, 2004 / year-entry #373 |
Tags: | history |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20041022-00/?p=37503 |
Comments: | 34 |
Summary: | Windows 95 Setup would notice that a file it was installing was older than the file already on the machine and would ask you whether you wanted to keep the existing (newer) file or to overwrite it with the older version. Asking the user this question at all turned out to have been a bad idea.... |
Windows 95 Setup would notice that a file it was installing was older than the file already on the machine and would ask you whether you wanted to keep the existing (newer) file or to overwrite it with the older version. Asking the user this question at all turned out to have been a bad idea. It's one of those dialogs that ask the user a question they have no idea how to answer. Say you're installing Windows 95 and you get the file version conflict dialog box. "The file Windows is attempting to install is older than the one already on the system. Do you want to keep the newer file?" What do you do? Well, if you're like most people, you say, "Um, I guess I'll keep the newer one," so you click Yes. And then a few seconds later, you get the same prompt for some other file. And you say Yes again. And then a few seconds later, you get the same prompt for yet another file. Now you're getting nervous. Why is the system asking you all these questions? Is it second-guessing your previous answers? Often when this happens, it's because you're doing something bad and the computer is giving you one more chance to change your mind before something horrible happens. Like in the movies when you have to type Yes five times before it will launch the nuclear weapons. Maybe this is one of those times. Now you start saying No. Besides, it's always safer to say No, isn't it? After a few more dialogs (answering No this time), Setup finally completes. The system reboots, and... it bluescreens. Why? Because those five files were part of a matched set of files that together form your video driver. By saying Yes to some of them and No to others, you ended up with a mishmash of files that don't work together. We learned our lesson. Setup doesn't ask this question any more. It always overwrites the files with the ones that come with the operating system. Sure, you may lose functionality, but at least you will be able to boot. Afterwards, you can go to Windows Update and update that driver to the latest version. Note, however, that this rule does not apply to hotfixes and Service Packs. [Raymond is currently on vacation; this message was pre-recorded.] |
Comments (34)
Comments are closed. |
And where is the option "Yes to all" gone ?
Its also on vacation ;)
Sure, not sharing dlls is great for not breaking things, but then the GDI+ update comes along and no one has a clue if they are "fully patched" or not. And people have to write tools to search the whole harddrive for instances of that dll.
Also keep in mind that most developers see setup/deployment as a nuisance. The system is in a very weird state while running setup – the system is kind of there but kind of isn’t.
When setup breaks, the mentality still persists within Windows that it’s the setup team’s fault. Nevermind that someone introduced a new dependency which never would have possibly made it through setup in the first place, the setup team has to triage these issues before the dev teams get involved.
As people familliar with large organizations will already know, the problem with having centralized cost centers like this is that you start optimizing to reduce your cost.
So the end result is that anything which might make setup less likely to work (e.g. the machine crashes as Raymond says) is stopped.
We’re working on fundamentally rethinking/reworking how os/product setup works so that we’re less dependent on such crutches but then the next obvious thing to people in large orgs comes into play: after you’ve centralized a cost, it’s hard to re-distribute it back out to the profit centers which really should own the cost associated with their decisions. It’s really hard to get the XYZ team to write 2 less features so that they can instead own their own setup story.
Fortunately upper management, while maybe not seeing/believing the organizational issues, does see the effectiveness issues that affect real live customers and is supporting changing these patterns.
Re: shared DLLs:
When you think of shared DLLs as some random optimization over static linking, what you say is true.
The truth of the matter is different.
First, code page sharing is very important for performance reasons, especially on systems with lots of processes (e.g. terminal server).
Second, when code manages some system-wide resource it has to line up across all processes. Most intra-system communications protocols do not receive the level of design or scrutiny that inter-system communications protocols do, and it’s a fundamentally hard problem for the small number of implementations of those to interoperate such that there are usually 3rd party interop testing/validation facilities.
Third, it’s a fundamental part of the Windows platform value proposition that we fix problems in the platform for you. If there’s a bug in comctl32.dll, we fix it and we get the fix onto the user’s machine. If every app had its own static copy there would be no way to service it.
There are counter arguments to each of these, but in the context of Windows and how/why it has been successful, all three are vital. Maybe #2 should be solved by having more services/daemons running but now you’re inflicting cost that wasn’t necessary. Maybe someday #1 goes away when everyone is running 128 bit processors TS machines can scale to 100,000 sessions because everyone has 20TB of main memory but that’s not the case yet. #3 is harder to counter; it’s more of a core value proposition about us being a platform. The counter-argument is of course about the so-called monoculture but the fact is that the industry expects us to take responsibility for all the code we write regardless of whether it’s statically linked or dynamically linked.
Any solution that "fixes" this problem for statically linked code would smell close enough to DLLs so that you’d just be creating a lot of churn/dust to try to address it.
Finding the right balance here is the single biggest engineering problem facing Windows in the future.
I care if you waste my memory and disk space… It’s probably not entirely rational, but I care. (lessee… x5 for multiple copies, ’cause no one cares. x10 for bloated code, ’cause no one cares. x5 for bloated data formats, ’cause… no one cares. x10 for eye candy, ’cause no one cares. I got a bigger drive to put more stuff on, not because I don’t care!)
Anyway, whenever I saw these, I always thought "Why on earth would I ever want to install older versions?" Knowing the computer’s penchant for blindly repeating things with no compelling reason, I was fortunately unwavering in that position. Now I guess I don’t have that option… Unless it’s just the OS installer, that actually makes sense.
Few points.
1. The problem arises not only when user clicks inconsistently, but even if chooses the old dll one single time, and this dll is used by someone else. Even the smartest users, save by the author of the program, can not avoid messing up the system, only if never choose the old one.
2. If the backward compatibility was always provided, the problem would not exist, always the newest file had to be kept.
3. If the system was designed to support multiple dll versions, the problem would not exist. Of course this change is now almost impossible, since affects the way windows locates and loads dlls, and it is a lot of work to do. (Note: it can be implemented with full backword compatibility, though)
"Third, it’s a fundamental part of the Windows platform value proposition that we fix problems in the platform for you. If there’s a bug in comctl32.dll, we fix it and we get the fix onto the user’s machine. If every app had its own static copy there would be no way to service it."
Maybe for some APIs but not all of them. When Microsoft fixes a bug or adds features, they don’t tend to put the fixes in the earlier versions. This leads to workarounds in the code if you care to target customers using these older platforms. Coding your own functions to emulate AlphaBlend and TransparentBlt for Windows 95 compatibility and to work around the memory leak in Windows 98 comes to mind. A lot of programs end up having a static copy of a function anyway.
I think this is a bit of an oversimplification. I’m usually the first one to say that users can’t read (not don’t, can’t). But that’s not really fair. The problem is more complex than this.
Why does the user read the "replace this existing file you saved with the new one you’re now trying to save" dialog, and not the "should I replace the newer file with this older one during this installation" dialog? It’s because they *care* about the first one. Additionally, it’s a choice where the 2 options are both entirely reasonable from the perspective of the user.
A user can *get* the fact that s/he might not want to overwrite an existing file with something they just created themselves (assuming they weren’t editing that very file, of course). It’s a valid question. Maybe they do, maybe they don’t. Both options are "right".
The *biggest* problem with the installer’s "replace newer file with old?" dialog was that the overall functionality was broken. It should have scanned *all* the files, and offered *1* choice, and that choice should be a real choice that the user might actually have an opinion about. In this particular example, it is *clearly* wrong for the user to say "yes" to one of these and "no" to another one. But is it wrong to ask them if they are sure they want to install an older driver package? I’m not so sure.
"This file or that file" isn’t something they will know how to answer, nor do they care. "You have newer version of this program already installed. Do you want to install this older version?" is not an unreasonable question. Better still, both answers lead to reasonable results. Even if a user always says yes or no, it won’t matter. If they say no, and they really did want the package, at least it will be clear what happened and they can run setup again. If they say yes and they didn’t want it, well they also ran the install program when they didn’t want it, so you’re no worse off than if you did it automatically.
Frankly, though, in many cases even that’s asking the wrong question. The true solution isn’t to figure out that answer without asking. The solution is to make it not matter. Shared DLLs were a clever idea in their day. They are an abomination now except when they are truly identical. No one cares if you waste a few meg of their $.10/GB hard disk. They don’t even care if you waste a bit of their memory. And they certainly won’t care if you waste a bit of the CPU. They care whether the machine works.
Thank you. This is the right thing to do. Part of a developer’s job is to *make reasonable decisions* instead of dumping that responsibility on the user. For the 1% of people who really wanted the alternate (probably wrong) versions of those files, do it yourself instead of inconveniencing the 99% of people who just want it to work.
krizstian, I have a pointer for your #3: If you have XP or 2003, open up c:/Windows/WinSxS, and look through the subfolders, or even check the very descriptive folder names. Somehow or another, probably some monumental software engineering, Windows now supports multiple dll versions simultaneously.
(btw, don’t ever get clever and delete the folder, figuring it’s just another dllcache. >_<)
Not that there’s much in there yet. Most apps and system support dlls still don’t use it; I don’t have a clue how to, but I haven’t researched it since I don’t put out shared system dlls. I hope Raymond or someone else here talks about it someday.
You have way to many vacations man..
same with path…why do software keeps changing their way of naming, for example
somecompagnie softwarethe best soft
in another software
somecompagnie software Incthe best soft2
again
some compagnie software Incthe best soft3
so the same compagny has 3 folders for himself
as well in registry as in program files
program files introduced someway of sorting your software so that you dont end up with lots of folder….
foxyshadis, that folder is, indeed, a way for you to specify that an app should use a specific version of a DLL. The functionality is called "side-by-side" or SxS for short, and was introduced in XP and Server03 as an answer to DLL Hell — but, as you correctly pointed out, nobody seems to want to use it :-
You enable it by creating an XML file for every DLL you want to use SxS with, and an XML file for every application that requires a specific version.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sbscs/setup/isolated_applications_and_side_by_side_assemblies_start_page.asp
An alternative which also works on 95/98/ME is using local isolation using .local files.
We very strongly recomment /against/ .local files at this time. The feature was developed when app compat issues dominated. Security and bug fixes dominate now and .local lets you escape bug fixes.
The sxs store is the beginnings of the preferred approach. (My team did this work for XP.) We’ll be moving the model forwards in Longhorn to bring some of the same values to non-sxs components and in a future OS to introduce a more full featured app model including robust deployment (my team also did the infrastructure for clickonce on Whidbey) and a usable shared component / servicing / versioning model.
The basic question of whether or not to replace an existing file caused additional problems because the question was broken in several ways.
1. If clearly worded, there are essentially two ways to ask this, "do you want to keep the existing file" or "do you want to install the file from whatever thing you’re installing now". Yes to one is the same as no to the other, and vice versa. In order to figure out the answer, you have to fully read the question AND know which file is newer AND know if you really want the newer one. Both in Japanese and in English I’ve seen the question asked both ways.
2. If the question is not clearly worded, it is impossible for the reader to figure out which of "yes" or "no" will get the newer file, and/or which file (the existing one or the one in the package being installed) is newer. For some reason I haven’t seen this level of impossibility in English language installations, but in Japanese there were cases when Japanese software engineers and I both together could not figure which answer would keep the newer file in place.
3. Sometimes the newer file is a different language version, and then sometimes it doesn’t matter whether you take it or not because you can’t get a file that’s compatible with another file you already accepted.
4. Sometimes there’s a "yes to all", sometimes there’s a "no to all", but I haven’t seen both. Both would be kind of useful. In cases where the user figures out the right answer is "yes to all" but the thing doesn’t offer a "yes to all", this is really frustrating.
5. If a driver gets broken by this, going to Windows Update is not a reliable way to fix it. Sure, some drivers from Windows Update really are fixes. If my experience is anything to go by, a majority are. Now, the difference between a majority and 100% makes the difference between unreliability and reliability.
Shared libraries are great.
But the way Windows handles them is weak. Version numbers are incorporated into filenames on a random basis (sometimes they are, sometimes they aren’t, no rhyme or reason to it).
Unix has got this right; it handles multiple versions cleanly and effectively.
Windows doesn’t, and uses extraordinarily complicated things like SxS to try to remedy the situation.
Windows could, and should, use the Unix model.
DrPizza: There are serious problems with the Unix model, too, though. Symbol names are not resolved to libraries at static link time, so it is entirely possible for symbol names to clash and to be resolved unpredictably at dynamic link time. (This also makes dynamic linking relatively slow, especially for C++ programs.) This can be avoided by using versioned symbols and being selective in the use of RTLD_GLOBAL, but that currently takes a lot of effort so it isn’t done as a matter of course.
The UNIX shared library thing, from what I could see as someone who toyed far too briefly with developing apps for Unix, seems to not be enforced or enabled in any way by the OS. It seems to be rather a purely voluntary standard adhered to by most Unix developers.
Well, the general principle behind it seemed rather easy for any Win32 vendor to implement should they choose to do so as a means to version their own dlls.
It seemed in practice to be essentially the same way COM objects are versioned – which seemto offer the same – link to explicit or latest version type functionality.
When I was at Nebraska (2001-2002), I met someone who worked in the computer equipment department.
One day he came into possession of a broken monitor. He wrote on the screen in permanent marker: "BAD"
A few days later someone else in the department had apparently plugged in and attempted to turn on the monitor, and asked why the word "BAD" was written on it.
This happened several times, until finally my friend became annoyed and thought up a solution.
The monitor, when he was done with it, said "NAZI BAD" on it.
Nobody ever asked again about that monitor.
Vorn
Yes, well, I wasn’t sufficiently clear about my dislike for simple shared DLLs, since I was more talking about the underlying issue of making things work rather than asking the user.
Anyway, to be more clear: unversioned shared DLLs are an abomination. COM is a step in the right direction, but Microsoft put so much other garbage into that model that it’s a bloated hard to use mess.
These days, processors are fast enough that you could even get away with them all being out-of-process, which would isolate them even more and lead to fewer bugs of the shared-memory-vs-thread-local-storage type and vastly simplify the apartment threading models (like, get rid of them).
But the way things actually played out, COM turned into a monster. A really simple versioning mechanism layered on top of a pure interface DLL would be a beautiful thing.
Put every component in its own address space? The marshaling requirements would be outrageous. People barely understand how to author communications protocols when they realize it’s a communications protocol let alone when it’s "just an API".
The problem isn’t that you just want to isolate each component, but rather that you want isolated stacks of components (I’d call these entities "applications").
Working out how you have a valuable platform (and possibly more importantly, a platform for others to write valuable platforms on because in the platform biz it’s all about client adoption) while providing the right balance between innovation, support costs, compatibility costs, etc. is not trivial. Working this issue out in an economic context is absolutely vital to our business however so you can be sure we’ll be looking for the simplest solution which meets the requirements.
Chris Becke: Regarding UNIX .so versioning, it’s semi-voluntary and does have OS support. I’ll attempt to explain in more detail, but I’m far from an expert on the matter so authorative sources should be consulted for details.
Nothing stops a library developer from releasing every version of their library as ‘libblah.so.0’ . They’re not forced to version the library soname.
In practice, it’s rare to see unversioned libraries at least on the open source *nix side of things. Most library maintainers seem to increment the soname (library version number) sensibly, so when they break compatibility they release ‘libblah.so.1’, etc. More minor changes are generally indicated by a more specific version on the soname, eg ‘libblah.so.1.2’ .
The versioning scheme does rely on the library maintainer to properly increment the soname when releasing incompatible changes.
The dynamic linker supports this scheme by permitting applications to choose how specific they wish to be about library versions and automatically locating a matching library.
If I have an application that links against ‘libblah.so.0’, ld.so will correctly link it to ‘libblah.so.0.1.2.3’ but will refuse to link it to ‘libblah.so.1’ . Another application might know that it requires exactly ‘libblah.so.0.1’ and can specify this. Unfortunately, I don’t think it is possible for an application to specify that it requires ‘libblah.so.0.2’ but permit its self to be linked to ‘libblah.so.0.3’ or greater.
This mechanism makes it possible for libblah.so.0 and libblah.so.1 to be installed at the same time, and for applications linked against both to load and run without conflicts. Both can be in the same directory – there is no need for tricks with dynamic linker search paths.
Unfortunately, this scheme does not usually cover symbol versioning. Witness the horror that is Berkley DB on UNIX. It is not uncommon for an application to require a newer version of Berkley DB than is shipped with the system. This works fine, and both the old and new versions can be in use at the same time. Problems appear when the app that requires the newer Berkley DB links to a system library that in turn links to the older Berkley DB. *boom*.
This issue can be worked around with symbol versioning, but few libraries seem to bother with it. It would be nice if symbol versioning was handled more automatically by the compiler, linker, and dynamic linker. Of course, that’s just my opinion as a sysadmin and beginner programmer who’s had to deal with Berkley DB conflicts far too many times.
As a mostly-UNIX user who deals with Windows at times (and is delighted to see how much nicer it’s becoming), I’ve always been puzzled by the lack of DLL versioning. The UNIX approach is far from perfect, but if it was extended to cover symbol versioning and supported by tools to help detect things like incompatible function prototype changes, it could be very interesting indeed. Windows also has standard ways of storing metadata within executables, so it wouldn’t be forced to use simple filename tricks for versioning.
The day I can see an application installing DLL files into the system directories without a twinge of "will my system boot tomorrow" horror, I’ll be awfully happy.
Of course, any versioning scheme probably couldn’t help older apps, so it’d take quite some time to see the benefits. Oh well – better long term and done right than short term and ugly.
Way I figure it, the best way to ask the user a question like this is this:
"Windows has detected that the following DLLs are already installed with newer versions than the ones on the setup CD. It is generally a good idea to let newer versions stay; however, you may wish to use the older version for some of them (for instance, unstable or compromised DLLs should be replaced with the older versions). Please check the DLLs you want to use the older version of, and then hit ‘OK’."
Followed by a list of DLLs that you can check (like IE’s advanced preferences pane), with none of them checked.
Vorn
Like any normal human being is going to read a dialog box the size of "War and Peace"…
Better than asking over and over about DLLs that the user doesn’t know the name of.
Vorn
Vorn, how does asking a user about a whole list of DLLs they don’t know about, and presenting them with a long intimidating list, come out better than asking them about each individual one.
If I don’t understand the question (and we can be sure that many users don’t) then I can’t provide a useful answer either way.
Simple: My way actually gives experts all the details they need, recommends a default course of action, prevents absurd repetition, and gives enough information that anyone can act on it. From what I can tell, half the problem with asking, originally, is that it didn’t give any actual information (no DLL name…) so it was just "Oh, Windows is being stupid and repetitious." Which isn’t a nice thing to have happen.
The point is this: certainly, a novice computer user doesn’t need this kind of information; a short summary will do. For the expert, on the other hand, the ability to go in there and choose specific files to overwrite comes in mighty handy. The problem with the original setup method was, at least in part, that each DLL replacement dialog came with no actual information. The user, whether expert or novice, has no clue what is being replaced, or if the setup has fallen into an infinite loop. The solution, then, is to create a single dialog (so we only see it once on a reinstall and never get worried that we may have broken the installer) that describes the problem (so we know what the machine is trying to do) and gives information that allows people who have some idea as to what’s going on the ability to make a decision.
A useful example in this is the configuration program that comes with an installation of perl: it asks specific questions, describes what the answers are used for, provides a default (often gleaned from system environment information), and explains clearly conditions (that it generally can’t determine itself) that would cause the default to be inappropriate.
Vorn
"the problem is that the user doesn’t have the background knowledge to make an informed decision"
Then give it to him, right in the dialog.
Also you must be talking about a different dialog than I am – the last time I saw one it didn’t tell me what it was trying to replace… which is extremely aggravating – I didn’t know if it was trying to deal with kernel32.dll or lookashinydllthatdoesshinythings.dll .
Old MacOS had enough of a problem with that sort of thing that people use it as a common complaint. Eric Raymond talks about it, too, in that horror story involving CUPS, so it’s not constrained to there, either.
Also I’m aiming those blahs at the expert user, not the one that doesn’t have a clue, because I know that the one who doesn’t have a clue isn’t going to read them. Also also good UI design puts the action to be performed on the button: "replace the new files with the old ones (recommended)" (default) "don’t replace" so that you can’t pick a button without reading them, but also have a good idea of what it wants you to do. Also also also this is what the "more details" button is for.
Vorn
"Then give it to him, right in the dialog."
That’s just shouting louder.
The point is that the user doesn’t WANT to learn. They just want to surf the web and send email to their grandchildren. Whatever you put in the dialog, they simply won’t read it. And if the dialog box has multiple buttons, users will pick them randomly in the hopes of making the dialogs go away.
Even people like you and me, the propeller heads, don’t necessarily have enough information to know whether we should keep version 4.12.5.101 of nv4vb9.dll or downgrade it to 4.12.4.8.
The dialog might as well read:
I can’t figure out what is wrong. If you answer "Yes" below, your app might work but it might be that no other apps work including explorer and login. If you answer "no" below, your app probably won’t work.
Yes / No / [Cancel]
(one of those situations where Cancel should be the default…)
This is just because software deployment sucks today. Simplistic answers work for simplistic situations which isn’t what happens on real world consumer machines. At the end of the day all the authenticode etc. dialogs might as well be rolled into a single one:
—
Do you want:
a) that app you just downloaded or bought to work or
b) your system to keep working
a / [b]
—
All the information you describe and more was given in the file conflict dialog. The problem isn’t that the user wasn’t given enough information. The problem is that the user *doesn’t have the background knowledge* to make an informed decision.
To a user, the dialog looks like this:
A problem blah blah blah blah blah.
File: blahblah blah
Description: blah blah blah
blah version: blah blah blah
blah blah: blah blah
blah blah: blah blah
blah blah: blah blah
If you blah blah blah blah blah blah blah blah. Otherwise blah blah blah blah.
Yes, No, Yes to All, Cancel
Making the dialog longer just increases the number of blahs. It’s like trying to communicate with someone who doesn’t speak your language by repeating yourself louder and more slowly.
okay, you win. The question shouldn’t be asked.
If the question DOES need to be asked, however, I think a list is far preferable to asking essentially the same question over and over and over.
Vorn
I don’t think asking the question over and over is a good model at all. If you want to call that the worst option out of the list of possible compromises then I’ll agree with you.
Users don’t read dialogue boxes, users don’t want to learn how a computer works, and "technical people" are very much in the minority.
And if they answer the question wrong they’ll consider it your fault for asking it no matter what.
You don’t necessarily have to make the dialog complicated. The dialog could say e.g. 17 files were newer on your system .. And present three options Keep/Replace/More details (Advanced) .. If you indicate which of keep/replace was recommended and keep the long list off the screen you
1. Don’t have people picking ‘keep’ to some files and ‘replace’ for other files solely due to repetitious dialog fatigue
2. You give more information to the user about what is happening, and optionally more control if they need to take advantage of the flexibility (without overwhelming people that aren’t interested) .. The ‘more options’ type of expanding dialog is used in other places, seems like it might be appropriate here.