Blog du Pôle .NET

Partager pour mieux développer...

Un profiler de mémoire bien sympathique…

clock August 20, 2009 12:23 by author lnyffels

Lors d’un précédent ticket, j’ai brièvement décrit comment invoquer un objet .NET à partir d’un client COM écrit en VB (non managé).

Pour rappel cela se fait par l’intermédiaire d’un wrapper CCW (COM Callable Wrapper). Le CCW est un objet COM non managé qui est créé par le CLR au même titre que l’objet .NET qu’il encapsule. Toutefois, contrairement au client .NET qu'il enveloppe, le wrapper CCW fait l'objet d'un décompte de références selon le mode COM standard. Quand le décompte de références du wrapper CCW atteint zéro, le wrapper libère sa référence à l'objet managé. Un objet managé sans aucune référence restante est collecté lors du cycle garbage collection suivant. (cf. lien msdn suivant : http://msdn.microsoft.com/en-us/library/f07c8z1c.aspx)

 

Aussi, il est nécessaire que le CCW soit « déréférencé » par le client COM VB pour que les objets managés .NET qu’il référence soient également détruits par le garbage collector. Etant de nature plutôt méfiante lorsqu’il s’agit d’interopérabilité COM / .NET et n’étant un as du VB ;-), il me paraissait utile de vérifier cela via un profiler de mémoire. J’avais utilisé il y a quelques années de cela chez un ce mes clients préférés l’utilitaire Optimize-it de Borland. Mais celui-ci n’a semble t’il plus évolué depuis le Framework 1.1. Il en existe beaucoup en .NET mais assez peu sont capables de remonter les objets managés et les objets non managés.   J’en ai trouvé un plutôt sympa qui m’a apporté le service que j’attendais. Il s’agit de « .NET Memory Profiler 3.1 » de la société SciTeck Software (http://memprofiler.com). Le soft m’a permis de m’attacher au processus client, de prendre des photos (snapshot) à différents intervalles et après plusieurs sollicitations je me suis aperçu que les objets .NET étaient bien libérés par le garbage collector. La preuve en 2 images… ;-)  

Snapshot 1 :

Snapshot 2 : 

Conclusion : l’interopérabilité COM / .NET, « ça marche pas pas si mal que cela » !

Laurent Nyffels 

 

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Echanger des collections d’objets via « COM Callable Wrapper »

clock August 19, 2009 12:08 by author lnyffels

Confronté récemment à une problématique d’intéropérabilité VB / .NET, je souhaitais poster ce ticket qui je l’espère pourra servir à certains.

Nous avons tous un jour ou l’autre dû dans nos développements sous .NET invoquer un « vieux » composant COM réalisé en VB6, en C++ ou en Delphi… Cela se fait assez facilement dans Visual Studio 2005 ou 2008, et l’objet COM exposé apparait comme un objet .NET. Ceci est rendu possible grâce au wrapper RCW (Runtime Callable Wrapper) dont la fonction principale est de « marchaliser » les appels entre un client .NET et l’objet COM invoqué.

Mais nous sommes surement moins nombreux à avoir été confronté à la problématique inverse. A savoir, comment exposer un objet .NET à un composant COM existant.

La problématique est moins triviale car un composant COM développé en VB6 ou en C++ unmanaged n’est pas capable de dialoguer nativement avec une assembly .NET.  Il existe heureusement un Wrapper .NET qui permet d’exposer un objet .NET sous la forme d’un composant COM. C’est la fonction du CCW «COM Callable Wrapper ».

 Je ne vais pas dans ce ticket décrire toutes les étapes nécessaires pour réaliser cela, car il existe des liens, notamment sur MSDN qui le font très bien. Cf : http://msdn.microsoft.com/en-us/library/f07c8z1c(VS.71).aspx

Comme souvent, les exemples que l’on trouve nous montrent comment renvoyer une simple chaine de caractères ou un objet. Toutefois, lorsqu’il s’agit de passer une collection d’objets complexes définis en VB6 en paramètre d’une méthode d’une classe .NET ou de renvoyer une collection d’objets cela se complique un peu…

En fait, même si vous avez fait tout ce qu’il faut pour exposer une classe .NET en COM via CCW en décorant votre classe avec les attributs qui vont bien  [GUID()] [ComVible()] etc… et utilisé l’utilitaire Regasm.exe, vous arrivez bien à renvoyer un objet vers votre client COM mais pas une collection de cet objet.

Euh… un petit exemple peut être…

Voilà, je souhaite invoquer la méthode « GetUtilisateur » de  la classe .NET « ProxyUtilisateur  » d’une assembly « ClassProxyRefCOM » exposée en COM  pour qu’elle me renvoie un objet « MappingUtilisateur ».

En VB6, cela donne un truc du genre :

 
Dim oProxyService As ClassProxyRefCOM.ProxyUtilisateur
Dim oMappingUser As ClassProxyRefCOM.MappingUtilisateur
Set oProxyService = CreateObject("ClassProxyRefCOM.ProxyUtilisateur")
Set oMappingUser = oProxyService.GetUtilisateur(UserNT)

Pour se faire, il a fallu nous seulement décorer et exposer la classe ProxyUtilisateur, mais également la classe « MappingUtilisateur » pour qu’elle soit connue comme un objet COM.

En C#, cela donne un truc comme cela :

 

[Guid("3661703D-2BB9-46a2-8723-72B78B7E0390")]

[ComVisible(true)] 

public class MappingUtilisateur : ClassProxyRefCOM.IMappingUtilisateur 

{

     private string _prenom;

     private string _nom;

      private string _email;

        private string _profilNT; 

       public MappingUtilisateur()        {}

       public string Prenom   {    get { return _prenom; }    set { _prenom = value; }        }

       public string Nom        {    get { return _nom; }     set { _nom = value; }        }

        ……  

} 

Au passage, n’oubliez pas de cocher l’option « Register for COM Interop » dans les propriétés de votre projet .NET. Cette option fait la registration de la dll en COM dans la base des registres pour vous et crée le fichier tlb que vous pouvez ensuite utiliser dans Visual Studio 6 en référence de votre projet VB6. Enfin je ne vais pas vous refaire le cours…

Au final cela fonctionne correctement !!!

Toutefois imaginer maintenant que vous vouliez renvoyer une collection d’objet MappingUtilisateur, via une méthode GetListUtilisteurs(). Et bien vous ne pouvez pas exposer en COM une collection d’objets sans passer par une astuce. Celle-ci consiste à exposer un objet qui hérite d’une …. ArrayList .NET.

En C#, cela donne du code du style :

[Guid("F5113128-784F-4125-8AA4-A00F9762C73C")]

 [ComVisible(true)]

 public class MyCollectionCOM :ArrayList

 {

        public MyCollectionCOM() : base()        { }  

       public object GetByIndex(int idx)        return this[idx];   }

       public int NbElem()    {     return this.Count;     }

  }

De ce fait, vous pouvez déclarer un objet « MyCollectionCOM » en VB6 capable de recevoir votre collection de « MappingUtilisateur » :

Dim oProxyService As ClassProxyRefCOM.ProxyUtilisateur 
Set oProxyService = CreateObject("ClassProxyRefCOM.ProxyUtilisateur")
Dim arr As ClassProxyRefCOM.MyCollectionCOM
Set arr = oProxyService.GetListUtilisateurs()

Dans un prochain ticket, je parlerai du mécanisme de libération des objets CCW et .NET et du « profiler » de mémoire qui m’a permis de m’en assurer…

Laurent Nyffels

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Comment « BenchMarker » une application développée avec le .NET Compact Framework ?

clock November 10, 2008 17:01 by author lnyffels

Lors d’une mission récente, j’ai été amené à tester les performances d’une application sur Pocket PC développée en C# avec le .NET Compact Framework 2.0.

L’objectif était de mesurer des temps de réponses et de tester la consommation mémoire de l’application.

1-      Mesure de la consommation et visualisation des objets .NET aloués  

Afin de détecter d’éventuels problèmes de fuite mémoire et d’obtenir des données sur la taille des objets alloués pour l’application, j’ai utilisé l’outil .NET CF Remote Performance Monitor, livré avec le package .NET Compact Framework Power Toys 3.5 de Microsoft.Ces outils gratuits sont disponibles en téléchargement à l’adresse suivante :

   http://www.microsoft.com/downloads/details.aspx?familyid=C8174C14-A27D-4148-BF01-86C2E0953EAB&displaylang=en.

L’outil permet de démarrer l’application sur le Pocket PC depuis votre PC sous Windows et de remonter en temps réel les informations suivantes :

ü   La taille de la mémoire allouée pour l’application par la machine virtuelle

ü   Les objets désalloués par le Garbage Collector

ü   Le nombre d’appels natifs « interop » effectués

ü   Les collections génériques allouées

ü   Le nombre de classes chargées à un instant t

ü   Le nombre de méthodes appelées

ü   Le nombre d’exceptions managées relevées.

ü    

L’option GC Heap Viewer permet également d’obtenir une « photo » à un instant donné des objets .NET alloués par l’application, ainsi que leurs consommations en mémoire (estimés en bytes). Vous pouvez également sauvegarder vos relevés et l’outil permet de faire des comparaisons de nombre d’instances entre deux relevés.

L’outil est simple à prendre en main et peut rendre de très bons services...

2 – Tester les performances d’une méthode ou d’une portion de code

Il peut être nécessaire de marquer une ou plusieurs méthodes dans votre code afin de relever des temps en runtime. Ces temps peuvent être stockés dans un fichier sur le Pocket PC afin d’être exploiter ultérieurement.

Je joins à ce post une classe technique que j’ai utilisée à plusieurs reprises qui stocke des temps marqués dans un fichier xml par section.

public void EcritureFichier() {            BenchMark oBench = new BenchMark("Ecriture_Flash", "FCT_EcritureFichier");            oBench.Begin();            //ON MEMORISE LES INFORMATIONS FLASHE             StringBuilder MyStringBuilder = new StringBuilder();            MyStringBuilder.Append(tabReleve[compteurReleve - 1].CodeIlot.ToString());            MyStringBuilder.Append(";");            MyStringBuilder.Append(tabReleve[compteurReleve - 1].CodeArticle.ToString());                                        oBench.End(); } 

  

L’écriture des temps se fait en mémoire et la sauvegarde physique sur fichier est réalisée via la méthode : BenchMark.SaveBenchDocument(). (Cf. Fichier joint)

Laurent Nyffels 

BenchMark.cs (4,16 kb)

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Des classes utiles pour vos développements avec .NET Compact Framework

clock June 29, 2008 16:22 by author lnyffels

Il n’est pas rare lorsque l’on développe une application sur Pocket PC ou Smartphone avec le .NET Compact Framework d’avoir besoin de faire appel à l’API de Windows CE  pour réaliser certaines tâches. En effet, certaines méthodes ne sont pas encapsulées au sein du Compact Framework  :

-          Connecter le modem GPRS du mobile pour initier une communication

-          Modifier l’horloge interne du PDA pour la synchroniser avec celle du serveur

-          Récupérer l’identifiant unique du PDA (le Device ID)

-          Indiquer l’état de la batterie et la mémoire restante (Présent dans le NET CF 3.5)  

-          Lancer, supprimer ou lister des processus (Présent dans le NET CF 3.5)

Je joins à ce post un ensemble de classes utilitaires que j’ai eu l’occasion d’utiliser au cours de développements sur des plateformes Windows CE et qui je l’espère vous serons utiles.

Laurent Nyffels

ClassesUtiles.zip (6,45 kb)

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Créer une classe AppSettings sur le .NET CF 3.5 avec Linq to XML

clock June 26, 2008 10:11 by author lnyffels

Il y a quelques années j’ai écrit un article sur « codeppc », un site dédié au développement sur plate-forme WinCE. A l’époque, je déplorai l’absence de l’assembly System.Configuration et du fichier de configuration App.config sur le .NET Compact Framework 1.0.

Force est de constater que 6 ans après sa sortie, le Compact Framework 3.5 n’apporte toujours pas cette fonctionnalité pourtant bien pratique qui consiste à pouvoir externaliser des variables dans un fichier XML et de pouvoir les récupérer simplement dans une application sur Pocket PC ou smartphone simplement via une classe technique .NET. Heureusement, il en fournit bien d’autres…

Le Compact Framework de l’époque offrait toutefois la possibilité de manipuler une source XML à travers l’assembly System.Xml et nous pouvions assez facilement recréer une classe technique pour manipuler un fichier de type App.Config   (cf. http://www.codeppc.com/articles/sde2/sde2.htm ).

Aujourd’hui, le .NET CF 3.5 permet d’utiliser la technologie  Linq to Object et Linq to XML pour construire, lire et modifier une source XML.

Je me suis donc amusé avec les classes XDocument et XElement de Linq to Xml pour simuler le comportement  de la classe ConfigurationSettings du framework .NET et de la propriété AppSettings.   

Pour se faire, je propose d’externaliser cette classe dans une assembly ConfigurationManager.dll en créant un projet SmartDevice de type Class Library dans Visual Studio 2008.

Créons au sein de cette classe une propriété statique permettant de récupérer le chemin de l’app.config déployer sur le PPC.

 

 

Remarquer l’utilisation de la « réflexion » pour récupérer le répertoire de l’assembly en cours d’éxécution. Bon OK, la lignede code est un peu longue… mais bon, elle est fun, non ? Nous allons ensuite créer une méthode statique AppSettings permettant de récupérer la valeur de l’attribut value de l’élément <add> en passant le nom de la clé (attribut key) en paramètre  de la méthode 

<?xml version="1.0" encoding="utf-8" ?><configuration>  <appSettings>    <add key="dossier_exercices" value="C:\exo\questions"/>    <add key="dossier_corrections" value="C:\exo\corrections"/>  </appSettings></configuration>

La première étape consiste à charger le fichier App.Config avec la classe XDocument. Ensuite, on applique une simple requête Linq pour récupérer l’ensemble des éléments <add> comportant la clé choisie. Il suffit ensuite de récupérer l’attribut value qui est le dernier de l’élement add à travers un foreach.

 

Ajouter à cela quelques vérifications d’usages des valeurs passées en paramètre et un try – catch pour générer les éventuelles erreurs et le tour est joué ! Exemple de l’appel à la méthode au sein de l’application est le suivant :

String valeur = ConfigurationSettings.AppSettings("dossier_exercices")

Pour obtenir plus d’informations sur Linq je vous engage à parcourir le site msdn sur le sujet et à suivre le maître inconstesté : Anders Hejlsberg.

http://msdn.microsoft.com/en-us/netframework/aa904594.aspx

Laurent Nyffels

SmartTestLinqXML.zip (49,81 kb)

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Calendrier

<<  July 2010  >>
MoTuWeThFrSaSu
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678
Afficher en pleine page

Visiteurs