vendredi 19 octobre 2012

Récupérer la taille des dossiers dans le répertoire courant

Voici un petit script powershell qui permet de récupérer les dossiers du répertoire courant et d'indiquer leur taille en Gb:

Get-ChildItem |
where {$_.PsIsContainer} |
select @{Name="SizeGb";Expression={(Get-ChildItem $_ -Recurse | Measure-Object Length -Sum).Sum/1Gb}},Name |
Format-table -AutoSize

mercredi 25 juillet 2012

Générer des ressources licenses buildées (App_Licenses.dll) à partir des fichiers licences.licx - Build Runtime Licenses

Comment générer des ressources licenses buildées (App_Licenses.dll) à partir des fichiers licences.licx? Après de nombreuses recherche voici un résumé de ces recherches ainsi que la solution à cette question.

Les fichiers licenses.licx sont des fichiers textes qui contiennent le nom de l'assembly ainsi que le nom du composant sur lequel agit une licence d'utilisation. Les applications ASP.Net (et les WCF applications) ont besoin d'avoir une dll qui comprends la licence car ces applications ne s'exécutent pas par elles-mêmes, elles sont exécutée par un process IIS. Pour ces applications, il ne suffit pas de simplement ajouter le fichier licenses.licx dans votre assembly et de lancer la compilation, mais il est nécessaire de les liers à des ressources compilées qui contiendra la license. On vous expliquera que pour générer ces assembly il suffit de faire un clic droit dans l'explorateur de solution de visual studio 2010 et de cliquer sur "Build Runtime Licenses". Le problème c'est que mise à part si vous travaillez sur un site Web vous ne verrez pas cette option. 

Alors, comment faire ? Il suffit de simplement ouvrir votre solution comme un Site Web (File > Open > Web Site) et de déposer votre fichier licenses.licx à la racine de votre projet. Et la, miracle, vous avez l'option "Build Runtime Licenses" disponible qui va vous générer le fameux fichier App_Licenses.dll dans le dossier Bin de votre application. Il ne reste plus qu'a rajouter cette assembly aux références de votre projet et fini les problèmes de licenses sur vos application asp.Net !

Cette solution marche également pour les projets de type "Wcf Application".

mardi 17 juillet 2012

Client WCF à partir de l'interface .NET - le ChannelFactory

Souvent, pour réaliser un client sur un service WCF, on passe par une "Service Reference". Ce type de référence, va générer du code(Visual Studio) et notamment un client qui implémente une interface compatible avec l'interface du service. Après génération de ce code, si vous regarder votre code, vous trouverez d'une part l'interface au niveau de votre service et d'autre part l'interface générée gentiment par Visual Studio. Les datacontracts utilisés par votre service seront également dupliqués du coté du client.

L'avantage de cette solution est sa facilité de mise en place et l'indépendance du client par rapport au service. Le désavantage est cette duplication du code. Si vous êtes détenteur du code du service et donc de ses contrats, pourquoi ne pas directement utiliser ces contrats au lieu d'en régénérer dans votre assembly cliente ? Pour éviter cette duplication, il est possible de créer un client wcf à partir du contrat via la classe System.ServiceModel.ChannelFactory. Comment utiliser ce ChannelFactory ?

Pour voir le fonctionnement, nous allons faire une petite solution visual studio qui comprendra:
  • Un assembly avec l'interface du service(Contracts)
  • Un assembly avec l'implémentation du service(Services) - reférence Contracts
  • Un host pour le service (SVCHost) - référence Services et Contracts
  • Une console qui sera client du service (ConsoleClient) - référence Contracts
N'oubliez pas d'ajouter les références vers System.ServiceModel et System.Runtime.Serialization sur vos projets. Vous devriez alors avoir quelque chose comme :
Voici le code des différents composants :

Le code du host (hello.svc)
 Le code du client
Comme nous pouvons le voir ici, il n'y a pas de code généré. Le client référence simplement l'assembly contenant les interfaces et WCF va nous généré un client au travers de la classe ChannelFactory.

Le gros avantage est que si vous modifier votre interface, vous pouvez directement voir les impacts. Cette solution ne fonctionne néanmoins que dans un système fermé (entièrement sous contrôle d'une seule entité). Si vos services sont ouverts, vous ne pouvez pas fournir forcément fournir votre assembly de contrats. Dans ce cas la, une service reference s'impose !

Sources :

mardi 10 juillet 2012

Définir les styles par défaut dans Word

Certaines configuration de Word ne montre pas les styles que vous utilisez le plus souvent. Dans mon cas, je suis tombé sur une machine ou Word ne me proposait pas les styles Titre1,Titre2,Titre3 ou Heading1, Heading2, Heading3 si votre MS Office est en anglais.


Alors comment faire pour configurer son bandeau ? Pour les styles, voici la procédure à suivre :
  • Afficher la fenetre des styles (ctrl+alt+shift+s ou cliquer sur la petite flèche de la boite des style comme montré sur l'image ci dessous
  •  Afficher la boite de dialogue Manage Styles
  •  A partir de cette fenêtre, dans l'onglet Recommend, vous pouvez définir les styles à afficher par défaut (Show), à cacher (Hide) ou à cacher tant qu'il n'est pas utilisé (Hide until used)


  • Enfin, vous avez la possibilité de préciser que vous souhaiter garder la configuration pour votre document ou pour tous les documents qui ont le même template

mardi 3 juillet 2012

A socket operation encountered a dead network

Ce matin, en voulant me connecter à ma base de données Oracle locale via un projet Console C# avec devart dotConnect for Oracle

connection = new OracleConnection(ConfigurationManager.ConnectionStrings["XE"].ConnectionString);
 
voici le joli message d'erreur que j'ai obtenu :

Network error:: 10050 - A socket operation encountered a dead network < Host = 127.0.0.1:1521>

Un tnsping vers ma base de données m'indique que la base de données est joignable et que le problème vient donc de l'application .Net. Après de nombreuses recherches je tombe sur une discussion qui indique que cela peut venir du "Firewall Client for ISA Server". Après désactivation de ce process, j'obtiens le message suivant :

Socket error "An invalid argument was supplied"
Network error:: 10022 - An invalid argument was supplied < Host = 127.0.0.1:1521>

Alors que je perséverais dans mes recherches, je me suis souvenu que mes projets C# avait été déplacé sur un disque réseau ... Pour ceux qui ne le saurait pas, Windows n'autorise pas à une application se situant sur un disque réseau(qui n'est pas configuré comme étant un "disque de confiance") à effectuer des connections réseaux ...

L'une des solutions pour régler ce problème consiste donc simplement à déplacer votre exécutable sur votre disque local. Ces messages peuvent provenir d'autres problèmes sur votre machine mais avant de chercher trop loin vérifiez que votre application ne se trouve pas sur un disque réseau !

mercredi 20 juin 2012

Oracle Execute Immediate : Nom de table invalide (ORA-00903: Invalid table name)

Si vous avez cette erreur c'est que comme moi vous avez tenté de faire quelque chose comme :

Begin
  Execute Immediate 'Truncate Table :1' using 'MaTable';
End;

En y réfléchissant bien, il est normal qu'Oracle refuse de faire cela. En effet, la commande Execute Immediate travaille avec des bind variables (préfixées par un ':'). La valeur d'une bind variable est assignée après que le parseur ait analysé votre requête. Oracle vous indique donc que la table ":1" n'existe pas.

Pour info, si vous travaillez avec sqlplus et que vous pouvez scripter le code que vous souhaitiez exécuter, il est possible d'avoir le comportement que vous souhaitiez en utilisant une variable de script, c'est à dire &1 :

Begin
   Execute Immediate 'Truncate Table &1';
End;
/

Si sqlplus n'est pas une solution, vous devez concaténer votre requête dynamique :

Begin
  Execute Immediate 'Truncate Table ' || 'MaTable';
End;

mardi 12 juin 2012

2 fenêtres Excel indépendantes en dual screen

Voici une petite astuce assez simple qui permet d'avoir 2 instances d'Excel indépendantes.

Si vous tentez d'ouvrir 2 fichiers Excel différents vous remarquerez qu'il n'y a qu'une seule instance d'Excel qui est ouverte contenant 2 sous fenêtres avec vos documents. Afin de pouvoir splitter votre Excel, il suffit de lancer 2 instances d'Excel sans spécifier de fichier puis de récupérer le fichier sur l'instance souhaitée.

En gros:
  1. Fermez toutes les instances d'Excel ouvertes
  2. Allez dans le menu démarrer (ou dans la barre des tâches) et lancez Excel
  3. Disposez la fenêtre sur l'écran voulu
  4. Répétez l'étape 2 pour ouvrir une nouvelle instance d'Excel indépendante.
Voila une procédure assez simple, mais la question me revient souvent, donc je l'inscris ici :-)

 Solution testée avec MS Excel 2007 SP3 et MS Excel 2010

lundi 4 juin 2012

Un aperçu de Html5

Voici le lien vers une présentation (en html) que j'ai réalisée à propos de Html5 lors d'un workshop dans la société pour laquelle je travaille :
Présentation : Un aperçu de Html5

Je présente les points suivants :
  1. Introduction à Html 5
  2. Nouveaux Eléments Sémantiques
  3. Formulaire
  4. Multimédia
  5. Stockage
  6. Dessins
  7. Géolocalisation
Chaque partie présente quelques exemples.

Cette présentation utilise la librairie slidy2.js (http://www.w3.org/Talks/Tools/Slidy2/#%281%29) qui est utilisée pour les présentation du W3C. Les exemples de la présentation fonctionnent tous avec Opera 11.64

lundi 30 avril 2012

Détection de modifications sur un fichier ou un dossier: Le FileWatcher

Sur les systèmes Windows, il est possible de récupérer des évenements liés au système de fichier tel que la création d'un fichier, sa modification, sa suppression, ...

Le framework .Net fourni une classe, le FileSystemWatcher, qui permet de récupérer ces événements. Cette classe peut-être utilisée pour, par exemple, récupérer l'événement de modification d'un fichier de configuration afin de le recharger sans devoir redémarrer l'application concernée. Le FileSystemWatcher peut récupérer les évenements liés à un dossier et ses sous-dossiers ou un fichier déterminé.

Les principales propriétés définissant le watcher sont les suivantes :
  • Filter (string) : Permet de filtrer les fichiers par extensions. Utilise les wildchars (exemple *.xml pour les fichiers avec l'extension xml). Si on specifie un nom de fichier les évenements ne seront déclenchés que pour ce fichier.
  • IncludeSubdirectories (bool) : Permet d'inclure ou non les sous dossier du dossier défini dans la propriété Path
  • NotifyFilter (enum NotifyFilters) : Permet de filtrer les évenements qui doivent déclencher le watcher.
  • Path (string) : Le chemin du dossier sur lequel il faut écouter les évenements.
  • EnableRaisingEvents (bool) : Démarre ou arrête le déclenchement des évenements par le watcher
  • InternalBufferSize (int) : la taille du buffer contenant les évenements non encore traité. Une taille trop faible risque de provoquer de nombreux dépassements. La taille par défaut est de 8192.
Et les évenements écoutables sont :
  • Changed : Un fichier ou un dossier a été modifé
  • Created : Un fichier ou un dossier a été créé
  • Deleted : Un fichier ou un dossier a été supprimé
  • Renamed : Un fichier ou un dossier a été renommé
  • Error : La limite du buffer du watcher a été dépassée
Voici un petit exemple permettant d'afficher dans une console si un fichier a été modifié :
Et voici le handler de l'évenement :


En fonction de l'éditeur que vous utilisez, il est possible que 2 évenements soient déclenchés lorsque vous sauvez votre fichier. Il existe plusieurs solutions permettant de résoudre ce problème (je vous invite à lire la source 3). Celle que je vous propose ici consiste à déterminer la date de dernière modification du fichier et de voir si le second évenement n'a pas été déclenché en même temps. Je stocke donc la date de dernière modification dans une variable et je la teste avant de réaliser la tâche à faire :
Ainsi, l'évenement ne sera déclenché qu'une seule fois.

La documentation de la MSDN (source 1) est, comme d'habitude, très explicite, n'hésitez donc pas à y jeter un oeil pour en savoir plus.

Sources :
  1. http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx
  2. http://weblogs.asp.net/ashben/archive/2003/10/14/31773.aspx
  3. http://stackoverflow.com/questions/1764809/filesystemwatcher-changed-event-is-raised-twice

vendredi 27 avril 2012

Transformation des fichiers de configuration

Lorsque l'on déploie son application sur plusieurs environnements différent, il est nécessaire de modifier le fichier de configuration(web.config dans le cas des applications web, app.config sinon). Il est donc nécessaire de conserver ces fichiers de configurations et ne pas les écraser lors des déploiements.

Il est possible avec Visual Studio 2010 de générer des fichiers de configuration propre à l'environnement considéré avec la fonctionnalité Web.config Transform. Par défaut, cette fonctionnalité est automatiquement gérée par visual studio pour les projets web. Pour avoir le même comportement avec les fichiers app.config (projets non web) il existe un plug-in qui fera tout le travail pour vous : SlowCheetah - XML Transforms.

Comment ca marche ? Tout d'abord il est nécessaire d'ajouter un fichier de configuration dans votre projet(si cela n'est déja fait). Ensuite, avec un click droit sur votre fichier de configuration séléctionner l'option "Add Transform" ce qui va généré un fichier par configuration défine dans votre projet.
Ajouter les fichiers de transformations

Il est à présent possible de définir ce qui doit être changé dans le fichier de configuration en fonction de l'environnement/configuration cible. Pour l'exercice, je voudrais avoir une paramètre de mon application qui change en fonction de l'environnement. Voici mon fichier de configuration :

Un exemple de fichier de configuration

Je voudrais avoir la valeur "Hey this is the debug file" lorsque je suis dans mon environnement de debug. Pour ce faire, je modifie le fichier App.Debug.config comme suit :

Un exemple de transformation de configuration

Dans mon projet, je référénce la configuration et je récupère le paramètre de configuration comme on le fait habituellement, par exemple (Une référence vers l'assembly System.Configuration est nécessaire) :


En fonction de la configuration choisie lors du build, le résultat retourné sera différent ! Il est possible de faire d'autres actions que simplement modifier le fichier de configuration. Pour plus d'informations, je vous invite à lire la document de la MSDN (voir sources)

Pour générer des fichiers de configuration propre à chaque environnement, il est possible de créer des configurations de build supplémentaires via le configuration manager (accessible via le menu Build/Configuration Manager). Une fois vos environnements définis, il suffit de recréer les fichiers de transformation en répétant l'opération "Add Transform" comme nous l'avons vu plutôt.

Sources et références:

mardi 17 avril 2012

Client WCF asynchrone


Pour réaliser des clients Wcf asynchrone, il existe de nombreuses solutions. Cela peut se faire via la génération automatique du client via le ServiceModel Metadata Utility Tool (Svcutil.exe) ou via l'outil fourni avec visual studio comme montré ci dessous.

Génération d'un client Wcf avec Visual Studio 2010

Le problème de ces 2 solutions, c'est que le client généré n'est pas directement lié à l'interface du service (le contrat)
Il est possible de réaliser son propre client asynchrone en héritant de la classe ClientBase ou en utilisant un contrat de services proposant des méthodes asynchrones (ce qui demande de les développer manuellement)

Une autre solution que je trouve fort sympathique est d'utiliser le WCF Facility fourni avec la librairie Castle Windsor. Cette solution permet, à partir d'un contrat non asynchrone de créer dynamiquement un client asynchrone.

Pour ce faire, il suffit d'enregistrer le proxy dans un container et définir le contrat qu'il implémente lors de l'enregistrement:

Il est nécessaire d'ajouter le Wcf Facility dans les facilities Castle pour activer la fonctionnalité
Ensuite, il suffit de récupérer l'objet dans le container et d'appeler la fonction BeginWcfCall :

BeginWcfCall prend en paramètre une fonction de callback. la signature de cette fonction est la suivante :
Ainsi, vous pouvez avoir rapidement un proxy Wcf asynchrone en quelques lignes.

La fonction BeginWcfCall est une extension méthode il est donc nécessaire d'inclure le namespace Castle.Facilities.WcfIntegration.Async dans les usings du code.

Sources:
  • http://msdn.microsoft.com/en-us/library/ms730059.aspx
  • http://msdn.microsoft.com/en-us/library/aa347733.aspx
  • http://www.castleproject.org/castle/projects.html
  • http://www.castleproject.org/container/facilities/trunk/wcf/index.html
  • http://docs.castleproject.org/Windsor.WCF-Facility-Async-Calls.ashx
  • http://msdn.microsoft.com/en-us/library/aa347733.aspx

jeudi 5 avril 2012

Timer en Javascript (Timing events)


Il est possible en javascript de réaliser des timers qui exécutent une fonction de manière répetée après un certain interval de temps ou tout simplement programmer un appel de fonction dans le futur.

Pour ce faire, il existe 2 fonctions :
  • setInterval([string expression],[interval en ms]) returns [timerID]
  • setTimeout([string expression],[interval en ms]) returns [timerID] 
Ces 2 fonctions disposent chacune d'une autre fonction permettant d'annuler la programmation :
  • clearInterva([timerID])
  • clearTimeout([timerID])
La fonction setInterval défini une expression à exécuter périodiquement tant que la fenetre n'est pas fermée ou que l'on appelle la fonction clearInterval.

La fonction setTimeout défini une expression à exécuter après un certain interval de temps. Cette expression ne sera pas automatiquement réexécutée mais libre a vous de refaire un setTimeout pour reprogrammer l'exécution de l'expression! Un appel à clearTimeout ou la fermeture de la fenetre annulera le timer et l'expression ne sera pas réexécutée.

Ci dessous un petit exemple en javascript qui permet de faire clignoter le caractère '_' à la fin du titre :

Sources

mercredi 4 avril 2012

Paramètre OUT dans une procédure Oracle en Java

Comme vous le savez sans doute, il est possible de développer ses propres procédures/fonctions en Java dans une base de données Oracle. Les procédures Oracle écrites Java référencent des méthodes statiques dans les classes compilées dans la base de données.

Les procédures en Java sont souvent utilisées pour développer les manipulations sur le système de fichier (move, copy, remove, list) car ces actions ne sont pas aisément réalisable avec le package UTL_FILE.

Mon objectif, est de retourner en paramètre OUT de ma procédure le contenu d'un dossier sur mon système de fichier. Le contenu est retourné sous la forme d'un tableau. Voici la procédure à suivre :

1. Définir le type tableau de chaînes de caractères qui contiendra les noms des fichiers
2. Compiler le code Java sur la base de données

Notez l'utilisation d'un array descriptor pour spécifier à Oracle comment transformer l'array de string en sortie.

3. Compiler le package/procédure qui appelle la méthode statique Java


Ainsi, vous pouvez profiter des fonctions de manipulation de fichier disponible dans le package java.io.

Notez que si vous souhaiter mettre un paramètre de type scalaire en sortie (OUT) il est nécessaire que votre méthode statique retourne un tableau de type scalaire étant donné que Java ne gère pas les paramètres passé en sortie.

vendredi 30 mars 2012

Convertir un hostname IPv6 en IPv4

Depuis Windows Vista, la variable HttpContext.Request.UserHostAddress peut retourner une adresse au format IPv6. Il peut être utile de récupérer cette adresse au format IPv4. Voici une solution qui permet d'avoir une IPv4 à partir du hostname ou de l'adresse IPv6 :
Sources :

mardi 27 mars 2012

Optimisation du Update Set Row

La clause Set Row permet de faire des updates d'une table à partir d'un record PL/SQL. La syntaxe utilisée permet d'avoir un code très clair.

Voici un petit exemple illustrant ce principe :

vMyVariable  MyTable%RowType;

Update MyTable tab
Set Row = vMyVariable;
Where tab.Id = 5;

Il est également possible de faire un insert utilisant cette variable de la manière suivante :

Insert MyTable 
Values vMyVariable;

Cependant, l'update via un set row met à jour toutes les colonnes de la table (même la clé primaire) même si cette valeur reste inchangée. La requete équivalente à l'update ci dessus est la suivante :

Update MyTable tab
Set tab.r1 = 1,
    tab.r2 = 2,
    tab.r3 = 3,
    ...
Where tab.Id = 5;
Il n'y a pas besoin de longues explications pour comprendre que dans le cas d'une large table cela peut couter cher de mettre à jour toutes les colonnes si on ne doit juste mettre à jour une ou 2 colonnes.

Pour contrer ce problème, il suffit de définir un subset de la table à mettre à jour. Oracle comprendra alors qu'il ne doit mettre à jour que les colonnes selectionnées par la sous-requete. Il faudra aussi définir un type ne contenant que les colonnes que l'on souhaite mettre à jour. La requete suivante permet de faire ce que l'on souhaite :

update (Select v.r1,tab.r2 from MyTable tab where tab.id = 5)
       Set Row = vMyVariable;


Ainsi seules les colonnes que l'on a définie dans la sous requete sont mises à jour !

Multi desktop Windows 7

Desktops est une petite application développée par sysinternals qui permet de gérer 4 desktops en même temps dans windows. Cette application est très légère et créé jusqu'a 4 bureaux indépendants.


Article technet sur l'outil : http://technet.microsoft.com/en-us/sysinternals/cc817881
Téléchargement : http://download.sysinternals.com/files/Desktops.zip