Detection of product failed during request for component


If your MSI Installation package is bringing that error message I might have a solution for you. It applies only if you are authoring the installation, your product doesn’t use the resiliency feature and you know what are you doing.

First the theory – each and every COM component, that your installation is registering becomes a little feature with it – every time it is used Windows Installer is going to check if something has gone wrong with it, if so repair installation is started. This brings a lot more problems than it solves, especially if you know, that the updated COM component, is still valid.

So how to “Stop Installation Idiocy”?
My solution was to remove the extra information registered with each COM component, so the Windows Installer has no way to monitor it and as end result can’t bring up an error message if something has changed with the component.  This resiliency feature may be useful in some occasions, but our product does not rely on it in any way and it is just a source of endless problems when we ship updated component.

Here is sample code for a custom action in InstallScript, you can do the same in C++ no matter how are you building your MSI package.
The idea is to find out which COM components are you registering and to remove the hash values, that are inserted automatically from Windows Installer.

function RemoveRepairKeys(hMSI)
	STRING key, guid, context;
	LONG hDB, hView, hRec, r;
	NUMBER pos, num;
begin
	RegDBSetDefaultRoot(HKEY_CLASSES_ROOT);

	hDB = MsiGetActiveDatabase(hMSI);

	if(hDB = 0) then
		SprintfMsiLog("Error MsiGetActiveDatabase");
		return 0;
	endif;

	PrintStatus(
             MsiDatabaseOpenView(hDB, "SELECT `Key` FROM `Registry` WHERE `Root`=0", hView),
             "MsiDatabaseOpenView"
        );
	PrintStatus(MsiViewExecute(hView, 0), "MsiViewExecute");
	r = MsiViewFetch(hView, hRec);
	PrintStatus(r, "MsiViewFetch");
	RegDBSetDefaultRoot(HKEY_CLASSES_ROOT);
	num = 260;
	while(r == 0)
		r = MsiRecordGetString(hRec, 1, key, num);
		pos = StrFindEx(key, "CLSID\\", 0);
		if(pos >= 0) then
			SprintfMsiLog("GUID %s", guid);
			StrSub(guid, key, pos + 6, 38);
			LogResult(RegDBDeleteValue(
				"\\CLSID\\" + guid + "\\InprocServer32", "InprocServer32"),"\\CLSID\\"
                                + guid + "\\InprocServer32.InprocServer32"
			);
			LogResult(
				RegDBDeleteValue("\\CLSID\\" + guid + "\\LocalServer32", "LocalServer32"),
				"\\CLSID\\" + guid + "\\LocalServer32.LocalServer32"
			);
		endif;

		MsiCloseHandle(hRec);
		r = MsiViewFetch(hView, hRec);
		//PrintStatus(r, "MsiViewFetch");
	endwhile;

	PrintStatus(
              MsiDatabaseOpenView(hDB, "SELECT `CLSID`, `Context` FROM `Class`", hView),
             "MsiDatabaseOpenView");
	PrintStatus(MsiViewExecute(hView, 0), "MsiViewExecute");
	r = MsiViewFetch(hView, hRec);
	PrintStatus(r, "MsiViewFetch");
	RegDBSetDefaultRoot(HKEY_CLASSES_ROOT);
	num = 260;
	while(r == 0)
		r = MsiRecordGetString(hRec, 1, guid, num);
		r = MsiRecordGetString(hRec, 2, context, num);
		LogResult(
			RegDBDeleteValue("\\CLSID\\" + guid + "\\" + context, context),
			"\\CLSID\\" + guid + "\\" + context  + "." + context
		);
		MsiCloseHandle(hRec);
		r = MsiViewFetch(hView, hRec);
		//PrintStatus(r, "MsiViewFetch");
	endwhile;

	PrintStatus(MsiCloseHandle(hView), "MsiCloseHandle");

	DeleteRepairKeysFixed(hMSI);
end;

Use this at your own risk, it did work for us pretty well. Questions and comments are welcome.

Some links regarding the resiliency feature:

http://blogs.msdn.com/astebner/archive/2005/01/13/352649.aspx

http://blogs.msdn.com/astebner/archive/2004/08/24/219764.aspx

http://blogs.msdn.com/windows_installer_team/archive/2005/11/01/486587.aspx

http://www.installsite.org/pages/en/msifaq/a/1037.htm

About these ads

Tags: ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: