DEBUG: Error 2769: Custom Action CA_InstallAssemblyDef.3643236F_FC70_11D3_A536_0090278A1BB8 did not close 2 MSIHANDLEs.

While installing .Net Framework 3.5 / .Net Framework 2.0 /any other patches, it may fail with the following error message:
DEBUG: Error 2769: Custom Action CA_InstallAssemblyDef.3643236F_FC70_11D3_A536_0090278A1BB8 did not close 2 MSIHANDLEs.

From the MSI verbose log:

MSI (s) (78:A0) [15:48:43:802]: Executing op: ActionStart(Name=CA_InstallAssemblyDef.3643236F_FC70_11D3_A536_0090278A1BB8,,)
MSI (s) (78:A0) [15:48:43:802]: Executing op: CustomActionSchedule(Action=CA_InstallAssemblyDef.3643236F_FC70_11D3_A536_0090278A1BB8,ActionType=1025,Source=BinaryData,Target=InstallAssembly

,CustomActionData=c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Web.dll;5242880)
MSI (s) (78:18) [15:48:44:052]: Invoking remote custom action. DLL: C:\WINDOWS\Installer\MSI1C6.tmp, Entrypoint: InstallAssembly
09/02/11 15:48:44 DDSet_Status: LANGID: 1033
09/02/11 15:48:44 DDSet_Entry: InstallAssembly started
09/02/11 15:48:44 DDSet_Status: CustomActionData: c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Web.dll;5242880
09/02/11 15:48:44 DDSet_Status: No ProductCode was passed in the CustomActionData. Using the current ProductCode.
09/02/11 15:48:44 DDSet_Status: ProductCode for assembly install/uninstall has been set to {C09FB3CD-3D0C-3F2D-899A-6A1D67F2073F}
09/02/11 15:48:44 DDSet_Status: Loading mscoree.dll
MSI (s) (78:18) [15:48:44:537]: Leaked MSIHANDLE (4186) of type 790531 for thread 3132
MSI (s) (78:18) [15:48:44:537]: Leaked MSIHANDLE (4185) of type 790531 for thread 3132
MSI (s) (78:18) [15:48:44:537]: Note: 1: 2769 2: CA_InstallAssemblyDef.3643236F_FC70_11D3_A536_0090278A1BB8 3: 2
09/02/11 15:48:44 DDSet_Status: Loading fusion.dll using LoadLibraryShim()
DEBUG: Error 2769: Custom Action CA_InstallAssemblyDef.3643236F_FC70_11D3_A536_0090278A1BB8 did not close 2 MSIHANDLEs.
The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2769. The arguments are: CA_InstallAssemblyDef.3643236F_FC70_11D3_A536_0090278A1BB8, 2,

I captured process monitor trace and debugged the custom action ( debug process is mentioned at the bottom of this page). I found that there was an Access Violation in the CNgenIndex destructor, possibly heap corruption. Based on the procmon trace, Fusion is getting pretty far installing this assembly, much past initial load of the shim. It looks like the thread dies right after enumerating the NGEN index. The trace also shows some very unusual usage pattern in the NGen index (in particular, multiple nodes for the same assembly), which generally indicates that the index is corrupted. Finally, I found that it was an issue with native images index corruption.

0:003> .exr -1
ExceptionAddress: 7c91168b (ntdll!RtlpCoalesceFreeBlocks+0x0000012a)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000000
Parameter[1]: 00320037
Attempt to read from address 00320037

0:003> knL100
# ChildEBP RetAddr
00 00f8da28 7c91084c ntdll!RtlpCoalesceFreeBlocks+0x12a
01 00f8dafc 79e7a1b6 ntdll!RtlFreeHeap+0x2e9
02 00f8db34 79e7a1f1 mscorwks!EEHeapFree+0x98
03 00f8db48 79e7a17a mscorwks!EEHeapFreeInProcessHeap+0x22
04 00f8db7c 79f0db7a mscorwks!operator delete+0x2a
05 00f8db8c 7a168606 mscorwks!CNgenIndex::`scalar deleting destructor'+0x17
06 00f8dbd4 7a1692e6 mscorwks!CAssemblyCacheItem::UpdateGACChangeAndNgenIndex+0x1eb
07 00f8e884 79f70fb0 mscorwks!CAssemblyCacheItem::MoveAssemblyToFinalLocation+0x879
08 00f8e8cc 79f70e0b mscorwks!CAssemblyCacheItem::LegacyCommit+0x245
09 00f8e908 7a160682 mscorwks!CAssemblyCacheItem::Commit+0x5d
0a 00f8f1a4 10012689 mscorwks!CAssemblyCache::InstallAssembly+0x425
0b 00f8f1f8 1001345c MSI1AA!CAssembly::Install+0x63
0c 00f8fc9c 100134fe MSI1AA!ProcessAssembly+0x861
0d 00f8fcd4 3feee094 MSI1AA!InstallAssembly+0x3e
WARNING: Stack unwind information not available. Following frames may be wrong.
0e 00f8fcf0 3feb04cb msi!MsiPreviewBillboardA+0x3fcee
0f 00f8ffb4 7c80b729 msi!MsiPreviewBillboardA+0x2125
10 00f8ffec 00000000 kernel32!BaseThreadStart+0x37

In order to resolve this issue, please open the registry editor and clear the NGen index by deleting the registry key HKLM\SOFTWARE\Microsoft\Fusion\NativeImagesIndex\v2.0.50727_32 , then run ngen update.

<From a command prompt type C:\Windows\Microsoft.NET\Framework\v2.0.50727\ngen.exe update >

Capturing a dump of the custom action “CA_InstallAssemblyDef.3643236F_FC70_11D3_A536_0090278A1BB8”

======================================================================

1) Download and install Windbg 32 bit on the repro box from the following location https://msdl.microsoft.com/download/symbols/debuggers/dbg_x86_6.11.1.404.msi

2) Right-click My Computer, and then click Properties.

3) On the Advanced tab, click Environment Variables, and then under System Variables, click New.

Note: You must add MsiBreak to the list of System Variables (and not to the list of User Variables).

4) In the Variable Name field, enter "MsiBreak" (without the quotation marks).

5) In the Variable Value field, enter “CA_InstallAssemblyDef.3643236F_FC70_11D3_A536_0090278A1BB8” without quotes

6) Run the patch from elevated command prompt and start installing

7) During installation, a break message will appear stating "To debug your custom action, attach your debugger to process XXX (0xZZZ) and press OK". Open WinDBG instead of following the instructions on the dialog that pops up, press F6 (or Attach to a process from file menu), and select the process id that was prompted earlier XXX (0xZZZ).

8) Hit No for the next message and you will find the command line of windbg just above the task bar,

image

9) Hit “g” without quotes and hit enter again, you will find that the installation will resume and the Windbg command line will be greyed out.

10) It will break again with some exception on the Windbg window and you will find that the command line is enabled again.

11) Now either continue debugging the custom action or type .dump /ma c:\CustomActionFailureDump.dmp to save the dump file for offline analysis.