Help with ActiveX Install? Merge Modules - Windows Vista and Windows 7 - dll

I'm building an ActiveX control installer in VS2008 which uses both the CRT and MFC merge modules to install. When my control tries to register on Windows 7 it fails.
Dependency Walker says I'm missing the mfc90u.dll, msvcr90.dll and msvcp90.dll dependencies when trying to register my control and the install fails. Are the merge modules supposed to take care of this? My output OCX is being registered with the vsdrpCOMSelfReg option. From what I am reading on other forums, this might not be the best method, what should I try at this point?
Install works fine on Windows XP.
Update 4/8/2010:
Changed to vsdrpCOM and the install gets through (no surprise), however, msvcr90.dll isn't being found afterwards. I thought this was handled by the merge module for CRT (microsoft_vc90_crt_x86.msm)? On Windows XP, Dependency Walker finds it in Windows/System32, not in the SxS folder like I expected. On Windows 7 it just doesn't find it at all. Should I be putting the msvcr90.dll into Windows/System32 myself? It doesn't seem like it.
Update 4/20/2010:
Well it seems as though Dependency Walker finds msvcr90.dll at the top level dependency of the control itself, although msvcp90.dll and mfc90u.dll both have implicit/forwarded dependencies on msvcr90.dll as well and those couldn't be resolved in the Dependency Walker. The control, however, registers fine and runs loading those libraries. Is this something that can be ignored?

The two modules you need are:
- Microsoft_VC90_MFC_x86.msm
- Microsoft_VC90_CRT_x86.msm
For a 64-bit app you should be using
- Microsoft_VC90_MFC_x86_64.msm
- Microsoft_VC90_CRT_x86_64.msm
Unfortunately self-registration causes a lot of problems, what you should do is add the required registry entries manually into the setup project. (The 'heat' tool from WiX provides a really easy way to capture this information, although if you wrote the DLL you should know the required entries already). The real problem with self-registration is that if it fails, then the setup dies. The most obvious problem is that if your DLL requires additional modules to successfully complete self-registration and they're being installed at the same time you can't guarantee that the system will find them present for self-registration to complete.

Related

How to express a file dependency using WiX

I have a couple of MSI files installing different applications. All these packages share the same underlying runtime which basically is a set of DLLs. This runtime is pulled in each of the installers as a merge module. Installing a couple of these packages works just fine, always the latest version of the runtime stays on the system and when the last package is removed everything is removed from the system.
Now I had to split one of the DLLs into 2 and added a new component to the runtime installing the new DLL. This new DLL is linked with other libs of the runtime. Now assume the following scenario:
install an old package with the merge module for the runtime without the new DLL
install a new different package with a newer version of the merge module for the runtime. Now there are 2 packages on the system
remove the new package again
Now the old package is broken because:
the new component for the new DLL had a reference count of one as the old package didn't have it and therefore gets removed
the other runtime DLLs stay on the system because they are still referenced by the older package. However as they are new they are already linked with the new DLL that is now no longer present
So my question is:
Is there either a way to explicitly state in the WiX code that file A depends on file B so that it stays on the system until all references have been uninstalled?
or is there a way to explicitly downgrade the dependees in a way the dependency does not longer exists?
Am I doing something fundamentally wrong?
What I did try on a clean machine was to follow Stein Åsmul suggestion like this:
<Component Id='OldLibsNowDependingOnNewLib' Guid='C8DCD2AB-CBE5-4853-9B25-9D6FE1F678DD'>
<File Id='LibOne' Name='LibOne.dll' Source='$(var.SourceDir)/LibOne.dll' />
<File Id='LibTwo' Name='LibTwo.dll' Source='$(var.SourceDir)/LibTwo.dll' />
</Component>
<Component Id='NewLibComponent' Guid='CD2DB93D-1952-4788-A537-CE5FFDE5F0C8' Shared='yes'>
<File Id='LibNew' Name='LibNew.dll' Source='$(var.SourceDir)/LibNew.dll' />
</Component>
However unfortunately this doesn't change the behaviour.
UPDATE: Looking in the SDK again, I see the flag msidbComponentAttributesShared for components. This
looks promising for the problem you describe. Please try to enable
this flag and recompile the version 2 of your setup (unless it is
live).
Enable the Shared flag for the component in question (last part):
<Component Feature="Product" Shared="yes">
This seems to be for patch support, but maybe it will work for your case too. From the MSI SDK:
"If a component is marked with this attribute value in at least one package installed on the system, the installer treats the component as marked in all packages. If a package that shares the marked component is uninstalled, Windows Installer 4.5 can continue to share the highest version of the component on the system, even if that highest version was installed by the package that is being uninstalled."
I think the above should work, but don't have time to test right now. Leaving the below for review.
Short Answer: Use WiX's Burn (setup chainer) to install in sequence the application setup and a new, separate runtime setup that can be handled
independently of your application setup versions.
Prerequisite Setup: Interesting case. This is why I like to split prerequisites into its own MSI package and deploy it via a Burn Bundle Bootstrapper. Burn is WiX's bootstrapper / downloader / chainer - essentially a way to run several setups in sequence - in a few different formats such as MSI, EXE, MSU, MSP. When doing this - putting the runtime in its own MSI - there are no entanglements and you get good decoupling of your runtime and application-specific files. In other words: you can update the runtime files on its own - with their own MSI. The files will even have a reference count of 1 meaning you can easily uninstall them all (not if you install via a merge module that also can be included in other packages - more below).
Merge Modules - Semi-Static Linking?: In a weird way merge modules are sort of semi-static linking. The whole merge module is a version - a binary bundle (think COM) - but its installation behavior is one of "higher version wins" only. Hence a single newer MSI with the newest merge module in it will update the shared files for all applications that use them. Uninstalling will then do what you see: preserve the files that were originally installed by older setups.
Options: One "solution" in your case could be to re-compile the older setup with the newer merge module and then reistall, which I understand you don't like. I don't like it either. I guess it is no solution at all. Some other suggestions:
Permanent component: You can set the hosting component for the new file to be permanent on the system. This is very easy, but also quite silly and not always very desirable. Uninstall will then not remove the file at all.
Prerequisite: This is my favorite option mentioned above. You compile a prerequisite MSI setup that installs the runtime components. This MSI can deliver updates to itself without affecting the main application. This is the primary benefit I am after: Cohesion & Coupling benefits.
Merge Modules: I would avoid merge modules altogether, but it is common to merge the same merge module into the prerequisite setup - if you have a merge module already.
In most cases merging a merge module is fine since you then install the prerequisite and then you can install and uninstall application versions at will without affecting the runtime since a different product (prerequisite MSI) installed the runtime - and that setup should stay behind and not be uninstalled.
If the merge module does not work and brings along the conflict that you already had, maybe try to combine with the msidbComponentAttributesShared "solution" mentioned above. Not tested by me so far. Always risky to suggest things like this, but it is "best effort".
WiX Include Files: I prefer to use WiX include files which allows me to pull in new files without re-authoring a whole merge module in binary format (think C++ include files as opposed to a merge module's COM-style binary reuse).
Side-By-Side: Many people prefer to install prerequisites side-by-side so that several versions of the runtime can co-exist. This may or may not involve the GAC. Switching runtime versions would then be a manifest-manipulation task. Generally somewhat confusing, but doable. You can use both merge modules and separate MSI files to deploy such runtimes - as described above. I would definitely use a prerequisite MSI.
I can't think of more right now, but I know I have forgotten something important this time. Let me persist what I have for now in case it sparks ideas for you.
Cumbersome Prerequisite Setups: Note that prerequisite MSI files are not so bad for corporate deployment since deployment systems will allow one to define relationships between MSI files and to set up deployment chains. For home users you can easily wrap everything in a large setup.exe.
Nonsense Options: Options that don't make sense would be to roll the new file into both setup versions. No gain, lots of overhead. Some people like to copy new files locally to the main installation folder. Does not work since the files it is linked to are likely elsewhere (runtime location). Static linking wouldn't be relevant in this case I think. Only as a last resort to solve a live problem I guess. Setting the SharedDllRefCounter flag will not affect MSI reference counting, it is for legacy reference counting (non-MSI setups), though tweaking this manually is an emergency "solution". The last resort people end up with is typically to abandon the runtime installation and install everything to the same installation folder. Then you have to always recompile everything for every release - which is what you want to avoid?
Some Links:
WiX (Windows Installer Xml), Create universal variables
Pre-Processor constructs, features, Burn Bundles and beyond

How to create a registration-free installer with WiX (manifest-based)

I'd like to create an installer package to install registration-free COM components (with manifest files included). This would be more or less a self-extracting archive to place some files in a target directory given as commandline argument, but it would also need to check or install some other redistributables like VC++ or DirectX.
The package is supposed to be used in another applications's installer as some kind of redistributable package itself. It should not be registered in the "Program and Features" dialog of Windows but has to be removed with the application. Ideally there should be no changes to the Windows registry.
So far I haven't been very successful. Can anyone please provide me with some hints regarding this use case?
You've got about a dozen different questions in that one question. Start with just creating a simple MSI that successfully installs your files and your manifest. Create a COM client to test it. You can also put AppSearch and LaunchConditions in your MSI to detect your dependencies and not allow installation if they are missing.
That's about all you should have to do for this simple question. As for the other questions.... if you are a redistributable and someone else is silently installing you then it's their job to handle the installation of the other redistributables. Also if they don't want you listed in Programs and Features they can pass the ARPSYSTEMCOMPONENT=1 to your installer and you won't be listed. If they want to uninstall you when they uninstall themselves, that's their problem not yours.
If you are really creating a redistributable to be used by other products, sometimes a merge module is the appropriate solution. They build their MSI files and include your merge module.
Otherwise, reg-free COM is in theory an easy install because you're just installing manifest files and Dlls etc. However I don't understand how that could be used by other apps because (IIRC) a client app exe needs your manifest and Dll in their install folder, so how can they do that when they are not installed yet? Or even if they are installed how can you find them? So that goes back to the merge module idea so they include your merge module and install an exe, your manifest and your Dll in the same location. When they uninstall so do your files.

LoadLibrary project.dll failed. The specified module could not be found

When I try to register the 32 bit version of my C++ / ATL project with
regsvr32 project.dll
i'm getting this error:
LoadLibrary("project.dll") failed - The specified module could not be found
project.dll is my dll built using ATL on Visual Studio 10.
The 64 bit version registered fine.
What am I missing?
I have observed this exact same error, but the solution was not installing the redistributable. All the dependent DLLs were present on the system1 according to depends.exe.
In my case, the icon of KERNEL32.DLL was slightly red tinted. Depends.exe did not offer much explanation, but digging around revealed that one of the imported functions were missing from the DLL on the system. To see the imported functions, select the dependent DLL in the treeview and look for the import on the right panel. Order by the PI column to see the red icons of missing imports.
In my case, the missing function was a function that did not exist on my sad target operating system, Windows XP. Since my program did not directly depend on this function, I was able to get away with #defineing the following in my project:
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
Compiling with these macros made it so the function in question was not declared in the headers, and consequently not imported at load-time. Now I was able to use regsvr32. This of course is a very specific (and lucky) case. I did not depend on that import or any other newer APIs, so I could get away with retargeting the project. Were it not a system DLL, I would have needed to find a newer version which could easily lead to a need to update a whole sub-tree of the dependency graph. Or even worse, if I depended on the missing imports, some serious refactoring would be needed.
To sum it up, this error message2 can be caused by the following issues:
The DLL file was not found or could not be read. Check the command line.
Some dependent DLLs were not found or could not be read.
Some imports are missing from some dependent DLLs. If these are system DLLs, you are likely targeting a wrong version of Windows. If these are non-system DLLs, you need to install newer versions of them and all their dependencies.
1.: Apart from IESHIMS.DLL and WER.DLL which is apparently a bug in this old tool.2.: Or really, any problems in loading the DLLs on a particular system
The error description is misleading in this case. The system finds your DLL (project.dll) but one (or more) dependency of your DLL might be missing.
I just installed
Microsoft Visual C++ 2010 Redistributable Package
and now I can install the dll.
Although this works, I'm not too happy with this, because I don't want to have to install this package on a client in order for my dll to work by them.

Installer fails with "failed to register" error for certain DLLs

I developped a vb6 program then I build an installation wizard with visual studio interdev.
I used "dependency walker" and "process explorer" to find out the missing DLLs but there is always a problem with :
IESHIMS.DLL
WER.DLL
MPR.DLL
These dlls shown by dependency walker.
And when installing the program on another machine I have these error messages :
uxtheme.dll failed to register
msdatsrc.tlb failed to register etc..
PS : no problem on a machine where visual studio is installed.
Any Idea to fix this issue?
Thanks
Dependency Walker is not an appropriate tool to troubleshoot VB6 dependencies. It works well enough for DLLs written in C or C++ that use implicit dependencies. Although it hasn't kept up with the times and has trouble with DLLs that are stored in the Windows side-by-side cache or are delay loaded. Delay loading is what generates the warnings on ieshims.dll et al.
VB6 uses COM, which loads DLLs dynamically with LoadLibrary(). You'll never see such a dependency back in Depends unless you use the Profile option. Such DLLs are found back through the registry, the reason you needed to write an installer and tinker with regsvr32.exe.
You have to be pretty careful when writing installers like that, VB6 is old and can depend on operating system components that have been updated many times since 1998. Like uxtheme.dll, an important operating system DLL that implements visual styles. Having your installer overwrite the existing one on the user's machine is, well, disastrous. Although it is probably protected by Windows through its File System Protection feature, something that got added as a counter-measure against broken installers.
Giving proper advice is here difficult beyond "do no harm". A commercial installer like InstallShield or Wise (which I liked back then) is the best way to avoid shooting off the customer's leg. Fairly sure they still support VB6 installs. Microsoft makes a pre-cooked installer available for VB6 that installs all the core vb6 runtime components. You can download it here.
You should ALWAYS double check and verify any dependancies that you think your application needs.
All the files you mentioned are system DLLs and MUST NOT be distributed.
For a VB6 application you need the basic runtimes, and any DLLs you explicitly reference/use if and only if you have permission from the authors of those DLLs and instructions on the correct procedure and location for installing them.
For the standard Microsoft provided OCX files, these normally just need to be copied to the system32 folder and registered.
See redist.txt in the root of your Visual Studio installation for more details.

VS Setup Project - Installing Assemblies to GAC and starting a service that uses them all in one installation

I've read every stackoverflow article on MSI installations, but I cannot find the solution to my problem:
I have a VS2010 solution with 5 projects, all targeting .NET 2.0:
DLL A, no project references
DLL B, references DLL
A Windows Forms App, references DLL B
Windows Service, references DLL B
Setup Project
DLL A and DLL B are set up as to be installed to the GAC at install time. I'd like to start the service once the installation has finished, but according to what I've read, the assemblies are not registered until the very last step. I have proven this by attempting to start the service on the AfterInstall event of my ServiceInstaller class and I get the following error:
Error 1001. Could not load file or
assembly 'DLL_B', version 1.0.0.1,
Culture=neutral,
PublicKeyToken=5e297270603814f4' or
one of its dependencies. The system
could not find the file specified.
But of course, once installation is complete, I can manually start the service and it runs fine. Also, in Windows XP, I can usually have the service started at application launch (I have a checkbox with Launch Application as the last step of the installer). But in Windows 7, permissions are no longer elevated at that time and starting the service throws an error.
How can I achieve the installation and starting of the service without forcing a reboot? To quote my client: "Its 2011 now and that shouldn't be necessary.", and I agree whole-heartedly.
Thanks ahead of time.
This is a well-known issue with the GAC. One option might be to use two separate installers and daisy-chain them. This is the way we have chosen to get around the problem of deploying Microsoft VC runtimes on Vista and later. If you use the merge modules, any services that depend on them won't start. So in effect you put your GAC-destined components in a pre-installer whose transaction will be completed and committed before you run a second install that installs and starts the services that depend on them. Ugly, I know, but better than a reboot.
A solution is to use a custom action which runs after InstallFinalize in InstallExecuteSequence table. This custom action should use the msidbCustomActionTypeAsync and msidbCustomActionTypeContinue flags so it runs in a separate process after the installation is finished.
This cannot be done with a Visual Studio setup project, but there are a lot of alternatives: Orca, WiX, a commercial setup authoring tool etc.
I worked around this issues slightly differently: I installed my assemblies not only in GAC, but also into the Application Folder. My GAC-bound assemblies were already found as dependencies, so I put those into GAC (and those indeed end up there only after all custom steps executed). I also added same assemblies as primary output to the Application Folder, where my InstallHelper DLL with custom actions also resides. This way during installation local copy from Application Folder is used.