简体   繁体   中英

MsiInstallProduct() starts msiexe.exe but in 32 bit mode?

I have a customized setup application which installs several MSI files. today I tried to implement the external UI to implement my own progress bar using this article. everything looks working (progressbar receives data and updates) but after about 60% when starting to update the components I receive an exception: 'object not set to ...' and digging further got this: _COMPlusExceptionCode "-532462766"

checked the process monitor and suddenly realized the msiexec is running in 32 bit mode.

funny is when calling the msiexe directly it starts in 64 bit but using MsiInstallProduct() method it starts in 32 bit.

I believe the exception raises when the msiexec tries to configure the registry keys and as the MSI files are 64 bit it crashes.

any help appreciated.

Cheers, Afshin

Update 1: enabled the log using MsiEnableLog and this error showed up:

"MSI (c) (94:F8) [07:50:29:395]: Internal Exception during install operation: 0xc0000005 at 0x000007FE9827F768."

Update 2: digging further based on suggestion by @marceln, used Process Monitor and noticed there are two msiexec processes in the memory. one in 64 bit mode which is in session 0 and the other starts by the first one when I call MsiInstallProduct. the second one starts from 'c:\\windows\\syswow64\\msiexec.exe' which is 32 bit version. I tried to set the lookup path using SetDllDirectory but still getting the same result.

Update 3: the main process is definitely running in 64 bit mode: both prccess monitor proves this and the powershell command result:

[reflection.assemblyname]::GetAssemblyName("setup.exe") | fl

Name                  : Setup
Version               : 5.0.0.0
CultureInfo           :
CultureName           :
CodeBase              : file:///...../Setup.exe
EscapedCodeBase       : file:///Setup.exe
ProcessorArchitecture : **MSIL**
ContentType           : Default
Flags                 : None
HashAlgorithm         : SHA1
VersionCompatibility  : SameMachine
KeyPair               :
FullName              : Setup, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null

Update 4: I'm using this method to import MSI.DLL:

[DllImport("msi.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern int MsiInstallProduct(string packagePath, string commandLine);

Update 5: Tried the process explorer, the application is 64 bit, MSI.DLL file under the application is running from system32. but the msiexec.exe process is still running from syswow64 which is 32 bit. msi file is built as a 64 bit msi.

Update 6: I just found out that this line is the source of the problem:

oldHandler = MSIIntrop.MsiSetExternalUI(
    new MSIIntrop.InstallUIHandler(OnExternalUI),
    32735,
    IntPtr.Zero);

Update 7 [FINAL UPDATE]: To whom it may concern: After hours and hours of wasting time, I finally managed to overcome the issue. looks like there's some sort of internal memory management leak in the MSI API which causes the external UI handler crash in a completely random behaviour. To fix the issue, I implemented IDisposable interface and tried to use the class in a "using" block to make sure the class is completely disposed. The MsiSetExternalUI() and MsiInstallProduct() are now safely called within this block. do not forget to call the MsiSetExternalUI() to revert the UI to it's original state:

IntPtr prevWindow = IntPtr.Zero;
MSIIntrop.INSTALLUILEVEL prevUILevel = MSIIntrop.MsiSetInternalUI(MSIIntrop.INSTALLUILEVEL.INSTALLUILEVEL_NONE, ref prevWindow);

using (MSIContext context = new MSIContext(progressChanged, messageRaised))
{
    MSIIntrop.INSTALLUI_HANDLER prevHandlre = MSIIntrop.MsiSetExternalUI(context.Handler,
        MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_FATALEXIT |
        MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_ERROR |
        MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_WARNING |
        MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_ACTIONDATA |
        MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_PROGRESS,
        IntPtr.Zero);
    try
    {
        int ret = MSIIntrop.MsiInstallProduct(runningPath, commandLine);
    }
    catch (Exception ex)
    {
        messageRaised("Error: " + ex.Message);
    }
    finally
    {
        MSIIntrop.MsiSetExternalUI(prevHandlre, 0, IntPtr.Zero);
    }
}

PS 1: I have't put this in the answer since I'm not %100 sure that this was the source of the error. This is just a workaround. PS 2: Thanks to Marcel and Jacob :)

I think after two years of the code running with no issues it would be proper to conclude the workflow proposed in the Update 7 above is an answer to the question:

looks like there's some sort of internal memory management leak in the MSI API which causes the external UI handler crash in a completely random behaviour. To fix the issue, I implemented IDisposable interface and tried to use the class in a "using" block to make sure the class is completely disposed. The MsiSetExternalUI() and MsiInstallProduct() are now safely called within this block. do not forget to call the MsiSetExternalUI() to revert the UI to it's original state

The reason is the garbage collector. Please, try to use GC.KeepAlive() method to prevent the garbage collector from collecting the external UI handler.

For example:

// create ui handler
MSIIntrop.UIHandlerDelegate externalUIHandler = new MSIIntrop.UIHandlerDelegate(context.Handler);

// execute MsiSetExternalUI with this handler
MSIIntrop.INSTALLUI_HANDLER prevHandlre = MSIIntrop.MsiSetExternalUI(externalUIHandler,
    MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_FATALEXIT |
    MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_ERROR |
    MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_WARNING |
    MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_ACTIONDATA |
    MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_PROGRESS,
    IntPtr.Zero);

// install product
int ret = MSIIntrop.MsiInstallProduct(runningPath, commandLine);

// restore the previous ui handler
MSIIntrop.MsiSetExternalUI(prevHandlre, 0, IntPtr.Zero);

// prevent GC from collecting ExternalUIHandler during the product installation
GC.KeepAlive(externalUIHandler);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM