views:

50

answers:

2

I have written some code in VB that verifies that a particular port in the Windows Firewall is open, and opens one otherwise. The code uses references to three COM DLLs. I wrote a WindowsFirewall class, which Imports the primary namespace defined by the DLLs. Within members of the WindowsFirewall class I construct some of the types defined by the DLLs referenced. The following code isn't the entire class, but demonstrates what I am doing.

Imports NetFwTypeLib
Public Class WindowsFirewall
    Public Shared Function IsFirewallEnabled as Boolean
        Dim icfMgr As INetFwMgr
        icfMgr = CType(System.Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwMgr")), INetFwMgr)

        Dim profile As INetFwProfile
        profile = icfMgr.LocalPolicy.CurrentProfile

        Dim fIsFirewallEnabled as Boolean
        fIsFirewallEnabled = profile.FirewallEnabled

        return fIsFirewallEnabled
    End Function
End Class

I do not reference COM DLLs very often. I have read that unmanaged code may not be cleaned up by the garbage collector and I would like to know how to make sure that I have not introduced any memory leaks. Please tell me (a) if I have introduced a memory leak, and (b) how I may clean it up.

(My theory is that the icfMgr and profile objects do allocate memory that remains unreleased until after the application closes. I am hopeful that setting their references equal to nothing will mark them for garbage collection, since I can find no other way to dispose of them. Neither one implements IDisposable, and neither contains a Finalize method. I suspect they may not even be relevant here, and that both of those methods of releasing memory only apply to .Net types.)

A: 
Abel
+1  A: 

Not sure what to recommend here. There is most definitely no memory leak here, the garbage collector releases COM reference counts. COM objects are not disposable but you can release them early with Marshal.ReleaseComObject(). The trouble with doing this explicitly is that it is normally very hard to track interface references.

In your code snippet for example, calling ReleaseComObject on the icfMgr won't have any effect. There's a hidden reference through the LocalPolicy member that will keep the interface reference alive. You'd have to call ReleaseComObject on that hidden reference as well.

I would not recommend making this a practice at all. Getting it wrong produces hard to diagnose failure, you're essentially back to the bad old days of explicit memory management. But it is somewhat manageable in your specific example.

Hans Passant