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.
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.
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.".
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.
All our products are build with the Wix Property "AllUsers=1" so products should be installed for all users, not just one.
Any ideas/suggestions appreciated.
Thanks
Ben
Update:
I've noticed that when running the problem msi package with logging the following line is shown:
MSI (s) (88:68) [12:15:50:235]: FindRelatedProducts: could not read ASSIGNMENTTYPE info for product '{840C…etc…..96}'. Skipping…
Does anyone have any idea what this might mean?
Update: Code sample.
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);
Best Answer
I suppose that you try to use MsiGetProductInfo to get a property other as described in documentation. For example you can get in the way the value of the
"PackageCode"
property (INSTALLPROPERTY_PACKAGECODE
) without any problem, but you can't get the value of the"UpgradeCode"
property with respect of MsiGetProductInfo and receive the error 1605 (ERROR_UNKNOWN_PRODUCT
).UPDATED: OK, now I understand you problem. How you can find in the internet there are a bug in MsiGetProductInfo, so it work not always. Sometime it get back 1605 (
ERROR_UNKNOWN_PRODUCT
) or 1608 (ERROR_UNKNOWN_PROPERTY
) back. In the case as the only workaround is to get the version property manually. I could reproduce the problem which you described on my computer with the Microsoft Office Outlook 2010 MUI (UpgradeCode = "{00140000-001A-0000-0000-0000000FF1CE}") and wrote a workaround where I get the product version from the registry. In the example I get information only fromHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products
. If you have an interest to products installed not only for all users you have to modify the program. Here is the codewhich produce on my computer the correct output
instead of errors in the
ProductVersion
before.