Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

Snippet Designer : un plugin VS 2008 à posséder !

Les snippets de code Visual Studio vous connaissez certainement. Ce sont des modèles (petits ou grands) de code qui peuvent contenir des zones personnalisables et qui économisent beaucoup de frappe...
Créer des Snippets n'est en revanche pas toujours très simple ou très commode.

C'est pourquoi je vous conseille un petit plugin bien sympathique, "SnipperDesigner".
Cet outil est téléchargeable sur CodePlex :


http://www.codeplex.com/SnippetDesigner

Les étapes pour son utilisation une fois l'outil installé se trouvent résumées ici.



image

C'est tout simple, facile, gratuit, et ça peut faire gagner beaucoup de temps...

Bon Dev ... Et Stay Tuned !


Améliorer le debug sous VS avec les proxy de classes

Visual Studio est certainelement l'IDE le plus complet qu'on puisse rêver et au-delà de tout ce qu'il offre "out of the box" il est possible de lui ajouter de nombreux add-ins (gratuits ou payants) permettant de l'adapter encore plus à ses propres besoins. Ainsi vous connaissez certainement les "gros" add-ins comme Resharper dont j'ai parlé ici quelque fois ou GhostDoc qui écrit tout seul la doc des classes. Vous connaissez peut-être les add-ins de debogage permettant d'ajouter vos propres visualisateurs personnalisés pour le debug. Mais vous êtes certainement moins nombreux à connaître les proxy de classes pour le debug (Debugger Type Proxy).

A quoi cela sert-il ?

Tout d'abord cela n'a d'intérêt qu'en mode debug. Vous savez que lorsque vous placez un point d'arrêt dans votre code le debugger de VS vous permet d'inspecter le contenu des variables. C'est la base même d'un bon debugger.

La classe à deboguer 

Supposons la classe Company suivante décrivant une société stockée dans notre application. On y trouve trois propriétés, le nom de la société Company, l'ID de la société dans la base de données et la date de dernière facturation LastInvoice :

public class Customer
        {
            private string company;
            public string Company
            {
                get { return company; }
                set { company = value; }
            }
 
            private int id;
            public int ID
            {
                get { return id; }
                set { id = value; }
            }
 
            private DateTime lastInvoice;
            public DateTime LastInvoice
            {
                get { return lastInvoice; }
                set { lastInvoice = value; }
            }
        }

 

Le debug "de base" 

Supposons maintenant que nous placions un point d'arrêt dans notre application pour examiner le contenu d'une variable de type Customer, voici que nous verrons :

Le debugger affiche toutes les valeurs connues pour cette classe, les propriétés publiques comme les champs privés. Il n'y a que 3 propriétés et 3 champs dans notre classe, imaginez le fatras lorsqu'on affiche le contenu d'une instance créée depuis une classe plus riche ! Surtout qu'ici, pour tester notre application, ce dont nous avons besoin immédiatement ce sont juste deux informations claires : le nom et l'ID de la société et surtout le nombre de jours écoulés depuis la dernière facture. Retrouver l'info parmi toutes celles affichées, voire faire un calcul à la main pour celle qui nous manque, c'est transformer une session de debug qui s'annonçait plutôt bien en un véritable parcours du combattant chez les forces spéciales !

Hélas, dans la classe Customer ces informations sont soit éparpillées (nom de société et ID) soit inexistantes (ancienneté en jours de la dernière facture).

Il existe bien entendu la possibilité de créer un visualisateur personnalisé pour la classe Customer et de l'installer dans les plug-ins de Visual Studio. C'est une démarche simple mais elle réclame de créer une DLL et de la déployer sur la machine. Cette solution est parfaite en de nombreuses occasions et elle possède de gros avantages (réutilisation, facilement distribuable à plusieurs développeurs, possibilité de créer un "fiche" complète pour afficher l'information etc).

Mais il existe une autre voie, encore plus simple et plus directe : les proxy de types pour le debugger.

Un proxy de type pour simplifier

A ce stade du debug de notre application nous avons vraiment besoin du nombre de jours écoulés depuis la dernière facture et d'un moyen simple de voir immédiatement l'identification de la société. Nous ne voulons pas créer un visualisateur personnaliser, mais nous voulons tout de même une visualisation personnalisée...

Regardons le code de la classe suivante :

public class CustomerProxy
        {
            private Customer cust;
 
            public CustomerProxy(Customer cust)
            {
                this.cust = cust;
            }
 
            public string FullID
            {
                get { return cust.Company + " (" + cust.ID + ")"; }
            }
 
            public int DaysSinceLastInvoice
            {
                get { return (int) (DateTime.Now - cust.LastInvoice).TotalDays; }
            }
        }

 

la classe CustomerProxy est très (très) simple : elle possède un constructeur prenant en paramètre une instance de la classe Customer puis elle expose deux propriétés en read only : FullID qui retourne le nom de la société suivi de son ID entre parenthèses, et le nombre de jours écoulés depuis la dernière facture.

Nota: Ce code de démo ne contient aucun test... dans la réalité vous y ajouterez des tests sur null pour éviter les exceptions si l'instance passée est nulle, bien entendu.

Vous allez me dire, c'est très joli, ça fait une classe de plus dans mon code, et comment je m'en sers ? je ne vais pas modifier tout mon code pour créer des instances de cette classe cela serait délirant !

Vous avez parfaitement raison, nous n'allons pas créer d'instance de cette classe, nous n'allons pas même modifier le code de l'application en cours de debug (ce qui serait une grave erreur... modifier ce qu'on test fait perdre tout intérêt au test). Non, nous allons simplement indiquer au framework .NET qu'il utilise notre proxy lorsque VS passe en debug... Un attribut à ajouter à la classe originale Customer, c'est tout :

#if (DEBUG)
        [System.Diagnostics.DebuggerTypeProxy(typeof(CustomerProxy))]
#endif
        public class Customer
        {
            //...
        }

Vous remarquerez que pour faire plus "propre" j'ai entouré la déclaration de l'attribut dans un #if DEBUG, cela n'est absolument pas obligatoire, j'ai fait la même chose autour du code de la classe proxy. De ce fait ce code ne sera pas introduit dans l'application en mode Release. Je vous conseille cette approche malgré tout.

Et c'est fini !

Le proxy en marche

Désormais, lorsque nous sommes en debug que nous voulons voir le contenu d'une instance de la classe Customer voici ce que Visual Studio nous affiche :

 

Vous remarquez immédiatement que le contenu de l'instance de la classe Customer n'est plus affiché directement mais en place et lieu nous voyons les deux seules propriétés "artificielles" qui nous intéressent : le nom de société avec son ID, et le nombre de jours écoulés depuis la dernière facture. Fantastique non ? !

"Et si je veux voir le contenu de Customer malgré tout ?" ... Je m'attendais à cette question... Regardez sur l'image ci-dessus, oui, là, le petit "plus" dans un carré, "Raw View"... Cliquez sur le plus et vous aurez accès au même affichage de l'instance de Customer qu'en début d'article (sans le proxy) :

 

Conclusion

Si ça c'est pas de la productivité et de la customisation aux petits oignons alors je suis à court d'arguments ! :-)

Bon debug !

... Et Stay Tuned !

le projet de test : DebugProxy.zip (5,55 kb)

Blend 2 n'appelle pas VS 2008 mais VS 2005 : la solution [edit]

Voilà un truc agaçant : vous possédez les derniers softs de la dernière technologie de la mort-qui-tue et voila que pour créer le gestionnaire du "click" d'un bouton dans Blend 2 ce dernier vous dit que vous n'avez pas Visual Studio et qu'il a copié le code dans le presse-papiers. Il va falloir lancer à la main VS 2008, ouvrir le fichier cs qui va bien et faire un "coller" à la mimine. Back to the préhistoire ? Non : bug.

En fait ce bug est de type "registry". Lorsque VS s'installe il renseigne une clé de la registry qui indique son CLSID. Ainsi, les autres produits MS peuvent savoir quelle version de VS appeler. C'est simple et c'est bien vu. ... sauf qu'il manque un petit test pour s'assurer qu'on ne "régresse" pas dans les versions par exemple. Et c'est le cas si vous avez installer SQL Server 2005 après VS 2008.

Je parle de la version complète, pas la version Express de SQL Server 2005, la version qui installe... VS 2005 pour BIDS notamment. Et dans ce cas, la dernière version installée de VS est bien 2005 qui joyeusement et sans rien tester colle son CLSID à la place de celui de VS 2008. Moralité, soit Blend 2 appelle VS 2005 (ce qui est dommage pour le support du framework 3.5 !), soit vous avez désinstallé VS 2005 et Blend 2 ne le voyant pas (et ne cherchant pas VS 2008) vous propose de coller vous même le code du gestionnaire d'événement qu'il vient de créer...

C'est un bel exemple qui illuste à quel point tout informaticien doit rester humble même lorsqu'il a créé une application extraordinaire... ça finira toujours par péter à la figure de quelqu'un, un jour, exhibant alors un odieux bug, le vilain petit grain de sable dans la belle mécanique...

C'est donc le cas ici, malgré la qualité fantastique de Visual Studio et de Blend, et pour un petit bug dans une séquence mineure (écrite par un stagiaire, allez savoir), c'est tout l'extraordinaire édifice créé par ces deux outils qui s'écroule en partie au moins, faisant régresser "l'expérience utilisateur" (la mienne en l'occurence!) à la préhistoire des OS fenêtrés où bien avant COM ou autre DDE encore plus primitif, la seule façon de faire "communiquer" deux applications était le copier/coller !

On notera que ce petit bug serait sans conséquence si Blend prévoyait dans ses réglages le choix de la version de VS à utiliser. Et ici nous avons une autre démonstration : une mauvaise analyse ou réalisation d'une partie accessoire du logiciel (le paramétrage dans ce cas) met en évidence un bug qui aurait pu être masqué. Leçon à retenir : tout logiciel qui doit en appeler d'autres ou faire référence à des "objets" (au sens le plus large) externes doit absolument posséder dans ses réglages un moyen de dire quels sont ces applications ou ces objets et à quel endroit les trouver. Pan sur le doigts des développeurs de Blend :-)

Un bug dans le setup de VS + Un manquement à cette dernière "best practice" et c'est le mariage entre deux outils complémentaires qui se transforme en un divorce !

En farfouinant, j'ai trouvé la solution. Elle consiste tout simplement à trouver cette fameuse entrée de la registry ou VS indique son CLSID, entrée qui est utilisée par Blend notamment pour savoir comment appeler VS. Ensuite il faut connaître le CLSID de VS 2008 pour le mettre à la place de celui de VS 2005. Une fois qu'on a ces deux informations et qu'on effectue la correction, Blend 2 lance à nouveau VS 2008 automatiquement lorsqu'il créé un gestionnaire d'événement. Ouf !

Et comme je ne suis pas vache, après vous avoir fait la morale sur les bugs et les dialogues de paramétrage des applications, je vais vous donner cette fameuse entrée de registry et ce fameux CLSID... Roulement de tambour... And the winner is.....

changer la valeur de HKEY_CLASSES_ROOT\VisualStudio.DTE\CLSID 
en {1A5AC6AE-7B95-478C-B422-0E994FD727D6}

C'est tout. Bon, sauvegardez votre registry avant de faire la manip, je ne suis pas responsable si ça ne change rien chez vous, et je ne veux rien savoir si après la modif votre ordinateur ne boote plus ou que votre femme part vivre en Alaska avec votre soeur alors même que vous apprenez que votre père est le facteur et toutes ces considérations légales qu'on ajoute généralement dès qu'on donne un conseil qui demande à toucher à la registry. Vous êtes prévenu ! :-)

Et Stay Tuned !

[EDIT 20-9-08]
La solution fonctionnait mais quand j'ai refait la manip le lendemain, un double-click sur un .cs dans un projet sou Blend 2 m'ouvrait le fichier dans le bloc-notes... Et plus de liaison avec VS 2008. Grrrrr.

En (re)farfouillant, j'ai modifié deux autres petites choses qui semblent (en plus de la manip déjà décrite), cette fois-ci, apporter une réponse complète :

  1. Vérifier que les fichiers .cs sont bien associés à "Microsoft Visual Studio Version Selector", le double-click sous Blend semble utiliser les associations de fichier de Windows plutôt que le système de CLSID de la registry.
  2. Dans la clé HKEY_CLASSES_ROOT\VisualStudio.DTE évoquée plus haut, outre l'entrée CLSID il faut aussi mettre l'entré CurVer en conformité, elle doit contenir VisualStudio.DTE.9.0 et non pas la même chose avec 8.0 (VS 2005).

Voici le résultat final (exportation de branche depuis regedit) :

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\VisualStudio.DTE]
@="Microsoft Visual Studio DTE Object"

[HKEY_CLASSES_ROOT\VisualStudio.DTE\CLSID]
@="{1A5AC6AE-7B95-478C-B422-0E994FD727D6}"

[HKEY_CLASSES_ROOT\VisualStudio.DTE\CurVer]
@="VisualStudio.DTE.9.0"

Voilà... En espérant que cela aidera quelques âmes égarées sur la toile en quête d'une réponse à ce problème...
[/EDIT]

Déboguer simplement : les points d'arrêt par code

Voici une astuce toute simple comme je les aime mais qui rend bien des services !

Lorsqu'on débogue une application on utilise fréquemment les points d'arrêt notamment lorsqu'on soupçonne un problème dans une partie de code précise. Tous les développeurs connaissent les points d'arrêt et savent s'en servir. Il est déjà plus rare de voir un développeur se servir des points d'arrêt conditionnels, pourtant un simple clic-droit sur le rond rouge dans la marge (symbolisant le point d'arrêt) permet de fixer une condition liée au code ou au nombre de passages par exemple. Il existe d'autres possibilités d'une grande richesse et si vous ne les connaissez pas, au moins une fois pour voir, faites un clic droit sur un point d'arrêt et jouez un peu avec les options, vous comprendrez alors comment vous auriez pu gagner des minutes ou des heures précieuses si vous aviez connu cette astuce plus tôt !

Mais ce n'est pas des points d'arrêt conditionnels que je voulais vous parler aujourd'hui mais d'une autre astuce encore moins connue / utilisée : les points d'arrêt par code.

En effet, le debugger de Visual Studio peut, en partie, être contrôlé par le code lui-même en utilisant la classe Debugger de l'espace de noms System.Diagnostics.

Les méthodes statiques de cette classe permettent par exemple de savoir si le debugger est lancé ou non, voire de lancer s'il n'est pas actif. La méthode Break() quant à elle permet simplement de faire un point d'arrêt et c'est elle qui nous intéresse ici.

Plutôt que d'attendre qu'une exception soit levée, de revenir dans le code, de placer un point d'arrêt et de relancer l'application en espérant que "ça plante" de la même façon, il est plus facile de prévoir d'emblée le point d'arrêt là où il existe un risque d'y avoir un problème, notamment en phase de mise au point d'un code. Un simple Debugger.Break(), dès qu'il sera rencontré lors de l'exécution, aura le même effet qu'un point d'arrêt inconditionnel placé dans Visual Studio. Bien entendu, le break peut être programmer selon un test (valeur non valide d'une propriété par exemple). Dans un tel cas dès que l'application rencontrera le break elle déclenchera le passage en mode debug sur le "point d'arrêt" ainsi défini. Le développeur peut se dégager l'esprit pour d'autres tâches de test, dès que le break sera rencontré VS passera en debug immédiatement sans risque de "louper" le problème ou de le voir trop tard et de ne plus avoir accès à certaines variables.

un petit exemple :

class Program
{
   static void Main(string[] args)
   { 
       var list = new List<Book>
       {   new Book {Title = "Livre 1", Year = 1981},
           new Book {Title = "Livre 2", Year = 2007},
           new Book {Title = "Livre 3", Year = 2040} };

foreach (var book in list) { Console.WriteLine(book.Title+" "+book.Year); }
}

class Book
{
   private int year;

   public string Title { get; set; }
   public int Year
  { get { return year; }
     set {
              if (value > 1980 && value < DateTime.Now.Year) year = value;
              else Debugger.Break();
                   // throw new Exception("L'année " + value + " n'est pas autorisée");
           }
   }
}

Lors de l'initialisation de la collection "list" dans le Main(), l'année du troisième livre (2040) déclenchera le break. On pourra alors directement inspecter le code et savoir pourquoi ce "logiciel" plante dès son lancement...  On voit qu'ici j'ai mis en commentaire l'exception qui sera lancée par la version "finale" du code. A sa place j'ai introduit l'appel à Break(). Rien à surveiller. Si le problème vient de là (ce qui est le cas ici) VS passera tout seul en debug...

C'est pas chouette ça ?

Alors Stay Tuned !

 

 

 

Astuce du jour : déboguer du code sans écrire de code de test

Il arrive souvent (ou il devrait souvent arriver...) qu'on veuille tester rapidement du code. Par exemple vérifier qu'une méthode retourne bien le bon résultat selon deux ou trois variantes des paramètres d'entrée. Mais écrire du code de test à chaque fois, même si "on devrait" le faire tout le temps, n'est pas totalement conforme à la réalité. On a plus souvent la pression que la bride sur le collier et cela impose de travailler bien, mais vite !

Alors une petite astuce rapide pour aujourd'hui. La fenêtre Immediate de VS 2008 offre un moyen simple d'invoquer du code et de tester rapidement une méthode. Peut-être connaissez-vous cette fonction de VS dans ce cas j'espère juste vous avoir rafraichi la mémoire pour vous en servir plus souvent !

Je ne connais pas le nom en français de cette fenêtre car j'utilise un VS en US. Mais vous trouverez facilement.

Une des façons rapides de l'appeler est d'utiliser le raccourci vers la fenêtre Command et de taper "immed" ce qui ouvre la fenêtre Immediate. La fenêtre Command s'appelle par Ctrl-Alt-A (vérifiez si en français le raccourci est le même).

Bien entendu pour invoquer du code il faut être en debug. Soit vous avez un point d'arrêt quelque part et vous attendez d'y être arrivé, soit vous pouvez lancer l'application par F10 (step over) au lieu de F5, cela s'arrêtera tout de suite sur le Main. Là, tapez Ctrl-Alt-A puis "immed" si la fenêtre Immediate n'est pas déjà affichée. Et il ne reste plus qu'à taper votre code de test... Vous disposez de Intellisence et de toute l'aide, c'est pas merveilleux ? !

En image pour voir de quoi il s'agit (la qualité de la capture est mauvaise en raison de la réduction à 80% et de la compression jpeg, j'essaye de ne pas trop grossir les flux RSS des abonnés au blog...) :

La fenêtre Immediate, c'est facile, rapide, puissant. Autant s'en servir !

Bon Dev

...Et Stay Tuned !

How Do I ? - Les vidéos Microsoft pour bien se lancer

Dans la jungle épaisse de MSDN on trouve des milliers de choses passionnantes, souvent par hasard car par définition une jungle est inextricable et MSDN n'échappe pas à la règle... Il est d'ailleurs parfois plus rapide et plus sûr de chercher une info dans Google pour trouver le lien dans MSDN que de chercher directement dans ce dernier ! Et pourtant... Cette jungle cache de nombreux trésors qui ne s'offrent qu'aux intrépides aventuriers osant s'enfoncer dans la moiteur tiède de l'information, sautant de lien-lianne en lien tel un Tarzan numérique...

Bon trève de plaisanterie, j'en reviens à l'essentiel : "Comment je fais ?".

Comment je fais "quoi" ? Allez-vous rétorquer. Tout. Plein de choses. Par exemple, Comment j'utilise l'Entity Framework, Comment je commence avec ADO.NET Data Service, Comment j'utilise le control LinqDataSource, Comment j'utilise le DataSet en multi-tiers ? Etc, etc.

Pour toutes ces questions il existe en réponse une vidéo, claire, expliquant par l'image et la parole ce qu'il faut savoir.

Bien entendu tout cela est en anglais et en concernera donc que les lecteurs capables de suivre une démo dans cette langue sans en perdre les trois quarts.

Si vous faites partie des heureux anglophones à qui ce genre de média ne fait pas peur, rendez vous sur la page des "How Do I?"...

[EDIT]
Le lien que je donne concerne les "How Do I" des données. Sylvain dans son commentaire à ce billet donne un autre lien concernant la série "How Do I" pour ASP.NET.
En fouillant sur MSDN on peut aussi trouver une série pour le "Native Coding" (C++ Win32), une autre pour Visual Studio, ou pour les Devices (Compact Framework), ou encore Office et les XML API, etc.

Toutes les séries "How Do I" ne sont pas forcément dotées de vidéos, en revanche, à la page suivante vous trouverez la liste de toutes les vidéos "How Do I" quel que soit le sujet abordé (à ce jour : ASP.NET, Ajax, Devices, Native Coding, Security, Silverlight, VB, VS, VS tools for Office, VSTS, Windows Forms, WPF).
[/EDIT]

 

Bonne vidéos

et Stay Tuned !

La guerre des clones n'aura pas lieu ! ... Si vous possédez Clone Detective !

Clone Detective pour Visual Studio est un outil de debug un peu particulier puisqu'il ne cherche pas les bugs mais les redondances de code.

La redondance de code est un ennemi sournois... Le code dupliqué est bien souvent la porte ouverte aux inconsistances et aux regressions lors de mises à jour correctives ou évolutives. En effet, si un bug apparaît un jour dans une séquence mais qu'il n'a pas encore été repéré dans une autre fonction qui utilise pourtant un code similaire, la mise à jour ne concernera que la séquence incriminée. Un jour où l'autre la partie codée de façon similaire plantera aussi pour les mêmes raisons. Elle ne sera d'ailleurs peut être pas corrigée de la même façon ni par la même personne... Inconsistance. Coûts de maintenance inutiles. Les défauts de la redondance de code ne manque donc pas.

D'ailleurs un outil capable de retrouver ces fameux clones est un excellent assistant pour un auditeur... La présence des clones trahit non pas celle de Palpatine ou du comte Doku mais bien d'un code for mal refactoré, donc pauvre et qui laissera par force voir d'autres faiblesses !

Précisons que Clone Detective cherche les "clones", pas seulement le code purement redondant de type copier/coller. Il analyse le code en supprimant les commentaires, les espaces, les noms de variables etc, afin d'obtenir un code de référence le plus générique possible avant d'y chercher les clones. Les clones formes des classes de code équivalent, l'un pourrait remplacer l'autre sans problème, à la présentation et aux noms de variables près.

Il s'agit donc bien d'une recherche intelligente et non simplement d'une recherche de "doublons". Mais la lecture de la documentation de CD vous en dira bien plus que ces quelques lignes.

Donc pour se prémunir des dommages causés par les clones, et si on ne connait pas le numéro de portable de Yoda, le mieux est encore de télécharger Clone Detective. Bonne nouvelle il n'habite pas une galaxie lointaire, il est sur CodePlex et donc gratuit avec le code source pour les curieux ! Mieux, C.D. s'insère dans VS 2008 (voir / autres fenêtres, pour afficher celles de C.D. une fois installé). Vraiment un bel add-in dont il serait bête de se priver !

Pour accéder à la page de chargement, cliquez simplement sur le logo de Clone Detective inséré plus haut dans le corps de ce billet.

Que la force soit avec vous !

(et Stay Tuned !)

Déboguer plusieurs projets simultanément sous VS 2008

Lorsqu'on travaille sur une solution comportant plusieurs projets il s'avère souvent utile de pouvoir lancer plusieurs projets en même temps, par exemple s'ils communiquent ensemble ou bien si les résultats de l'un peuvent influencer ceux de l'autre.
Il est certes toujours possible de lancer "à la main" depuis l'explorateur les projets "de fond" puis de lancer en mode debug le projet à déboguer. Mais cela n'est ni pratique ni totalement satisfaisant, en cas de bug dans l'un des projets "secondaires", aucun moyen de savoir ce qu'il se passe.

Il existe pourtant une solution simple...

Voici comment procéder :

  1. Clic droit dans l'explorateur de solution, sur la solution.
  2. Choisir Propriétés
  3. Aller à la page "startup project page" (désolé j'ai un VS en US. Mais c'est la 1ere page du dialogue normalement)

Vous allez voir trois boutons radio :

  • Current Selection (sélection courante)
  • Single startup projet (mode habituel, 1 seul projet lancé au debug)
  • Multiple startup projects (mode multi projets)

Pour chaque projet de la solution, une fois le mode multi projets activé, vous pouvez choisir ce que VS doit faire lorsque le debug est lancé (F5). Un projet peut ne pas être exécuté (par défaut), démarré ou démarré sans debug. La figure ci-dessous montre ces diverses options.

 

Une fois le dialogue validé, en tapant F5 tous les projets sélectionnés sont exécutés dans le mode que vous avez choisi... Les projets démarrés en mode debug peuvent tous être inspecté, avoir des points d'arrêts, etc.

C'est pas fantastique ça ?

Alors pour d'autres nouvelles, Stay Tuned !

Nouveau tutorial : RDL et ReportViewer, une solution gratuite de génération d'état

RDL ? Cela ne vous dit rien ? SSRS ou BIDS non plus ? Et le composant gratuit de Microsoft ReportViewer ? Rien ? ... Alors il faut que vous lisiez absolument ce nouveau tutorial (PDF, 30 pages + exemples VS 2008) que je viens de mettre en ligne !

Il existe en effet une solution gratuite et plus que performante pour générer des états, elle se cache dans Visual Studio et un peu aussi dans les méandres des sites Microsofts pour télécharger "ReportViewer" qui fonctionne sous VS 2005 et VS 2008.

Cette solution est plus qu'honorable : sous-états, états avec noeuds dépliables, prévisualisation avec recherche de texte, fonctionnant sous Windows Forms et sous ASP.NET, utilisant toutes les sources de données possibles dont les grappes d'objets en mémoire, capable de produire des PDF, des fichiers Excel... Le tout gratuitement et assez facilement.

Rêve éveillé ? Non... mais en revanche, et pour des raisons que j'ignore, cette solution est méconnue. Elle mérite bien un tutor pour rétablir la justice (et vous faire économiser l'achat d'un générateur qui n'en fera peut-être pas la moitié) !

L'article RDL et ReportViewer est à télécharger en suivant le lien ou bien en se rendant sur www.e-naxos.com page Publications, rubrique Divers.

Bonne lecture ... et Stay Tuned !

[Vous pouvez aussi lire cet autre billet sur les best practices de RDL]

Astuce : reformater une chaîne sur plusieurs lignes (comme une requête SQL par exemple)

Il arrive souvent qu'on ait besoin de faire un copier-coller d'une chaine de caractères fractionnée en plusieurs lignes. Qu'il s'agisse d'un bout de texte avec des retours à la ligne ou bien par exemple une requête SQL, s'il y a beaucoup de lignes la mise en forme est fastidieuse. Il faut indenter chaque ligne, mettre des guillemets au début et à la fin, ajouter un "+" à chaque ligne... C'est vraiment le genre de chose qui coupe l'élan en plein milieu du codage d'une méthode.

Mais il existe une solution simple, très simple même, qui fait intervenir le chercher/remplacer de Visual Studio avec deux mini expressions régulières, tellement petites que même si vous êtes réfractaire aux ER je suis sûr que celles là vous les noterez et les utilisez !

Acte 1 : une belle requête

Supposons une requête ni trop petite ni trop grosse, pour notre exemple, par exemple générée par un outil comme MKQB ou un autre VQB :

SELECT
  dbo.INPUTUNIT.BATCH_ID,
  dbo.INPUTUNIT.FOLD_ID,
  dbo.INPUTUNIT.DOCUMENT_ID,
  dbo.INPUTUNIT.SHEET_ID,
  dbo.INPUTUNIT.PAGE_ID,
  dbo.INPUTUNIT.ENTITYID,
  dbo.INPUTUNIT.CREATEDON,
  dbo.INPUTUNIT.CREATEDBY,
  dbo.INPUTUNIT.MODIFIEDON,
  dbo.INPUTUNIT.MODIFIEDBY,
  dbo.INPUTUNIT.LASTERROR,
  dbo.INPUTUNIT.NAME,
  dbo.INPUTUNIT.TYPE,
  dbo.INPUTUNIT.IMAGEID,
  dbo.INPUTUNIT.STATE,
  dbo.INPUTUNIT.REASON,
  dbo.INPUTUNIT.EXPIRYDATE,
  dbo.INPUTUNIT.POSITION,
  dbo.INPUTUNIT.PRIORITY,
  dbo.INPUTUNIT.COMMINGFROMSTEP,
  dbo.INPUTUNIT.NEXTWORKFLOWSTEP,
  dbo.INPUTUNIT.CURRENTVALUE,
  dbo.INPUTUNIT.REGEXPRESSION,
  dbo.INPUTUNIT.NULLALLOWED,
  dbo.INPUTUNIT.CHECKMINMAX,
  dbo.INPUTUNIT.MINVALUE,
  dbo.INPUTUNIT.MAXVALUE,
  dbo.INPUTUNIT.VALUELIST,
  dbo.INPUTUNIT.MULTIVALUE,
  dbo.INPUTUNIT.STRICTVALUELIST,
  dbo.INPUTUNIT.CROPZONE,
  dbo.INPUTUNIT.INPUTCOUNT,
  dbo.INPUTUNIT.CONFIDENCEINDEX,
  dbo.INPUTUNIT.FORMAT,
  dbo.INPUTUNIT.DATATYPE,
  dbo.INPUTUNIT.DECIMALDIGITS,
  dbo.INPUTUNIT.MONEYFACTOR,
  dbo.INPUTUNIT.CASING,
  dbo.INPUTUNIT.CHECKLENGTH,
  dbo.INPUTUNIT.MAXLENGTH,
  dbo.INPUTUNIT.MINLENGTH,
  dbo.INPUTUNIT.MINSECURITYLEVEL,
  dbo.INPUTUNIT.CHECKDLL,
  dbo.INPUTUNIT.DLLCHECKNUMBER,
  dbo.INPUTUNIT.COMMENT
FROM
  dbo.INPUTUNIT
  INNER JOIN dbo.FOLD ON (dbo.INPUTUNIT.FOLD_ID = dbo.FOLD.ENTITYID)
  INNER JOIN dbo.BATCH ON (dbo.INPUTUNIT.BATCH_ID = dbo.BATCH.ENTITYID)
WHERE
  (dbo.FOLD.FOLDTYPE = 0) AND
  (dbo.BATCH.CUSTOMERID LIKE '%') AND
  (dbo.BATCH.BUSINESSID LIKE '%') AND
  ((dbo.INPUTUNIT.STATE = 5) OR
  (dbo.INPUTUNIT.STATE = 6))
 

C'est une requête somme toute très classique (et réelle, prise au hasard d'une appli en cours). Mais voilà, elle est sur "plein de lignes", elle est indentée avec des espaces au début, il va falloir jongler au clavier pour supprimer les espaces, placer les guillemets au début et à la fin et un petit signe + pour finir...
Nous commençons par coller cette requête dans le corps d'une méthode. je vous fait grace de la capture écran, on trouve une méthode "machin" ses accolades de début et de fin et ... notre belle requête en plein milieu comme un cheveu sur la soupe de C#.

Acte 2 : Désindenter

Pour ça, c'est facile, mais peut-être ne connaissez-vous l'astuce : sélectionnez tout le bloc texte en question, et tapez autant de fois que nécessaire la combinaison SHIFT-TAB jusqu'à ce que toutes les lignes se retrouvent collées à gauche. C'est un bon début et c'est rapide à faire.

Acte 3 : Chercher - Remplacer

Le plus gros de l'effort a été fait, et nous n'avons pas fait grand chose pour le moment...
Vérifiez que le texte est toujours sélectionné puis ouvrez la boîte de dialogue Chercher/Remplacer (CTRL-H) et renseignez les champs comme le montre cette capture écran :

 

Le texte à chercher est {.+} et le texte de remplacement est +"\1 ", cochez "Use " puis "Regular expression" (Utiliser/Expressions régulières pour la version FR). Puis cliquez sur "Replace All" (Remplacer tout). Vous noterez l'espace après le "1", c'est au choix, il ajoute un espace à chaque ligne avant de mettre le guillement fermant, pour une requête SQL c'est putôt préférable, dans d'autres circonstances cela peut gêner ou bien être remplacé par un autre symbole.

Et voici le résultat (du à la mise en page la requête est indentée sous la méthode, en réalité elle reste collée à gauche) :

static void Main(string[] args)
{
+
"SELECT "
+
"dbo.INPUTUNIT.BATCH_ID, "
+
"dbo.INPUTUNIT.FOLD_ID, "
+
"dbo.INPUTUNIT.DOCUMENT_ID, "
+
"dbo.INPUTUNIT.SHEET_ID, "
+
"dbo.INPUTUNIT.PAGE_ID, "
+
"dbo.INPUTUNIT.ENTITYID, "
+
"dbo.INPUTUNIT.CREATEDON, "
+
"dbo.INPUTUNIT.CREATEDBY, "
+
"dbo.INPUTUNIT.MODIFIEDON, "
+
"dbo.INPUTUNIT.MODIFIEDBY, "
+
"dbo.INPUTUNIT.LASTERROR, "
+
"dbo.INPUTUNIT.NAME, "
+
"dbo.INPUTUNIT.TYPE, "
+
"dbo.INPUTUNIT.IMAGEID, "
+
"dbo.INPUTUNIT.STATE, "
+
"dbo.INPUTUNIT.REASON, "
+
"dbo.INPUTUNIT.EXPIRYDATE, "
+
"dbo.INPUTUNIT.POSITION, "
+
"dbo.INPUTUNIT.PRIORITY, "
+
"dbo.INPUTUNIT.COMMINGFROMSTEP, "
+
"dbo.INPUTUNIT.NEXTWORKFLOWSTEP, "
+
"dbo.INPUTUNIT.CURRENTVALUE, "
+
"dbo.INPUTUNIT.REGEXPRESSION, "
+
"dbo.INPUTUNIT.NULLALLOWED, "
+
"dbo.INPUTUNIT.CHECKMINMAX, "
+
"dbo.INPUTUNIT.MINVALUE, "
+
"dbo.INPUTUNIT.MAXVALUE, "
+
"dbo.INPUTUNIT.VALUELIST, "
+
"dbo.INPUTUNIT.MULTIVALUE, "
+
"dbo.INPUTUNIT.STRICTVALUELIST, "
+
"dbo.INPUTUNIT.CROPZONE, "
+
"dbo.INPUTUNIT.INPUTCOUNT, "
+
"dbo.INPUTUNIT.CONFIDENCEINDEX, "
+
"dbo.INPUTUNIT.FORMAT, "
+
"dbo.INPUTUNIT.DATATYPE, "
+
"dbo.INPUTUNIT.DECIMALDIGITS, "
+
"dbo.INPUTUNIT.MONEYFACTOR, "
+
"dbo.INPUTUNIT.CASING, "
+
"dbo.INPUTUNIT.CHECKLENGTH, "
+
"dbo.INPUTUNIT.MAXLENGTH, "
+
"dbo.INPUTUNIT.MINLENGTH, "
+
"dbo.INPUTUNIT.MINSECURITYLEVEL, "
+
"dbo.INPUTUNIT.CHECKDLL, "
+
"dbo.INPUTUNIT.DLLCHECKNUMBER, "
+
"dbo.INPUTUNIT.COMMENT "
+
"FROM "
+
"dbo.INPUTUNIT "
+
"INNER JOIN dbo.FOLD ON (dbo.INPUTUNIT.FOLD_ID = dbo.FOLD.ENTITYID) "
+
"INNER JOIN dbo.BATCH ON (dbo.INPUTUNIT.BATCH_ID = dbo.BATCH.ENTITYID) "
+
"WHERE "
+
"(dbo.FOLD.FOLDTYPE = 0) AND "
+
"(dbo.BATCH.CUSTOMERID LIKE '%') AND "
+
"(dbo.BATCH.BUSINESSID LIKE '%') AND "
+
"((dbo.INPUTUNIT.STATE = 5) OR "
+
"(dbo.INPUTUNIT.STATE = 6)) "
}

Il n'y a plus qu'à se placer au début de la chaîne et de taper "var machaine = " puis de se placer en fin de la dernière ligne de la chaîne, de taper ";" et hop! c'est tout fini tout beau, remis en page et sans risque d'oubli ou de fausse manip ! Là aussi je vous fait grace de la capture écran, vous imaginez facilement le résultat, et puis, profitez-en pour tout de suite refaire la manip histoire de la mémoriser !

Conclusion

Une astuce simple qui rend un grand service et une preuve de plus que pour rébarbatives et contre-intuitives que soient les expressions régulières, savoir s'en servir est toujours un gros avantage...

Bon dev.. et Stay Tuned !