Partager via


delegating uninstallation of assembly file : *** to Fusion

Summary: I created a MSI package which has Merge Module - Microsoft_VC90_DebugCRT_x86.msm. I was able to install the MSI package successfully on my WIN 7 OS. Then I uninstalled the same MSI successfully but the file msvcr90d.dll was NOT removed from the directory: C:\windows\winsxs\x86_microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.30729.6161_none_2a4f639a55563668\

But if I keep the system idle for few minutes, the file gets removed automatically. I took a procmon trace after the MSI uninstall and found that the file msvcr90d.dll was deleted by C:\windows\servicing\TrustedInstaller.exe

As per the MSI uninstall log:
MSI (s) (E4:50) [12:27:46:952]: Executing op: ActionStart(Name=RemoveFiles,Description=Removing files,Template=File: [1], Directory: [9])
MSI (s) (E4:50) [12:27:46:955]: Executing op: ProgressTotal(Total=22,Type=1,ByteEquivalent=175000)
MSI (s) (E4:50) [12:27:46:956]: Executing op: SetTargetFolder(Folder=C:\windows\winsxs\x86_microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.30729.6161_none_2a4f639a55563668\)
MSI (s) (E4:50) [12:27:46:957]: Executing op: FileRemove(,FileName=msvcr90d.dll,,ComponentId={F5DEC4D5-A8A3-3883-B311-C6227A0D21AD})
MSI (s) (E4:50) [12:27:46:967]: delegating uninstallation of assembly file : msvcr90d.dll to Fusion

As per the procmon trace:
TrustedInstaller.exe         3336       QueryDirectory                         C:\Windows\winsxs\x86_microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.30729.6161_none_2a4f639a55563668                    SUCCESS              0: msvcr90d.dll
TrustedInstaller.exe      3336       SetDispositionInformationFile   C:\Windows\winsxs\x86_microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.30729.6161_none_2a4f639a55563668                    SUCCESS              Delete: =True

As far as Windows Installer is concerned it did the right thing. MSI doesn’t remove the file itself. Instead it calls into the fusion asking it to uninstall the assembly. The above lines mean that we have marked the assembly as removable from MSI's viewpoint and asked fusion to remove the file when the transaction is completed and changes committed to the machine. It means that the fusion didn’t delete the file when requested as the component store performs lazy cleanup to speed up uninstall.  This is by design and the concept is called “scavenging”.  The key point is that even the binary file (msvcr90d.dll) is still present after uninstall, it isn’t available for binding by other applications. So there wouldn’t be any impact due to this behavior. For more information on Scavenging, please go through this blog post .  [the directory may hold on to recently-installed or soon-to-be-installed files until they are installed or scavenged in bulk. Scavenging happens periodically, but it cannot be controlled or induced. It is important to note then, that uninstalling a Side-by-Side assembly may not immediately remove the associated files from the WinSxS directory. This is expected, and not a violation of Windows Logo requirements for clean uninstall.]

You can observe that the binaries are indeed uninstalled, even before they are scavenged, by checking for install state with the tool checkruntimes.exe: https://blogs.msdn.com/b/talagrand/archive/2010/03/02/9973115.aspx

Once the MSI is uninstalled successfully, we found that the file msvcr90d.dll was not removed physically from C:\windows\winsxs\x86_microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.30729.6161_none_2a4f639a55563668\  but you can run the below command to know the actual install state of the binary:

After the MSI package is installed

C:\Users\Administrator>C:\checkruntimes\checkruntimes.exe -x86 -crt -9
DebugCRT x86 v9.0.30729.6161 is installed

     CRT    x86   v9.0.30729.4940 is installed

After the MSI package is uninstalled

C:\Users\Administrator>C:\checkruntimes\checkruntimes.exe -x86 -crt -9
     CRT   
x86   v9.0.30729.4940 is installed

The binary msvcr90d.dll is not listed above.

#When called with no arguments, it lists runtimes it can find – calling checkruntimes.exe with no arguments is equivalent to calling:  checkruntimes.exe -8 -9 -10 -debug -retail -x86 -x64 -ia64 -crt -atl -openmp -mfc