Avoid to bring MSI in compatibility mode "Previous version of Windows" - windows

I have an installer package for a 32-bit Application (built with MakeMsi, originally for Windows XP, and simplicisticly maintained since then), that fails registering a COM server on modern (64-bit) Windows systems (7, 8, 10). This is what I see when trying to install my MSI normally:
Application Error
Exception EOleSysError in module xyz at 000F0B01. Error accessing the OLE registry.
If I bring the MSI in compatibility mode Previous version of Windows, the COM server registers successfully. Since "it's working" somehow, I didn't invest much time in exploring the reasons so far. But finally, I'm exhausted to remember our customers (and sometimes also me) again and again of this precondition, so I wish to fix this issue.
The registration (and de-registration) is done via CustomActions, as I see looking into it using Orca:
"[INSTALLDIR.MYAPP]\placeholder.exe" -regserver
"[INSTALLDIR.MYAPP]\placeholder.exe" -unregserver
For each of those entries, Type is 1122 and Source is INSTALLDIR.MYAPP.
I could imagine that the COM server is started with insufficient privileges in the installation procedure, but aren't installers run automatically with administrator rights? I mean, when I (as a standard user) start the installer by double-clicking it, it shows the UAC prompt before the actual installation takes place. Why are the COM servers not run with elevated rights for their registration and de-registration? It's confusing...
How should I change my MSI to make Windows installer process it successfully?

I assume you know that the problem is in the executable that you're running as a custom action, not anything in Windows Installer. That means the issue will be the code in the executable, and it's probably old and incompatible with later OS versions. You'll need to look at the code to see what it's doing that is unsupported.
Many installs don't bother with self-registration. That data is all static data that can be extracted once and included in the MSI file in registry entries and other COM class tables. This means that there is no need to run code at all during the install.

After learning how to register COM servers the right way, I still was interested to understand, why my MSI package worked before. In other words: what is the crucial change after Windows XP? ...I meanwhile also checked that the MSI works when I run it as an administrator...
As I figured out reading the WiX toolset documentation, there is an attribute Impersonate for CustomAction that controls if the CA is executed with elevated privileges:
This attribute specifies whether the Windows Installer, which executes as LocalSystem, should impersonate the user context of the installing user when executing this custom action. Typically the value should be 'yes', except when the custom action needs elevated privileges to apply changes to the machine.
It refers to the msidbCustomActionTypeNoImpersonateflag in the Type field of the CustomAction Table. The value 1122 I observed in my MSI is decompiled into this:
1024 (flag): msidbCustomActionTypeInScript, or, deferred execution, runs in installation script
64 (flag): msidbCustomActionTypeContinue, or, ignore exit code and continue
34: Custom Action Type 34, or, launch executable via commandline
What I used to "fix" the problem the fast way is, enable the msidbCustomActionTypeNoImpersonate flag (2048) in the CA type (in WiX this would be Impersonate="no").
Translated into my MakeMsi script, I had to use the System attribute in the Type of the ExeCa command as to make self registration work as before:
Type="Deferred Sync AnyRc System"
I'm fully aware that this is only a workaround, since running a COM server for (un-)register is dangerous. And so the solution mentioned in the second section of PhilDWs answer should be preferred: manage COM related static information via registry entries in the MSI. But sometimes you need a fast solution, and sometimes there is no other option, see Euro Micellis comment.

Related

Diagnosing self-healing MSI

The app I work on is written mainly in VB6.
Some users report that when they start up my app a different MSI installer will automatically run and try to repair its own installation. Often this is for AutoCAD but sometimes other programs also.
Usually this occurs every time they start the app.
What is a procedure that we can use to diagnose why this occurs? Since it is a third-party's installer which is running we don't have any visibility into what it is doing.
AutoDesk does have some info published on this:
Unexpected installer launches
Windows Installer displayed unexpectedly
but these do not directly provide enough information. Ideally I want to be able to completely prevent this from occurring to my end users, rather than just telling them how to avoid it or clean it up.
Your installer is acting on a directory, file or registry key that Windows Installer knows is part of the AutoCad installation.
First, I would turn on global Windows Installer logging. This means that any Windows Installer activity - including AutoCad's installer - is written to an external log file (in %temp%).
How to Enable Windows Installer Logging
Next, run your installer, and let the AutoCad installer run.
Now go to %temp% and you should find files MSIXXXX.LOG - one for your installer, one for AutoCad. Open these and you can work your way through them and identify which file or registry key the AutoCad MSI find is missing or changed.
You may find WiLogUtl.exe helpful for this:
Wilogutl.exe
With any luck you will identify that the directory, file or registry key triggering autorepair is also in your installer. If you're really in luck you can identify it as an item you should not be installing anyway - perhaps you are referencing a system component that would be present anyway, something protected by Windows File Protection.
If not, you will have to look at something like RegFree COM to move files out of shared directories into your private directory and reduce registry conflicts. Also, if you are using (consuming) the Visual C++ Runtime MSMs to make your MSI, consider using the Microsoft EXE installer instead or (best of all) placing the DLLs directly in your program folder, since I've found that the MSMs can cause just this sort of problem.
With regards to Peter Cooper Jr's comment on VB6 causing self-repair. Please check out the heat.exe documentation for Wix. You will see that there is a special switch the tool supports to suppress extracting certain registry values that are owned by the VB6 runtime itself (and hence shouldn't be messed with or updated by any other MSI): http://wixtoolset.org/documentation/manual/v3/overview/heat.html
Go down the list to the switch -svb6 and read the description to the right. (Reproduced here:)
When registering a COM component created in VB6 it adds registry
entries that are part of the VB6 runtime component:
CLSID{D5DE8D20-5BB8-11D1-A1E3-00A0C90F2731}
Typelib{EA544A21-C82D-11D1-A3E4-00A0C90AEA82}
Typelib{000204EF-0000-0000-C000-000000000046}
[as well as] Any Interfaces that reference these two type libraries
Does your installer write to these keys? If so try to exclude them - this is good to do even if it isn't the culprit in this particular case.
Other than that there is a lengthy description of what can cause Windows Installer self-repair here: How can I determine what causes repeated Windows Installer self-repair?. It is a long article because there are so many different ways self-repair can occur. The common denominator is that different installers on your system are fighting over a shared setting that they keep updating with their own values on each application launch in an endless loop.

How does Windows know I'm installing something?

It's a common practice to disallow users from installing programs without elevated privileges, especially in larger companies. When the user runs the installation executable (whether .exe or .msi), the user is prompted for these admin credentials before User Access Control will allow the installation. A lot of programs that require installation take advantage of the default Windows installer .msi packaging or something similar, but an executable file could perform all the same functionalities, right?
Is it this common installation-packaging solution that tells Windows, "Hey, I'm an installer. Something is being installed."? Windows isn't analyzing the actual behavior of the executable file, right?
If your question is about asking for admin credentials, that's normal behavior when an executeable has a manifest that says it requires admin privilieges. I guess that if you say your InnoSetup requires admin privileges it will include a manifest requiring elevation, and Windows will show the elevation prompt.
There is no such thing as Windows InstallShield, in case you are thinking that InstallShield is a Microsoft Windows product. InstallShield is a 3rd party product that in many cases creates an MSI file. MSI files are marked (when built) as to whether they require elevation or not. It's the summary information strean Word Count that says whether the MSI requires elevation to install or not:
https://msdn.microsoft.com/en-us/library/aa372870(v=vs.85).aspx
In the case of an .MSI, sure, Windows automatically knows your installing something. I think your question is more along the lines of what about anything other then an .MSI? Windows has some heuristics built in that AFAIK are managed by the application compatibility team. They do things to detect what they is a setup (like file name, process name, inspection of the summary information stream and so on ) and perform various functions such as detecting a possible failed install, asking if it was an install and if it failed and them performing application compatibility shims such as version lying and forced UAC elevation prompting.
You get to avoid this ugly world my authoring properly designed MSIs. :)
MSIs can be authored per-user or per-machine. Per-user installs won't ask for elevation by default. Per-machine installs will ask for elevation once they hit the InstallExecuteSequence.

DllRegisterServer failed for comct332.ocx

I have a VB6 application I am trying to get working on a Windows 7 environment, however every time I start the application, I get the error:
"Component 'ComCt332.ocx' or one of its dependencies not correctly registered: a file is missing or invalid".
To resolve, I have tried to register the comct332.ocx file by running the regsvr32 in the Command Prompt in Administrator Mode but then I get the error:
"The module "comct332.ocx" was loaded but the call to DllRegisterServer failed with error code 0x80004005"
Other things I have tried include:
Deleting all parent nodes in the registry where 'comct332.ocx' exists
and running regsvr32 again in Admin Mode. Same result.
I granted admin permission to another user on the PC and I could register the
file successfully, and the application starts and runs successfully!
However when I log in as the previous user again, it fails miserably.
Any help, thoughts, other-things-to-try will be much appreicated. Thanks
If you have been keeping up on things as you must if you are to continue using VB6 successfully there are a number of things you'll be aware of.
One of these is the impact of UAC and per-user registry
virtualization.
Another is the impact of SysWOW registry redirection on 64-bit
systems.
You will understand that proper installation packages are more important than ever before. Windows has many auto-remediations for legacy software but some of them will not result in applications having all of the originally intended behaviors. Most of them will only be applied when your application "follows the right path" from installation to second run.
Here we have a case that is intended to be handled through use of a proper Windows Installer package, or at least a legacy setup recognized as such through Windows' "legacy installer detection heuristics." In general legacy scripted setups are deprecated but as long as they stay on the path Windows makes efforts to ensure they succeed.
Manually deploying by just copying over a bunch of files and randomly running regsvr32 on some of them has a reduced chance of success. This was never an approved method of deployment anyway.
You have most likely run afoul of some combination of registry virtualization and redirection.
The regsvr32 utility is a development tool, not a deployment tool. If you insist on trying to use it for deployment you must follow the same rules a developer must follow:
Run the correct version. On a 64-bit system there are both 64- and
32-bit versions of this utility. The 32-bit version which you must
use is located in the SysWOW64 folder.
Run it from an elevated command prompt. An easy
way to start one is to type <Winkey>cmd.exe<Ctrl-Shift-Enter> then
approve the UAC prompt or provide over-the-shoulder admin credentials
as needed.
There are many other things you need to know and handle in order to be successful. If you have ignored those most of them will only become apparent to you after your program gets installed and will run. A lot of them stem from filesystem virtualization.

WiX 3.0 throws error 217, while being executed by continuous integration

This is the error that is thrown by our automated build suite on Windows 2008, while running ICEs (after migrating from WiX 2.0 to WiX 3.0):
LGHT0217: Error executing ICE action 'ICE01'. The most common cause of this kind of ICE failure is an incorrectly registered scripting engine. See http://wix.sourceforge.net/faq.html#Error217 for details and how to solve this problem. The following string format was not expected by the external UI message logger: "The Windows Installer Service could not be accessed. This can occur if the Windows Installer is not correctly installed. Contact your support personnel for assistance.". in light.exe(0, 0)
The FAQ is now deleted, however, the text from it said:
In WiX v3, Light automatically runs validation-- Windows Installer Internal Consistency Evaluators (ICEs) --after every successful build. Validation is a great way to catch common authoring errors that can lead to service problems, which is why it’s now run by default. Unfortunately, there’s a common issue that occurs on Windows Vista and Windows Server 2008 that can cause ICEs to fail. For details on the cause and how to fix it, see Heath Stewart's Blog and Aaron Stebner's WebLog.
Additionally, these are the errors that show up in the event log:
MSIInstaller: Failed to connect to server. Error: 0x80070005
Product: [ProductName] -- Error 1719. The Windows Installer Service could not be accessed. This can occur if the Windows Installer is not correctly installed. Contact your support personnel for assistance.
Intuitively:
VBScript and JScript were registered under admin.
Integration service has permissions for the desktop interaction and all the files
Builds succeed, when executed manually on the same machine by another user or even user logged in as integration account (via RDP)
I'm out of ideas so far.
How do I solve this problem while keeping ICE validation?
End of the story:
After fiddling with the permissions of the integration account, DCOM, service activation, etc. without any luck, I finally simply disabled ICE validation in the continuous integration build, while still keeping it in the local build.
To disable ICE validation you can set SuppressValidation to true in the .wixproj file:
<PropertyGroup>
<SuppressValidation>true</SuppressValidation>
</PropertyGroup>
Or pass the -sval command line option to light.exe.
Adding the TFS build controller account to local admin group and restarting the windows service did the job for me.
I found the root cause. I tried everything I found, including custom validator extension similar to one posted in Re: [WiX-users] light.exe failed randomly when running ICEs..
It's not a concurrency issue as suggested in various threads. It's caused by a too large Process Environment Block (PEB).
It turns out Windows Installer can’t handle a process environment block larger than 32 kB. In my environment, due to number of variables set by the build system and their size (for example, PATH variable containing multiple duplicated values), PEB was about 34 kB.
Interestingly, per Environment Variables, Windows XP and 2003 had a hard limit of PEB set to 32 kilobytes. That would probably cause an easy-to-catch build break in an earlier phase of the build. Newer Windows' doesn’t have such limit, but I guess that Windows Installer developers limited their internal environment buffers to 32 kB and fail gracefully when the value is exceeded.
The problem can be easily reproduced:
Create a .bat file which sets environment variables which size exceeds 32 kB. For example, it can be 32 lines of set Variable<number>=<text longer than 1024 characters>
Launch cmd.exe
Execute the batch file you created
From the same cmd.exe window:
Try building the MSI package using WiX with ICE validation on OR
Run smoke.exe to validate your package OR
Simply run msiexec /i Package.msi
All the above commands will end up reporting Error 1719 - Windows Installer could not be accessed.
So, the solution is - review your build scripts and reduce number and size of environment variables so they all fit into 32 kB. You can easily verify the results by running:
set > environment.txt
The goal is to get file environment.txt smaller than ~30 kB.
The correct description (without a solution, except if adding the CruiseControl account into local administrators group can pass as a solution) of the problem:
Quote from Wix 3.5 & Cruise Control gives errorLGHT0217:
ICE validation needs an interactive account or administrator privileges to be
happy. See for example WiX Projects vs. TFS 2010 Team Build (2009-11-14) or Re: [WiX-users] Help with building patch (2009-11-20).
imagi is totally right! I could not believe this is the true answer. Supressing validation and making TFS user Administrator are not good solutions. Plus I could not find NT\Authority to add it to Administrators group and was totally stuck in this.
I got the same error on Windows Server 2012 Datacenter as Build Agent.
To solve the problem :
List item
Go to Environment Variables on the build agent machine
Create two System Variables
"PF86" which is equal to "C:\Program Files (x86)"
"PF" which is equal to "C:\Program Files"
They are so short because I want to save characters.I made them without the final backslash because TEMP, TMP and others were made so and I decided to stick to MS standard for these variables.
Edit PATH variable by substituting every "C:\Program Files (x86)" with %PF86% and every "C:\Program Files" with %PF%
Close and build and enjoy!
It worked for me. :)
UPDATE
I found a better solution : Rapid Environment Editor will do all this and even more for you. Automatically.
I faced the same problem and did not like to suppress ICE validation. My setup: I used my own computer as a build agent on Visual Studio Online (VSO). My solution was to change the account used to run the service on my machine. Instead of using Network Service or Local Service I simply made the service log on with my own account which had all the necessary rights.
From http://wix.sourceforge.net/faq.html#Error217:
In WiX v3, Light automatically runs validation--
Windows Installer Internal Consistency Evaluators (ICEs)
--after every successful build. Validation is a
great way to catch common authoring errors that can lead to service problems,
which is why it’s now run by default. Unfortunately, there’s a common issue
that occurs on Windows Vista and Windows Server 2008 that can cause ICEs to
fail. For details on the cause and how to fix it, see
Heath Stewart's Blog
and
Aaron Stebner's WebLog.
I was getting same ICE error, but the problem turned to be corrupted Windows Installer Service.
This solution worked for me:
http://support.microsoft.com/kb/315353
Log on to your computer as an administrator.
Click Start, and then click Run.
In the Open box, type cmd, and then click OK.
At the command prompt, type msiexec.exe /unregister, and then press ENTER.
Type msiexec /regserver, and then press ENTER.
Restart Windows
Also, verify that the SYSTEM account has full control access permissions to the
HKEY_CLASSES_ROOT hive in the Windows registry. In some cases, you may also have to add Administrator accounts.
I have some suggestions.
Try updating the Microsoft Installer version on the build server
Make sure you use the newest release of WiX 3.0, since it's 3.0 release stable now.
If all else fails, try running the build service under a specific build user who you can fiddle with permissions for...
I got this error from my Azure build agent running on-premises.
My solution was to upgrade its user account from "Network Service" to "Local system account".
Go to your build machine and restart the Windows Installer service
None of the above suggestions worked for me, for me the anti-virus (mcafee) came into the picture and looks like it updated the vbscript.dll registry entry to a wrong DLL location. These are the things to keep in mind:
Some of the WiX ICE validations are implemented using VBSCRIPT.
So while compiling the MSI, the build server would need access to the c:\windows\system32\vbscript.dll.
Chances are that somehow the user that runs your build lost access to this DLL.
As mentioned in the above answers do look for the admin access/registry access and make sure your user has it.
Here are the steps that I took to fix the issue:
Open cmd (run as admin) on the build agent machine.
Run RegEdit
Select the root, then click ctrl + f and Search for the following registry entry : {B54F3741-5B07-11cf-A4B0-00AA004A55E8}
Look for the InprocServer32\Default Key
On my build agent, the path was replaced with a mcafee DLL location. I updated the path back to c:\windows\system32\vbscript.dll
Editing the registry entry was not easy, as it was a protected registry entry. I used the below link to get access permissions changed before I could edit the property: Edit protected registry entry
Once I updated the path, everything started working as usual.
My solution is similar to Vladimir's one. My CI user was admin of the computer.
But the following steps were mandatory to allow my jenkins build to succeed:
log in as CI user using rdp
open a dos command prompt
execute: %windir%\system32\msiexec.exe /unregister
execute: %windir%\system32\msiexec.exe /regserver
then i got a successfull job

Installation file names in Windows Vista

I read in this article:
http://technet.microsoft.com/en-us/library/cc709628.aspx
That Windows detects Installers through file names, following this tip, Is it better to include setup in the file name for the installer
I mean ProductSetup.msi is better than Product.msi???
It's hard to think that Windows does this kind of detection :-)
This only applies to EXE files. If you've got an MSI file, it's up to the MSI file to specify which parts of the MSI require elevation or not.
That's news to me, but it does seem like Windows Vista treats files differently when they have "setup" in their name. It will probably just prompt you for administrative rights up front if it detects that it's an installer, which is what you'd want.
Also worth reading is How User Account Control Affects Your Application, to ensure that your setup runs as administrator embed the correct manifest into the setup EXE. This way it doesn't matter (to Vista) what your installation is called.
That said however, if you expect the application to be installed on a terminal server then if your installer is called something like SETUP.EXE or INSTALL.EXE Terminal Server will automatically kick into "install mode". Should save you some headaches from those customers who don't know they should be in install mode first, or choose not to install via Add/Remove Programs (which also kicks install mode in automatically)

Resources