Dot.Blog

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

SyncToy 2.0 : Copier n'est pas jouer ! Un outil de synchro de disques gratuit.

Aujourd'hui plus personne ne fait de sauvegarde sur CD ou DVD, ou très rarement : la capacité des disques durs est telle qu'il en faudrait une brouette pleine à chaque fois. Outre le prix délirant de telles sauvegardes, elles prennent un tout fou à faire et on le sait désormais que nous avons un peu de recul : les supports CD/DVD enregistrables ne sont plus lisibles une fois sur deux quand on a justement besoin de ce qui est dessus quelques années plus tard...

Résultat, tout le monde ou presque possède plusieurs disques durs internes et externes où les copies se multiplient.

Hélas, on s'aperçoit assez vite que cette stratégie a elle aussi ses limites : soit il faut systématiquement tout recopier, ce qui peut être très long pour des gros disques, soit il faut synchroniser les disques. Sinon, on se retrouve avec les mêmes fichiers en dix versions différentes sur plusieurs disques, et la bonne idée des sauvegardes se transforme parfois en cauchemard par l'écrasement d'un fichier par une version ancienne - erreur de manipulation fatale... (que celui à qui cela n'est jamais arrivé me lance le premier CD !).

Synchroniser. Le mot est donc lâché. Mais avec quoi ?

Personnellement j'ai longtemps utilisé un petit soft maison (en delphi) mais je n'ai jamais eu le temps de le finir comme je le voulais. J'ai aussi testé à une époque SynchronizeIt! un logiciel pas trop mal mais payant.

Aujourd'hui Microsoft nous offre gratuitement SyncToy 2.0, un outil de synchronisation de disques ou de répertoires paramétrable, simple d'emploi et permettant de balayer les principaux cas qui justifient d'utiliser une synchronisation, comme l'écho (l'esclave reflète le maître), la participation (l'esclave reçoit tout ce qui est nouveau du maître mais aucun fichier n'y est supprimé) etc.

Le logiciel offre un mode de prévisualisation qui permet de vérifier avant de lancer la synchro si tout semble ok.

Dès lors il est facile et rapide de synchroniser les disques de sa machine avec des disques externes. J'utilise par exemple un IOMEGA 1Tera externe comme "base" de sauvegarde de toutes les machines (chacune possède sur l'IOMEGA un répertoire à son nom où son disque Data est copié) ainsi qu'un Plextor 500 Mo portable qui duplique ma machine de base et avec lequel je vais partout en complément de mon portable.

Synchronizer tout ce petit monde (la station de musique et la station graphique en supplément) se fait maintenant en quelques clics et de façon fiable grâce à SyncToy.

Copier n'est pas jouer. En effet, c'est même vital. Alors pourquoi se priver d'un bel outil spécialisé et gratuit ?

Pour le télécharger c'est ici : SyncToy 2.0

[EDIT]
A noter: SyncToy fait parfaitement son travail mais dans certains cas il peut être lent, voire très lent. En général la synchro d'un gros disque s'effectue en tâche de fond, éventuellement déclenchée par une tâche planifiée et cela n'est donc pas très gênant. Mais ne soyez pas surpris si, lors d'une synchro notamment avec disque externe USB, l'opération prend plusieurs heures... En revanche avec des disques internes ou avec mon Plextor 500 qui marche en Sata, c'est très rapide.
Ceux qui trouveraient que ces attentes sont trop longues pour leurs besoins, ils peuvent aussi essayer le très bon AllWays Sync qui existe en version gratuite ici : http://allwaysync.com/index.html.
[/EDIT] 

C'est pas une bonne nouvelle ça ?

... Alors Stay Tuned !

Mettre des données en forme en une requête LINQ

Losqu'on traite de LINQ, la majorité des exemples utilisent des sources de données "bien formées" : flux RSS (mon dernier billet), collections d'objets, etc. Mais dans la "vraie vie" les sources de données à traiter sont parfois moins "lisses", moins bien formées. LINQ peut aussi apporter son aide dans de tels cas pour transformer des données brutes en collection d'objets ayant un sens. C'est ce que nous allons voir dans ce billet.

Prenons un exemple simple : imaginons que nous récupérons une liste de rendez-vous depuis une autre application, cette liste est constituée de champs qui se suivent, les initiales de la personne, son nom et l'heure du rendez-vous. Tous les rendez-vous se suivent en une longue liste de ces trois champs mais sans aucune notion de groupe ou d'objet.

Pour simplifier l'exemple, fixons une telle liste de rendez-vous dans un tableau de chaînes :

string[] data = new[] { "OD", "Dahan", "18:00", "MF", "Furuta", "12:00", "BG", "Gates", "10:00" };

La question est alors comment extraire de cette liste "linéaire" les trois objets représentant les rendez-vous ?

La réponse passe par trois astuces :

  • L'utilisation de la méthode Select de LINQ qui sait retourner l'index de l'entité traitée
  • La syntaxe très souple de LINQ permettant d'utiliser des expressions LINQ dans les valeurs retournées
  • Et bien entendu la possibilité de créer des types anonymes

Ce qui donne la requête suivante :

var personnes = data.Select ( (s, i) => new
                                          {
                                             Value = s,
                                             Bloc = i / 3
                                          }
                                        ).GroupBy(x => x.Bloc)
                                        .Select ( g => new 
                                                    {
                                                      Initiales = g.First().Value,
                                                      Nom = g.Skip(1).First().Value,
                                                      RendezVous = g.Skip(2).First().Value
                                                     } );

L'énumération suivante : 

foreach (var p in personnes.OrderBy(p=>p.Nom)) Console.WriteLine(p);

donnera alors cette sortie console de toutes les personnes ayant un rendez-vous, classées par ordre alphabétique de leur nom :

{ Initiales = OD, Nom = Dahan, RendezVous = 18:00 }
{ Initiales = MF, Nom = Furuta, RendezVous = 12:00 }
{ Initiales = BG, Nom = Gates, RendezVous = 10:00 }

Voici des objets bien formés (on pourrait ajouter un DateTime.Parse à la création du champ RendezVous pour récupérer une heure plutôt qu'une chaîne) qui pourront être utilisés pour des traitements, des affichages, une exportation, etc...

LINQ to Object ajoute une telle puissance à C# que savoir s'en servir au quotidien pour résoudre tous les petits problèmes de développement qui se posent permet réellement d'augmenter la productivité, ce que tous les langages et IDE promettent falacieusement (aucune mesure de ce supposé gain n'existe). Ici, essayez d'écrire le même code sans LINQ, vous verrez tout suite que le gain de productivité et de fiabilité est bien réel, et que la maintenance aura forcément un coup moindre.

Pour d'autres infos, Stay Tuned !

Le projet VS 2008 : LinqChunk.zip (5,35 kb)

Traiter un flux RSS en 2 lignes ou "les trésors cachés de .NET 3.5"

.NET 3.5 apporte beaucoup de classes nouvelles et d'améliorations à l'existant. Certains ajouts sont plus médiatisés que d'autres. Mais il serait injuste de limiter cette mouture à LINQ ou aux arbres d'expressions, aussi géniales et puissantes soient ces avancées.

.NET 3.5 apporte réellement une foule de nouveautés parmi lesquelles il faut noter :

  • L'apport de WCF et de LINQ au compact framework
  • De nouvelles facilités pour contrôler le Garbarge Collector comme le LatencyMode de la classe GCSettings
  • L'ajout de l'assemblage System.NetPeerToPeer.Collaboration qui permet d'utiliser les infrastructures de peer-to-peer
  • Des améliorations importantes de WCF, l'intégration WCF-WF
  • etc...

Pour une liste complète des nouveautés il est intéressant de jeter un oeil à cette page MSDN.

Un exemple qui illustre les avancées plus ou moins méconnues de .NET 3.5, l'espace de noms System.ServiceModel.Syndication dans la dll System.ServiceModel.Web apporte de nouvelles facilités pour gérer des flux RSS. Et pour s'en convaincre quelques lignes de codes :

SyndicationFeed feed;
using (var r = XmlReader.Create(http://www.e-naxos.com/Blog/syndication.axd))
{ feed = SyndicationFeed.Load(r); }

C'est tout ! Dans la variable "feed" on a tout ce qu'il faut pour travailler sur le flux RSS.

Vous pensez que je triche et que "travailler sur le flux RSS" c'est certainement pas si simple que ça ?. Bon, allez, c'est parce que c'est vous : compliquons même la chose et, à partir de ce flux, affichons le titre de tous les billets qui parlent de LINQ dans leur corps. Voici le code complet près à compiler :

using System;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Xml;

namespace NET35RSS
{ class Program
  {
     static void Main()
     {
        SyndicationFeed feed;
        using (var r = XmlReader.Create(
http://www.e-naxos.com/Blog/syndication.axd))
        { feed = SyndicationFeed.Load(r); }
           if (feed==null) { Console.WriteLine("Flux vide."); return; }
           Console.WriteLine(feed.Title.Text);
           Console.WriteLine(feed.Description.Text+"\n");
           var q = from item in feed.Items
           where item.Summary.Text.ToUpper().Contains("LINQ") select item;
           foreach (var item in q) Console.WriteLine(item.Title.Text);
       }
    }
}

Ajoutez une petite saisie pour le mot à chercher au lieu d'un codage en dur ("LINQ" dans cet exemple) et un petit fichier paramètre pour y stocker la liste des blogs que vous connaissez, et en deux minutes vous aurez un puissant outil de recherche capable de vous lister toutes les billets de vos blogs préférés qui parlent de tel ou tel sujet...

C'est pas génial ça ?

Si, ça l'est, bien sûr ! Alors Stay Tuned !

pour les paresseux du clavier, le projet VS 2008 : NET35RSS.zip (5,36 kb)

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]

Le retour des sous-procédures avec les expressions Lambda...

La syntaxe de C# et son orientation "tout objet" ont définitivement tourné la page de la programmation procédurale. Ce n'est certes pas un mal, bien au contraire, mais au passage nous avons perdu une petite facilité de langages tel que Pascal qui autorisaient la déclaration de procédures à l'intérieur de procédures. Le manque n'est pas cruel mais tout de même... Il semble souvent bien lourd et assez artificiel d'être obligé de créer une méthode private ou internal juste pour rendre un service à une seule méthode. De plus le morceau de code ainsi transformé en méthode, même private ou internal, ne sera encapsulé qu'au niveau de la classe et non de la méthode intéressée, d'où le risque de l'utiliser ailleurs (ce qui change sa statégie d"écriture). Le code sera aussi plus lourd en raison de la nécessité de passer en paramètre tout ce qui sera nécessaire à l'exécution de cette "sous méthode" alors qu'une procédure imbriquée peut référencer les variables de la procédure qui l'abrite.

Bref, l'affaire ne mérite certainement pas de grandes théories, mais il faut avouer que de temps en temps on aimerait bien pouvoir déclarer une petite méthode à l'intérieur d'une autre. Il s'agit là d'appliquer la logique des classes elle-mêmes : il est possible de déclarer une classe dans une autre lorsqu'elle ne sert exclusivement qu'à la première. Pourquoi ne pas retrouver cette possibilité au niveau des méthodes d'une classe ?

Les procédures imbriquées n'existent pas en C#. Cela vous semble une certitude. Avec C# 3.0 ce n'est plus aussi certain...

Les expressions Lambda utilisées comme des procédures imbriquées

Je n'entrerai pas ici dans le détail de la syntaxe des expressions Lambda que j'ai déjà présenté dans un long article sur les nouveautés de C# 3.0, article auquel je renvoie le lecteur s'il en ressent le besoin (Les nouveautés syntaxiques de C# 3.0 et Présentation des différentes facettes de LINQ)

Les procédures imbriquées ne sont rien d'autres que des procédures "normales" mais déclarées à l'intérieur d'autres procédures. En Pascal cela ne peut se faire qu'entre l'entête de la méthode principal et le corps de celle-ci :

Procedure blabla
 Procedure imbrique begin ... end;
begin // blabla
...
end; // blabla

Avec les expressions Lambda de C# 3.0 on retrouve une possibilité sensiblement identique avec plus de souplesse encore puisque la "sous procédure" peut être déclarée n'importe où dans le corps de la "procédure principale".

Exemple

static void Main(string[] args)
{
    // une "fonction" imbriquée (teste si un nombre est impair)
   Func<int, bool> isOdd = i => (i & 1) == 1;
   
// une "procédure" imbriquée (formate et écrit un int à la console)
   Action<int> format = i => Console.WriteLine(i.ToString("000")); 
   
   Console.WriteLine(isOdd(25));
   Console.WriteLine(isOdd(24));

   format(25);
   format(258);
   format(5);
}

La sortie sera :

True
False
025
258
005

Conclusion

La possibilité de déclarer des "sous procédures" est bien pratique, cela permet en général d'éviter les répétitions dans le coprs d'une méthode, donc de diminuer le risque de bug et d'améliorer sensiblement la lecture du code. C# ne supportait pas cette possibilité syntaxique, mais en utilisant les expressions Lambda nous retrouvons la même fonctionnalité...

Pour d'autres astuces, Stay Tuned !

Et pour les paresseux le projet VS 2008 : SubRoutines.zip (4,73 kb)

Un éradicateur de fichiers dupliqués gratuit !

Smarter Duplicate File Finder est un outil gratuit très malin : il permet de localiser les fichiers dupliqués dans une liste de répertoires pouvant se situer éventuellement sur des disques différents.

L'intelligence de SDFF se situe à plusieurs niveaux dont la recherche elle-même. Pour localiser les fichiers dupliqués l'utilisateur dispose de plusieurs méthodes : par le nom (casse indifférente), par le type et la taille, par un code de proximité phonétique sur le nom (4 algorithmes : soundex, metaphone, double metaphone et Daitch-Mokotoff, longueur de clé paramétrable de 2 à 50) ou bien par comparaison des contenus par le biais d'une clé de hash MD5 calculée à la volée.

On peut envoyer la liste des fichiers dans le presse-papiers, les déplacer vers tout répertoire ou bien les envoyer à la corbeille de Windows.

La sélection des fichiers montre aussi de l'intelligence : lorsque SDFF créé la liste des doublons il affecte à chaque groupe un code "groupe de proximité" pour pouvoir les traiter séparément. Il devient ainsi possible en un seul clic de sélectionner, pour le conserver, le plus gros, le plus petit, le plus récent ou le plus vieux fichier de chaque groupe. Il est bien entendu possible de sélectionner les fichiers à garder à la main (chaque fichier dans la liste est précédée d'une case à cocher).

Bref, un outil bien pratique. Il est tellement bien que je l'ai adopté tout de suite pour supprimer les doublons de ma collection de mp3 ou bien supprimer les fichiers dupliqués de dossiers clients copiés sur plusieurs disques. Bon, c'est vrai, j'aurais eu du mal à ne pas l'aimer cet outil puisque c'est moi qui l'ai fait :-)

Développé sous VS 2008 en C# 3.0 et framework 3.5 (que le setup installe si vous ne l'avez pas) et faisant appel à beaucoup de LINQ to Object, SDFF est auto-localisé en français et en anglais (mais on peut le forcer dans une langue par la ligne de commande). Le code source n'est pas distribué pour le moment, je travaille encore dessus.

Pour télécharger l'installeur msi c'est ici : http://www.e-naxos.com/download/SDFF1SetupFR.msi

C'est pas un joli cadeau ça ?

Alors Stay Tuned !

(et n'hésitez pas à me laisser un mot si vous avez des idées d'amélioration)

Une petite capture d'écran pour se faire une idée :

Nota: les mp3 de l'exemple sont tous enregistrés via Screamer dont je vous ai parlé dans mon billet coup de gueule sur le piratage. C'est donc du légal, enregistré à la radio et pas du donwload de la mule. Le résultat est rigoureusement le même, sauf que dans un cas on est un bon gars et dans le second on est passible de poursuites, de prison, d'amende et peut être même d'être fouetté en place publique par le patron d'une major. ça démontre la bêtise de la répression et des lois qui se contredisent. ne piratez pas, enregistrez des radios Internet achetez chez des labels indépendants et n'achetez plus rien aux majors ! 

Un excellent livre sur LINQ : "LINQ in Action"

LINQ (encore ! dirons certains, mais c'est justifié je vous l'assure) est une technologie qui décuple la puissance de C#, encore faut-il bien maîtriser toutes les nouveautés syntaxiques de C# 3.0 (voir mes articles sur ce sujet*) et bien comprendre comment tirer partie du meilleur de LINQ lui-même.

Pour cela rien ne vaut un bon livre. Sur le sujet ils ne sont pas très nombreux et quand on fait un peu le tri, il en reste fort peu qui valent l'achat. Ce n'est pas le cas de "LINQ in action" un excellent bouquin qui utilise une approche très pédagogique pour "monter en puissance" au fur et à mesure de la progression des chapitres. C'est d'ailleurs peut-être aussi parce que les auteurs reprennent justement cette logique que j'applique dans mes propres cours sur LINQ que j'apprécie ce livre.

Il s'agit bien entendu d'un ouvrage en anglais, si vous ne maîtriser pas la langue il faudra hélas passer votre chemin. Les concepts avancés dans le livre peuvent s'avérer suffisament sophistiqués en eux-mêmes sans ajouter la difficulté de décryptage si on n'est pas totalement à l'aise avec la prose d'outre-Atlantique.

Pour acheter le livre au moins cher, je vous conseille l'excellent librairie anglaise The Book Repository qui livre en France et qui applique des tarifs généralement hors concurrence. La page du livre est ici "Linq in Action". L'ouvrage possède aussi son propre site avec le téléchargement des exemples ainsi qu'un forum.

(* Les nouveautés syntaxiques de C# 3.0 et Présentation des différentes facettes de LINQ )

Geek Attitude : Un GPS intégré au rétroviseur...

Voici un gadget que tout geek se devra de posséder dans sa voiture : MirrorPilot. C'est un GPS qui s'intègre au rétroviseur avec un miroir semi réfléchissant qui le rend invisible lorsqu'il est hors fonctionnement (le rétro reste donc parfaitement fonctionnel, même en mode GPS bien entendu).

Il y a des versions françaises et européennes (au moins pour les cartes, pour l'interface je ne suis pas sûr), et je ne pense pas que ce merveilleux gadget soit déjà importé chez nous... A suivre donc, car autant le petit carré lumineux qu'on devine sur le parebrise faisait furieusement geek il y a dix ans, autant maintenant je trouve que le GPS accroché comme ça dans la voiture ça fait ringard au possible, tous les beaufs en ont un, une honte pour tout geek qui se respecte un minimum ...

Le site : http://www.mirrorpilot.com/en/navigator/a_new_dimension/

Une petite image pour se faire une idée (c'est livré avec une télécommande aussi) :

 

La machine fonctionne sous Windows CE 5.0, on peut donc supposer pouvoir agrémenter la chose avec d'autres logiciels, c'est pas merveilleux ? Le prix semble être de 700€ en europe reste à trouver une boutique web pour l'acheter !

Stay Tuned !

LINQ et Réflexion pour obtenir les valeurs de System.Drawing.Color

LINQ... l'un de mes sujets préférés... Plus je l'utilise, à toutes les sauces, et plus je trouve cette technologie indispensable. Mais foin de propagande, voici encore un exemple qui prouve à quel point LINQ peut servir à tout, facilement.

Le but du jeu : récupérer la définition des couleurs de System.Drawing.Color, en faire un tableau trié par ordre alphabétique.

A la "main" je vous souhaite bien du plaisir... Avec LINQ cela donne la chose suivante :

namespace LinqColor
{
  class Program
  {
     static void Main(string[] args)
    {
       var color_type = typeof(System.Drawing.Color);
       var color_properties = from prop in color_type.GetProperties()
                                     where prop.PropertyType == color_type
                                     orderby prop.Name
                                     select prop;
       
       foreach (var color_property in color_properties)
       {
           var cur_color = (System.Drawing.Color) color_property.GetValue(null, null);
           uint rgb_int = (uint) cur_color.ToArgb() & (0x00ffffff);
           Console.WriteLine(" {0,-20} = ({1,-3},{2,-3},{3,-3}) = 0x{4:X00000000}",
           color_property.Name,
           cur_color.R, cur_color.G, cur_color.B,rgb_int);
       }
    }
  }
}

La sortie écran (console) donne la chose suivante :

Le projet VS 2008 pour les fénéants du clavier : LinqColor.zip (5,43 kb)

C'est pas merveilleux LINQ ?

Bien sûr que si... Alors Stay Tuned !