Do COM Dll References Require Manual Disposal? If so, How?
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 applica开发者_开发问答tion 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.)
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.
You are exactly right: unmanaged code cannot be managed and thus needs to be managed by hand: disposed of. However, this greatly depends on what you are doing, but in many cases, it is sufficient to wrap the object instantiation around a Using-block. This only works if you use an object that implements IDisposable
.
However, the way you currently create an instance of a COM object, you will not have the possibility to clean up easily. It depends on the object. When it doesn't need cleaning up (check the destructor of FwMgr), it doesn't need disposing either. However, most COM objects do need disposal.
So, how to add the IDisposable
interface to a COM object that doesn't natively support it? It's a bit of work to do so manually, but you should create a wrapper .NET assembly. Luckily, the work has been taken out of our hands and Microsoft has created some tools and guidelines.
Some of this information is covered here too. You may want to also look up WeakReference as an alternative.
Note that COM and .NET do not talk well together, but they do talk. An excellent reference is .NET and COM The Complete Interoperability Guide by Don Box, SAMS Publishing.
EDIT:
In answer to your "memory leak" question: it is impossible to tell whether you introduced a memory leak, and how big it is. It depends on how often you call your COM object. Call it once per running process? Don't worry too much. Call it hundredths of times in an inner loop? Be very careful. Want to know for sure? Lookup the original documentation or source: if it releases handles, memory or other resources when it is destructed, then yes, you introduced a leak.
精彩评论