none
COM RCW doesnt appear to release underlying DLL RRS feed

  • Question

  • Hello All,

    I am writing a windows forms application (in C# targetting .NET v2 x86), that instanciates a COM object by its ProgID, calls a few methods on it to check its version , and then disposes it (with the dispose interface that the DisposeableCOMProxy provides). 

    Based on the method calls to the COM object, my program will download and run an MSI that updates the dll that contains the COM object (should an update be required).  The MSI is set to remove previous versions, and all this happens automatically.

    My problem is that the MSI shuts down my forms application because it claims that it still has a handle on the dll - the below is an excerpt from the msi verbose log:

    MSI (s) (40:74) [14:38:06:141]: RESTART MANAGER: Will attempt to shut down and restart applications in no UI modes.
    MSI (s) (40:74) [14:38:06:141]: RESTART MANAGER: Detected that application with id 3676, friendly name 'MyApp', of type RmUnknownApp and status 1 holds file[s] in use.

    The MSI only contains one file, and thats the dll file that the DisposableCOMProxy used when i instanciated the COM Object with the progid.

    Ive tried explicitly calling GC.Collect() and subsequently calling GC.WaitForPendingFinalizers()

    None of this works!

    How can I remove the "lock" on this file? is it even a lock?

    Is this an issue with the configuration of Windows Installer/the MSI? or is this a COM Interop Marshalling issue?,

    Any help anyone could provide would be greatly appreciated !

    Kind Regards,

    Matthew Dendle

    DisposableCOMProxy - used in this msdn article - http://msdn.microsoft.com/en-us/library/aa480731.aspx (Referenced towards end of article)

    The author of that article posted the code on thecodeproject.com - http://www.codeproject.com/KB/COM/safecomwrapper.aspx

     

    • Edited by MattDendle Friday, September 24, 2010 1:40 PM changed title to better reflect issue
    Wednesday, September 22, 2010 3:13 PM

Answers

  • After having opened a support case with Microsoft, I have a solution to my problems.

    It turns out that the file was still loaded in my process.  They (Mircosoft) used WinDbg to list the modules that my exe had, and sure enough, the dlls were there.

    The solution comes in two flavours - one for managed COM callable dlls, and the other for unmanaged com dlls.

    For managed COM callable dlls, the solution is to instanciate the object in its own AppDomain, then unload the appdomain, which in turn unloads the dll in question.

    For COM dlls, the solution involved using a pinvoke to CoFreeUnusedLibraries() in the ole32.dll, which releases unused libraries.  This must be called after calling Marshall.FinalReleaseCom to make sure reference counts are zero.

    This solution ensured that the windows installer did not associate the files to my app.

    I hope this helps ppl,

    Let me know if anyone needs more info.

    Thanks,

    Matt

    • Marked as answer by MattDendle Friday, January 21, 2011 4:15 PM
    Friday, January 21, 2011 4:15 PM

All replies

  • Update:

    Whatever lock its using, it doesnt appear to prevent me from renaming the file! So its not the type of lock I initially thought it was.  Perhaps its not even a lock at all. (Unless "shadow copies" is doing this - but dont I have to specifically enable that for a drive?)

    I have a feeling that the Restart Manager actually tries to find out which programs have ever called the COM object that is in the dll. Can anyone confirm this?

    I straight-up dont understand what is happening here.

    Please can someone help?

    Thanks,

    Matt

     

    Friday, September 24, 2010 1:39 PM
  • In non-RCW COM, clients call CoFreeUnusedLibraries(Ex) to get them released. I've not been able to find out if or when RCW code might do that, but you could try it from your client anyway.


    Phil Wilson
    Friday, September 24, 2010 9:11 PM
  • I believe Marshal.Release() does this - but it doesnt seem to work :(

    Its not a normal file lock though - because you can rename the file.

    I've tried

    Marshal

     

     

    .ReleaseComObject(instance);

    int

     

     

    referencesRemaining = Marshal.FinalReleaseComObject(instance);

    These calls do not prevent the restart manager from finding that this program "holds" the file it needs to update.

    Can someone tell me what type of lock the Restart Manager is checking for?

    Kind Regards,

    Matt

    Monday, September 27, 2010 8:08 AM
  • After having opened a support case with Microsoft, I have a solution to my problems.

    It turns out that the file was still loaded in my process.  They (Mircosoft) used WinDbg to list the modules that my exe had, and sure enough, the dlls were there.

    The solution comes in two flavours - one for managed COM callable dlls, and the other for unmanaged com dlls.

    For managed COM callable dlls, the solution is to instanciate the object in its own AppDomain, then unload the appdomain, which in turn unloads the dll in question.

    For COM dlls, the solution involved using a pinvoke to CoFreeUnusedLibraries() in the ole32.dll, which releases unused libraries.  This must be called after calling Marshall.FinalReleaseCom to make sure reference counts are zero.

    This solution ensured that the windows installer did not associate the files to my app.

    I hope this helps ppl,

    Let me know if anyone needs more info.

    Thanks,

    Matt

    • Marked as answer by MattDendle Friday, January 21, 2011 4:15 PM
    Friday, January 21, 2011 4:15 PM