2010-06-01 13 views
2

J'ai écrit du code dans VB qui vérifie qu'un port particulier dans le pare-feu Windows est ouvert, et ouvre un autre dans le cas contraire. Le code utilise des références à trois DLL COM. J'ai écrit une classe WindowsFirewall, qui importe l'espace de noms principal défini par les DLL. Au sein des membres de la classe WindowsFirewall, je construis certains des types définis par les DLL référencées. Le code suivant n'est pas la classe entière, mais montre ce que je fais.Les références COM Dll nécessitent-elles une élimination manuelle? Si c'est le cas, comment?

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 

Je ne référence pas les DLL COM très souvent. J'ai lu que le garbage collector ne nettoie pas le code non géré et je voudrais savoir comment m'assurer que je n'ai pas introduit de fuites de mémoire. S'il vous plaît dites-moi (a) si j'ai introduit une fuite de mémoire, et (b) comment je peux le nettoyer.

(En théorie, les objets icfMgr et profile allouent de la mémoire qui reste inédite jusqu'à la fermeture de l'application. Ni l'un ni l'autre n'implémente IDisposable, ni l'un ni l'autre ne contient une méthode Finalize Je suppose qu'ils ne sont peut-être pas pertinents ici, et que ces deux méthodes de libération de mémoire s'appliquent uniquement aux types .Net.)

Répondre

2

Vous ne savez pas quoi recommander ici. Il n'y a absolument aucune fuite de mémoire ici, le garbage collector libère des comptes de référence COM. Les objets COM ne sont pas jetables mais vous pouvez les libérer tôt avec Marshal.ReleaseComObject(). Le problème avec cela explicitement est qu'il est normalement difficile de suivre les références d'interface.Dans votre extrait de code, par exemple, l'appel de ReleaseComObject sur icfMgr n'aura aucun effet. Il y a une référence cachée par le membre LocalPolicy qui gardera la référence d'interface en vie. Vous devrez également appeler ReleaseComObject sur cette référence cachée.

Je ne recommanderais pas de faire une pratique du tout. Il est difficile de diagnostiquer l'échec en se trompant, vous revenez essentiellement au mauvais vieux temps de la gestion de la mémoire explicite. Mais c'est un peu gérable dans votre exemple spécifique.

0

exactement exact: le code non géré ne peut pas être géré et doit donc être géré à la main: éliminé. Cependant, cela dépend beaucoup de ce que vous faites, mais dans de nombreux cas, il suffit d'enrouler l'instanciation de l'objet autour d'un bloc Using. Cela ne fonctionne que si vous utilisez un objet qui implémente IDisposable.

Cependant, la façon dont vous créez actuellement une instance d'un objet COM, vous n'aurez pas la possibilité de nettoyer facilement. Cela dépend de l'objet. Quand il n'a pas besoin d'être nettoyé (vérifiez le destructeur de FwMgr), il n'a pas besoin de s'en débarrasser. Cependant, la plupart des objets COM doivent être éliminés. Donc, comment ajouter l'interface IDisposable à un objet COM qui ne le supporte pas nativement? C'est un peu de travail à faire manuellement, mais vous devriez créer un encapsuleur .NET. Heureusement, le travail a été retiré de nos mains et Microsoft a créé quelques tools and guidelines.

Certaines de ces informations sont covered here too. Vous pouvez également rechercher WeakReference comme alternative.

Notez que COM et .NET ne parlent pas bien ensemble, mais ils parlent. Une excellente référence est .NET et COM Le Guide complet d'interopérabilité par Don Box, SAMS Publishing.

EDIT:
En réponse à votre question « de fuite de mémoire »: il est impossible de dire si vous avez introduit une fuite de mémoire, et la façon dont elle est grande. Cela dépend de la fréquence à laquelle vous appelez votre objet COM. Appelez-le une fois par processus en cours? Ne t'inquiète pas trop. Appelez-le des centièmes de fois dans une boucle interne? Soyez très prudent. Voulez-vous savoir à coup sûr? Recherchez la documentation ou la source d'origine: si elle libère des handles, de la mémoire ou d'autres ressources lorsqu'elle est détruite, alors oui, vous avez introduit une fuite.