title: MSI Interop using MSIEnumRelatedProducts and MSIGetProductInfo
body: <p>Whilst working with the MSI Interop API I have come across some unusual behaviour which is causing my application to crash.  It is simple enough to 'handle' the problem but I would like to know more about 'why' this is happening.</p>
  
  <p>My first call to MSIEnumRelatedProducts returns an value of 0 and correctly sets my string buffer to a productcode.  My understanding is that this would only happen if the given upgradecode (passed as a parm to the method) has a 'related family product' currently installed, otherwise it would return 259 ERROR_NO_MORE_ITEMS.</p>
  
  <p>However when I subsequently call MSIGetProductInfo using the same productcode I get the return value 1605, "This action is only valid for products that are currently installed.".</p>
  
  <p>Does anyone have any ideas under what circumstances this might happen?  It is 100% repeatable on 1 machine but I have not yet managed to get reproduction steps on another machine.</p>
  
  <p>All our products are build with the Wix Property "AllUsers=1" so products should be installed for all users, not just one.</p>
  
  <p>Any ideas/suggestions appreciated.</p>
  
  <p>Thanks
  Ben</p>
  
  <p><strong>Update:</strong>
  I've noticed that when running the problem msi package with logging the following line is shown:</p>
  
  <p>MSI (s) (88:68) [12:15:50:235]: FindRelatedProducts: could not read ASSIGNMENTTYPE info for product '{840C...etc.....96}'.  Skipping...</p>
  
  <p>Does anyone have any idea what this might mean?</p>
  
  <p><strong>Update: Code sample.</strong></p>
  
  <pre><code>do
  {
     result = _MSIApi.EnumRelatedProducts(upgradeCode.ToString("B"), 0, 
                                          productIndex, productCode);
     if (result == MSIApi.ERROR_BAD_CONFIGURATION ||
         result == MSIApi.ERROR_INVALID_PARAMETER ||
         result == MSIApi.ERROR_NOT_ENOUGH_MEMORY)
     {
        throw new MSIInteropException("Failed to check for related products", 
                                       new Win32Exception((Int32)result));
     }
  
     if(!String.IsNullOrEmpty(productCode.ToString()))
     {
        Int32 size = 255;
        StringBuilder buffer = new StringBuilder(size);
        Int32 result = (Int32)_MSIApi.GetProductInfo(productCode, 
                               MSIApi.INSTALLPROPERTY_VERSIONSTRING, 
                               buffer, 
                               ref size);
  
        if (result != MSIApi.ERROR_SUCCESS)
        {               
           throw new MSIInteropException("Failed to get installed version", 
                                          new Win32Exception(result));
        }
  
        version = new Version(buffer.ToString());
     }
  
     productCode = new StringBuilder(39);
     productIndex++;
  }
  while (result == MSIApi.ERROR_SUCCESS);
  </code></pre>