title: MsiInstallProduct() starts msiexe.exe but in 32 bit mode?
body: <p>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 <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa368786%28v=vs.85%29.aspx" rel="nofollow">this</a> 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"</p>
  
  <p>checked the process monitor and suddenly realized the msiexec is running in 32 bit mode.</p>
  
  <p>funny is when calling the msiexe directly it starts in 64 bit but using MsiInstallProduct() method it starts in 32 bit.</p>
  
  <p>I believe the exception raises when the msiexec tries to configure the registry keys and as the MSI files are 64 bit it crashes.</p>
  
  <p>any help appreciated.</p>
  
  <p>Cheers, 
  Afshin</p>
  
  <p><strong>Update 1:</strong>
  enabled the log using MsiEnableLog and this error showed up:</p>
  
  <p><strong>"MSI (c) (94:F8) [07:50:29:395]: Internal Exception during install operation: 0xc0000005 at 0x000007FE9827F768."</strong></p>
  
  <p><strong>Update 2:</strong>
  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 <a href="http://msdn.microsoft.com/en-us/library/ms686203%28VS.85%29.aspx" rel="nofollow">SetDllDirectory</a> but still getting the same result.</p>
  
  <p><strong>Update 3:</strong>
  the main process is definitely running in 64 bit mode:
  both prccess monitor proves this and the powershell command result:</p>
  
  <pre><code>[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
  </code></pre>
  
  <p><strong>Update 4:</strong>
  I'm using this method to import MSI.DLL:</p>
  
  <pre><code>[DllImport("msi.dll", CharSet = CharSet.Auto, SetLastError = true)]
  internal static extern int MsiInstallProduct(string packagePath, string commandLine);
  </code></pre>
  
  <p><strong>Update 5:</strong>
  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.</p>
  
  <p><strong>Update 6:</strong>
  I just found out that this line is the source of the problem:</p>
  
  <pre><code>oldHandler = MSIIntrop.MsiSetExternalUI(
      new MSIIntrop.InstallUIHandler(OnExternalUI),
      32735,
      IntPtr.Zero);
  </code></pre>
  
  <p><strong>Update 7 [FINAL UPDATE]:</strong>
  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:</p>
  
  <pre><code>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);
      }
  }
  </code></pre>
  
  <p>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 :)</p>