As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I keep hearing about DLL hell - what is this all about?
It's when Application A installs a Shared DLL v1.0, Application B comes and updates the Shared DLL to v1.1 which should be compatible but there are slightly different behaviors, then App A stops working correctly and reinstalls v1.0 then App B stops working ... now imagine this with more than 2 apps let's say a dozen: DLL Hell.
DLL hell was mostly from the COM days, where a COM dll had to be registered, and clients of it would look it up in the registry. It was a nightmare because the filesystem (*.dll, *.ocx) could be modified leaving obsolete entries in the registry. Apps would stop working, it was horrible.
You'd then get the scenario where a new app installs and registers a new version of the DLL, thus breaking apps that really wanted the old version. You'd reinstall the old app, and break the new one in the process.
With .NET, there's no need to register the DLLs (the GAC is a special case, and has provision to avoid the versioning issue described above), the loader just picks up assemblies by looking in the correct paths.
In a nutshell in the good old COM days each COM component had to be registered (an entry was created in the registry) before it was used. Then your program would create a new object by supplying the type name (which was a key in the registry). And now you didn't have any control over which dll would really be loaded, would any other software register some newer/older/completely different version of this dll, etc.
Simple - in previous versions of windows, it was possible to have multiple applications all trying to access the same shared library. No problem there, that's why they are shared. the problem comes when different apps were trying to access different versions of the same assembly from a central location. Providing all the later versions of the dll are backward-compatible, and that you have the latest version there should be no problem, but if you install an app that requires v2, and then install and app that requires (and includes) version 1.x, you may find the first app stops working (because the v2 dll has been overwritten with v1.x).
Recent versions of windows are capable of storing multiple versions of a dll, and supplying the correct one on request.
It happens when an application installs a dll into the system, and another application replaces it with another version of the dll which is not compatible with the older one.
It is not a problem in c# (and .NET in general) because .NET assemblies are smart enough to be version-aware (and .NET has the GAC which manages different versions).
Related
I am am considering installing a dll assembly in the GAC and I don't have enough experience to know if this is the best practice for this scenario. Hopefully someone here can shed some light on me and get me pointed in the right direction.
The Scenario:
I have a library assembly that I have written. This DLL is designed to read some data from an output file of a third party software package. Once read the data is available for access to the caller of this DLL.
My company has developed four different windows form applications that use this library file to get data into the apps.
The 3rd party software manufacture has change the the way they write their output file, so I have modified my DLL to support the new features the third party is using.
Currently all the apps have been written using the dll as a private assembly.
The Update:
To update all of the applications would require a rebuild of all four apps referencing the updated dll file, then reinstall all four apps on every machine that may be running them.
If I were to change the dll to a GAC assembly, then all I would have to do is reinstall the updated dll in the GAC assemble on every machine that uses the DLL assembly.
The later option seems to be simpler, then the next time this happens, we just update the one dll in the GAC and away we go.
The Question
What is the best practice here?
This link makes me think I should not be thinking about GAC
When should I deploy my assemblies into the GAC?
And if GAC is the answer how do you go about deploying the strong named assembly so that is installed in the GAC from the setup file?
Any help is appreciated,
Mike
I created a WiX-based installer back in the WiX 3.5 days. The documentation then was even worse than it is now. To make matters worse, it was my first installer—so I didn't do everything right.
Some background: the installer installed two applications and a driver (each of these were a separate feature consisting of one or more components). One of the applications in question is a vendor-proprietary device configuration application written in VB6. Since it's a VB6 application, it uses the libraries comctl32.ocx and tabctl32.ocx.
The crux of the problem is that I didn't see these two libraries in the %windir%\System32 folder on Windows Vista (and/or Windows XP? I don't remember, it's been years since I first wrote this installer). So I thought I needed to install these two libraries along with all of their requisite COM registry entries. (I ended up installing the COM libraries in my application's folder—as you would for a private assembly, but registered them globally in HKLM.) As much as I read about things when creating the first installer, I never once came across the fact that, as of Windows XP, COM components could be installed side-by-side. (And even so, why didn't I use the MSI tables Clsid, ProgId, etc.—which granted, today, is frowned upon, but it would at least have been more correct than what I did? But I digress; what's done is done in MSI land.) Anyway, when creating the original installer, I used the following WiX markup for creating the COM registry values:
<RegistryValue ... Action="write" />
I also should mention that at the time, I had not come across any sort of 'Component Rules 101' kind of documentation as I have this time around. So, this MSI does not follow the component rules. The MSI contained one component for each COM library and its associated registry values with the COM library being the KeyPath of its component.
The question is, if the registry keys/values existed prior to my original MSI running and installing the first version of my product, will uninstallation cause these keys/values to be removed from the system? (I assume these keys/values were created during Windows setup—so are they already reference counted?) I don't want to possibly break other applications on a users' system that relies on those libraries.
If the answer to the above is yes, then my current plan to rectify the situation is:
Author a new MSI as a <MajorUpgrade />—afterall, I am performing an upgrade.
Provide the COM registry entries that were in the original installer for the comctl32.ocx and tabctl32.ocx COM libraries—I'm guessing that I would need to do this with a CA (or multiple CA's) so that they don't get removed again on the next upgrade. I see one of two ways of accomplishing this:
Directly create the registry entries taking care to ensure the values match those of a fresh windows installation (appropriate to the version of OS on which the installer is executing)
Dynamically add the registry entries to be created to the MSI Registry table (which if I understand correctly, isn't tracked by windows installer in terms of uninstallation?)
If previously existing registry keys overwritten by MSI are removed on uninstallation, then:
Is my proposed solution acceptable?
Which of the two options for replacing the removed registry entries is best?
If neither of those two options are acceptable, does anyone have any other suggestions on how I might rectify the situation so as not to break other applications that (may) rely on the libraries in question?
It was a long read but I think this is what you are looking for:
ICE09
To quote the beer commercials.... I don't always install files in the SystemFolder but when I do, I make them permanent.
First, thanks to Christopher Painter above for responding to my question; though, it's not really an answer in the sense that I'm looking for—fixing an existing installer that's "out in the wild". Though, in his last comment about a minor upgrade, that might work for some people.
Next, thanks to Aaron Stebner who responded to my e-mail requesting guidance on this same issue. His advice is to author a MSI component which has no ID. By authoring such a component into a MSI, the component is not tracked by MSI; essentially, it becomes a permanent, uninstallable component. This might work in this situation, if it were completely necessary.
However, after doing some research, I believe that there isn't much risk to damaging a user's system by removing the registry entries I outlined above.
I loaded a fresh copy of Windows XP SP3 and Windows Vista SP1 into a virtual machine. Out of the box, neither of these versions of Windows have the COM components in question registered in anyway in the Windows registry. This makes sense, since from Windows XP onward, there has been registry-free COM registration. This also continues to be the case for Windows 8.1—again, this was expected.
The worst that could happen if these registry keys are uninstalled is that some other older piece of software on a machine that relied on such registry entries could end up broken (e.g. this software is from the late-90's to early 2000's era and used a non-MSI installer and/or installed the COM libraries globally—which they shouldn't have done in the first place—just like I shouldn't have done in the first place ;) ). At that point, the user can either re-register the COM libraries using regsvr32.exe or repair/reinstall the application in question. The likelihood of such applications existing are slim to none in this day and age.
I'm not very experienced with deploying applications and i'm having an issue with my very small screen scrape application.
I use a project that handles all screen scrapes and i just call the functions from the dll(on dev machines at least). When i reference that dll from the directory, it works fine on my machine but installing and launching on another machine without the project crashes it immediately when it tries to access the class to instantiate the screen scrape object.
Perhaps my assumption of dll is incorrect but doesn't having the dll mean it incapsulates all the classes/references/etc in that project so it can be used elswhere without having to lug the whole project with it?
What could be going on with this dll?
The dll assembly encapsulates the project, but not its references. Anything that the project needs to reference must be available in the new environment as well, whether in the GAC (global assembly cache), the local directory, in a reference path, or wherever.
If you are using Visual Studio 2010 or earlier, you can use Setup Projects to nicely gather all necessary references and package them into an install package for you. There may still be complications that you will need to troubleshoot sometimes, but it simplifies your deployment effort. In Visual Studio 2012 and later, Setup Projects were dropped, but there are other options, like WIX and Install Shield. And that is a whole other topic with plenty of Q&A on this site.
I have a project done in VB.NET and I want to publish it for distribution. I know that when I build solution It creates an .Exe. But that requires local resorouces. If I build for release I know it works but it still needs the .Net platform installed. Is there anyway to make a true standalone .exe or something that would run on a persons computer if they do not have .NET installed. Also the ClickOnce application thing is not a wanted Solution.
Is there any converter program that can do this for me?
The .NET framework represents the basic prerequisite to run a .NET program; equivalently than having Windows installed is the prerequisite to run a Windows program. Bear in mind that any Windows version includes the .NET framework (and, actually, it tends to involve top-priority updates and thus are automatically perfomed by Windows Update in many cases). A big proportion of the programs running on Windows created during the last 10 years are built on the .NET framework; a relevant proportion of the sites (like this one, for instance) are built on ASP.NET and thus the given server has to include the .NET framework. If overall compatility is a concern for you, you might rely on a-bit-old .NET version: the latest one in VS 2010 (4.0) should be fine for most of modern computers; but you can even rely on the previous one (3.5) to be completely sure. Lastly, bear in mind that a .NET program can also be run under a OS other than Windows (Linux or MacOS, for example); although, from my past experiences, these are not too reliable situations. Nonetheless, in case of being interested in other OS, you should do some research/testing on this front to see if the available options offer what you are looking for.
SUMMARY: the exe file generated by the Visual Studio is actually what you call "standalone .exe". One of its defining features is the .NET version (which can be changed in the Project Settings); a program can only be run on computers with a .NET framework (or equivalent) equal or newer than the one on which it was built. The 4.0 version should be OK for most of new/properly-updated computers; the 3.5 .NET would work with virtually any computer (although, logically, it includes less features than the 4.0 one).
---------------------------- UPDATE AFTER COMMENTS --------------------
From some comments, I have undertood that my statement wasn't as clear as I thought and this is the reason for this update
.NET is pre-installed in Windows only since Vista. XP does not include the .NET runtime by default. The reason for not having mentioned this issue in my answer was that having a XP Windows without .NET is highly unlikely. Firstly because this is a top-priority, automatic update and thus one of the first times the computer is connected to internet "Windows Update" will take care of this. And secondly because this is the basic framework for any Microsoft programming over the last 10 years and thus a Windows computer not having it will not be able to run almost anything. With this last sentence, I don't mind that most of the programs are built on .NET, but that for a Windows-based environment most of nowadays basic requirements do include .NET.
It was also pointed out that there is some compatibility problems between different .NET versions (that various side-by-side versions were required). The basic Microsoft approach to the different .NET versions is backwards compatibility, what means that a given .NET version can run any program built with that version or older. This is theoretically right, but not always right in fact. My approach to this problem is relying on a bit old .NET version (3.5) and not using too new/untested features (e.g., WPF). If you want a for-sure overall compatible program you should work quite a lot on this front (compatibility between versions is one of most typical problem of any programming platform), instead expecting Microsoft to take care of everything. Thus, in principle, just one .NET version (the last one) has to be installed (which, on the other hand, is not the case for a big proportion of computers; for example: computer including the 3.5 version being updated, over the years, to 4.0 and 4.5 by maintaining the previous versions).
Lastly, I want to highlight that my intention with this answer is not defending any programming approach over any other one; I am just describing what is there from the point of view of your question "can I remove the .NET part?" -> no, you cannot; there is no (sensible) way to do that. If you want to rely on a different programming platform you should get informed about it (I am sure that Camilo Martin will be more than happy to help you on this front). If you prefer to rely on .NET, be sure that you can generate an overall compatible program (to be run on Windows).
Easy way to convert in .exe in VB.NET-2010:
Create New Project
Select Windows Application And Save Proper Path
Comple Project then Select File-> Save All
Select Build->Start Build
Your Project .exe Created Your Project Save Path:
Select Windows Application 1
Select bin Folder
Select Debug Folder
And in Debug folder your .exe File is ready.
Quick Basic once made and executable (.exe) directly form their VB code, but I wouldn't recommend converting to Quick Basic. You can look at Mono to see if they have anything yet. (mono allows you to use compiled vb.net in other operating systems).
Ezirit Reactor makes a single executable, but it's not free.
You can bundle .NET Framework into your distribution so that users don't have download it.
Why do you need an executable (.exe)? If the reason is for security and to minimize chances of reverse engineering, then get a good obfuscator.
One of our applications needs to register a COM control during installation. If a newer version of that control is already registered, we don't want to overwrite it with the older. What are the Windows MSI install conditions I would user to control this? Or is there some other 'best-practice' method I'm not aware of?
Thanks
Sounds like your main problem is that you have two controls that support the same CoClass's, but live in different file paths. That's not a great situation to be in. If at all possible, there should only be one possible file path for a binary that implements a particular COM class.
That way, file versioning rules will make sure that the latest file is installed by MSI installers. MSI won't by default overwrite newer file versions with older ones.
There are applications out there that have the problem that customers need to use the older version of a class occasionally while still having the newer version installed and available. One solution is to have a utility application that the customers can run that will "point" the COM registry entries to the correct binary.
There are definitely permissions issues with implementing that correctly on non-administrative accounts and you should avoid putting yourself in that situation if at all possible.
If you absolutely must have multiple binaries implementing the same COM CoClass GUID and if it is not too late to change old clients, you could create a master "factory" class that takes whatever data/info is available from the client and chooses the correct implementation to return. It would simply be a COM class with an interface that had methods that returned interface pointers to the actual interface the clients needs after allocating the proper implementation class and queryinterfacing for the client interface.
edit
You may choose to change the location of your application from version to version (e.g. "c:\program files\My App V2". That's okay so long as you use the MSI product code and version #, etc. attributes of your packages to force MSI to uninstall any existing versions of your application before installing new ones.
What you are missing here is merge-modules. Basicly you create a merge-module for your COMxx component. This gets recompiled with each new version 19, 20, 21, ... of your component (but keeps its GUID). Both your applications "reference" this COMxx merge-module and ship its content to the user.
This way windows installer will make sure your dll is refcounted and upgraded only if needed, provided you maintain (increase) version info in your dll.
Edit: The merge-module also hard codes install path, which usually ends up somewhere in C:\Program Files\Common Files\{My Company}\{My Component}, both applications ship it there.