DMI's Blog sur les technos .NET(dotnet) et J2EE

Récupérer le chemin courant de votre application avec VB.NET /s .NETCF

Path.GetDirectoryName([Assembly].GetExecutingAssembly.GetName.CodeBase)
Les espaces de noms nécessaires sont:
• System.Reflection
• System.IO

18 commentaires - 12 rétroliens

FileSystemWatcher

FileSystemWatcher

Une petite histoire

 

Un jour mon boss entre dans mon bureau et me demande si c’est facile de faire communiquer deux applications GRC distantes (Gestion de la Relation Client) développées sous .NET sachant qu’on n’avait pas la main sur l’une d’elles. J’ai répondu qu’il suffit de passer par .NET Remoting (trop lourd) ou utiliser un WebService (inadapté) car on n’avait besoin que d’une méthode (celle qui retourne les infos concernant le nouveau client). Mauvaise réponse !

 

L’idée :

 

La première application avais pour rôle de créer de nouveaux clients et d’effectuer un minimum de vérifications (adresse postale, mail, âge, …) et la seconde devait récupérer ces informations pour géocoder les adresses postales afin de les placer sur une carte.

 

Le principe:

 

Le principe serait d’avoir un répertoire commun aux deux applications dans lequel l’application 1 pourra déposer la description du nouveau client et l’application 2 devra vérifier à intervalle régulier si un nouveau client a été créé.

 

L’architecture :

 

Les deux applications appartenant au même réseau local (et domaine) nous avons créé un répertoire partagé nommé Spy contenant un fichier nommée Customers.xml.

 

L’application 1 devait créer un client puis le rajouté dans le fichier xml et l’application 2 vérifier à intervalle régulier si le fichier avait été modifié pour le lire.

 

Cette technique est très utilisée dans les applications EAI pour faire communiquer plusieurs applications hétérogènes.

 

La solution :

 

Après un peu de recherche sur le web j’ai vu que je n’avais pas à développer des containers ni de connecteurs comme dans les EAI puisque .NET offre une classe très particulière et peu utilisé qui permet de le faire : FileSystemWatcher.

 

Pour le faire :

 

  • Créer une application Windows console
  • Ajouter ceci :

 

using System;

using System.IO;

namespace ConsoleApplicationTests

{

/// <summary>

/// Description résumée de Class1.

/// </summary>

class Class1

{

/// <summary>

/// Point d'entrée principal de l'application.

/// </summary>

[STAThread]

static void Main(string[] args)

{

// Création de l’objet FileSystemWatcher

FileSystemWatcher MyWatcher = new FileSystemWatcher();

// Répertoire à surveiller \\par-madiop\Spy

MyWatcher.Path = @"\\MaMachine\Spy";

 

// Ne pas surveiller les répertoires fils

MyWatcher.IncludeSubdirectories = false;

// Filtre pour les notifications

MyWatcher.NotifyFilter = NotifyFilters.LastAccess |

NotifyFilters.LastWrite |

NotifyFilters.FileName |

NotifyFilters.DirectoryName;

 

// Superviser uniquement le fichier Customers.xml

MyWatcher.Filter = "Customers.xml";

 

//En cas de changement de Customer.xml -> appeler la méthode OnChange

MyWatcher.Changed += new FileSystemEventHandler(OnChanged);

//En cas de création de Customer.xml -> appeler la méthode OnChange

MyWatcher.Created += new FileSystemEventHandler(OnChanged);

 

// Permettre le composant de commencer à superviser nles changements

MyWatcher.EnableRaisingEvents = true;

 

//Maintenir la console afficher pour voir défiler les changements

Console.WriteLine("Press \'q\' to quit.");

while(Console.Read()!='q');

 

}

 

public static void OnChanged(object source, FileSystemEventArgs e)

{

Console.WriteLine("{0} : Changed", System.DateTime.Now);

}

 

}

}

 

 

aucun commentaire - aucun rétrolien

.NET Remoting (Visualiser avec IE -Internet Explorer-)

Dans cet article je vais expliquer en quelques étapes comment faire une application distribué avec la technologie

 

Dans cet article je vais expliquer en quelques étapes comment faire une application distribué avec la technologie .NET Remoting.

 

L’environnement technique :

 

IDE : Visual studio 2003 avec le .NET Framework 1.1

Langage : C#

 

Présentation

 

.NET Remoting est une technologie offerte avec le Framework .NET et permet de faire de la programmation distribuée. La programmation distribuée permet par principe d’exécuter un processus sur plusieurs machines. Le but étant d’exécuter des parties du processus sur des machines qui sont le plus disposées à l’effectuer (gros calculs, traitement métier, …).

 

Scenarii

 

Voici notre scenario :

 

Nous disposons d’une application de gestion de compte bancaire qui est composée de trois applications reparties dans toute la France.

 

  • La première application a pour but de récupérer dans une DB le montant du découvert d’un client identifié

 

  • La seconde, permettra à partir du montant de découvert d’effectuer des calculs permettant de savoir le montant des agios

 

  • La troisième, collectera les informations transmises par les deux premières applications et prendra la décision d’envoyer un courrier au client ou pas en étudiant le rapport découvert/agios.

 

 

Pour visualiser le schéma vous devez avoir un web browser IE


Mise au point

 

Il est utile de comprendre l’architecture du .NET remoting.

En gros : vous avez d’un côté un serveur puis de l’autre un ou plusieurs client comme ci-dessous.

 

Pour visualiser le schéma vous devez avoir un web browser IE

 

L’échange de données peut se faire via HTTP ou TCP (dans notre cas nous utiliserons le protocole TCP). HTTP est plus adapté pour des communications distantes nécessitants le réseau web et TCP pour des communications en réseaux locaux (format binaire, plus performant). Le format d’échange peut être du Xml ou du binaire.

 

 

Important : Dans notre cas les applications 1 et 2 sont des serveurs et l’application 3 le client

 

Mise en pratique

 

 

  • Créez une solution nommée _NETRemoting sous visual studio .NET,
  • Ajoutez une application console (projet) nommée Svr_App1 à la solution,
  • Ajoutez un projet ClassLibrary nommé Lib_App1 à la solution,
  • Ajoutez une application console (projet) nommée Svr_App2 à la solution,
  • Ajoutez un projet ClassLibrary nommé Lib_App2 à la solution,
  • Ajoutez une application WinForm (projet) nommée clt_App3 à la solution.

 

 

Il est intéressant de savoir que le client ne manipule jamais les objets hébergé par le serveur mais passe par se qu’on appelle des proxies.

En effet, les proxies sont les représentants locaux des objets distants. Pour communiquer avec un objet distant, on instancie un proxy qui sera la représentation locale de cet objet. On manipule le proxy comme si c’était notre objet distant.

 

Dans notre cas nous allons avoir deux proxies (un pour l’application 1 et l’autre pour l’application 2). Un proxy étant un objet, il est donc représentable par une classe ou une interface.

 

 

A ce stade nous avons toutes les entités nécessaires, reste plus qu’à les meubler.

 

Projet Lib_App2

 

Son rôle est de calculer un agio à partir d’un montant représentant le découvert bancaire

 

Renommer class1 en LibApp2 ainsi que le fichier (LibApp2.cs)

La classe LibApp2 doit forcément dériver de MarshalByRefObject

 

Ajouter au projet une méthode nommée float getAgio(float fDec)

 

Le projet Lib_App1

 

Son rôle est de récupérer le montant du découvert de la base de données puis d’interroger l’application 2 pour avoir le montant de l’agio.

 

Renommer class1 en LibApp1 ainsi que le fichier (LibApp1.cs)

La classe LibApp1 doit forcément dériver de MarshalByRefObject

Ajouter une méthode nommée void getAgioAndDec(long lIDClient, ref float fDec, ref float fAgio)

Ajouter une interface nommée IApp2 (proxy de Lib_App2) –fichier IApp2.cs-

 

 

Le projet Svr_App2

 

Renommer Class2 en App2 ainsi que le fichier (App2.cs au lieu de Class1.cs)

Ajouter une référence du projet Lib_App2

 

Le projet Svr_App1

 

Renommer Class1 en App1 ainsi que le fichier (App1.cs au lieu de Class1.cs)

Ajouter une référence du projet Lib_App1

 

Le projet clt_App3

 

Ajouter un bouton, une textbox, et un label

Dans le textbox vous saisirez l’ID du client et l’appui sur le bouton invoquera les méthodes distantes puis le résultat sera affiché dans le label.

Ajouter une interface nommée IApp1 (proxy de Lib_App1) –fichier IApp1.cs-

 

 

Au niveau des deux serveurs

 

Ajouter les références suivantes (fichier App1.cs et App2.cs) :

using System;

using System.Collections;

using System.Runtime.Remoting;

using MyTcpChannel = System.Runtime.Remoting.Channels.Tcp.TcpChannel;

using System.Runtime.Remoting.Channels.Tcp;

using System.Runtime.Remoting.Channels;

 

Attention: Vous devez ajouter la référence de l’assembly System.Runtime.Remoting à vos projets (Click droit sur le projet puis ajouter référence)

 

Pour “servir un objet” on doit:

 

  1. Ouvrir un canal selon un protocole et sur un port (1234 pour Svr_App1 et 5678 pour Svr_App2)

 

  1. Enregistrer le canal ouvert précédemment

 

  1. Publier son type avec l’URI et le mode pour y accéder

 

Et tout ça dans la méthode main

 

Au niveau du client (clt_App3)

 

using System;

using System.Collections;

using System.Runtime.Remoting;

using MyTcpChannel = System.Runtime.Remoting.Channels.Tcp.TcpChannel;

using System.Runtime.Remoting.Channels.Tcp;

using System.Runtime.Remoting.Channels;

 

Attention: Vous devez ajouter la référence de l’assembly System.Runtime.Remoting à vos projets (Click droit sur le projet puis ajouter référence)

 

 

 

Pour visualiser le schéma vous devez avoir un web browser IE

 

Codes Sources

 

Si vous voulez les codes complets envoyez moi un mail à l’@ suivante :bossiel@yahoo.fr

 

 

 

 

 

 

Svr_App1 :App1.cs

 

using System;

using System.Collections;

using System.Runtime.Remoting;

using MyTcpChannel = System.Runtime.Remoting.Channels.Tcp.TcpChannel;

using System.Runtime.Remoting.Channels.Tcp;

using System.Runtime.Remoting.Channels;

 

namespace Svr_App1

{

/// <summary>

/// Description résumée de Class1.

/// </summary>

class App1

{

/// <summary>

/// Point d'entrée principal de l'application.

/// </summary>

[STAThread]

static void Main(string[] args)

{

BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();

serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();

IDictionary props = new Hashtable();

props["port"] = 1234;//port

//(1): Ouvrir un canal selon le protocole tcp et sur un port 1234

// Enregistrer le canal ouvert précédemment

MyTcpChannel _tcpChannel = new MyTcpChannel(props,clientProv,serverProv);

ChannelServices.RegisterChannel(_tcpChannel);

 

//(2): Publier son type avec l’URI et le mode pour y accéder

RemotingConfiguration.RegisterWellKnownServiceType(typeof(Lib_App1.LibApp1),"Svr_App1",WellKnownObjectMode.SingleCall);

Console.Write("**********************************************\n");

Console.Write(" MON SERVEUR Svr_App1 \n");

Console.Write("***********************************************\n");

Console.Write("Moi je suis un serveur d'application conçu pour Lib_App1 distant\nqui sera utilisé par un client autonome (App3) via tcp/http au format binaire ou soap\n");

Console.Write("\n\n");

Console.Write("-Je viens de me lancer sur tcp:1234\n\n");

Console.Write("-Je viens de demarrer l'objet distant ok\n\n");

Console.Write("[Entree] pour quitter");

Console.ReadLine();

ChannelServices.UnregisterChannel(_tcpChannel);

}

}

}

 

 

 

Lib_App1 :LibApp1.cs

 

using System;

using System.Collections;

using System.Runtime.Remoting;

using MyTcpChannel = System.Runtime.Remoting.Channels.Tcp.TcpChannel;

using System.Runtime.Remoting.Channels.Tcp;

using System.Runtime.Remoting.Channels;

 

namespace Lib_App1

{

/// <summary>

/// Description résumée de Class1.

/// </summary>

public class LibApp1 :MarshalByRefObject

{

public LibApp1()

{ }

public void getAgioAndDec(long lIDClient, ref float fDec, ref float fAgio)

{

//les calcul sont fictifs: ajouter du code pour acceder à une DB

if(lIDClient > 0)

{

fDec = -152;//toujours

fAgio = getAgio2(fDec);

}

}

/// <summary>

/// Cette methode appel l'objet distant Lib_App2 pour avoir le montant de l'agio

/// sachant à combien s'éleve le découvert.

/// Pour que cette méthode marche il faut que le serveur Svr_App2 soit démarré

/// </summary>

/// <returns></returns>

private float getAgio2(float fDec)

{

//(1): Ouverture du canal selon le protocole Tcp

MyTcpChannel _tcpChannel = new MyTcpChannel(1);

//(2): Enregistrement du canal ouvert précédemment

ChannelServices.RegisterChannel(_tcpChannel);

// (3): Récupération d'une référence de l'objet distant Lib_App2 hebergé par Svr_App2

Lib_App2.LibApp2 pxy_App2 = (Lib_App2.LibApp2)RemotingServices.Connect(typeof(Lib_App2.LibApp2),

"tcp://localhost:5678/Svr_App2");

try

{

return pxy_App2.getAgio(fDec);

 

}

catch(Exception ex)

{

return -1;

}

finally

{

// (4): Fermeture et deréférencement du canal

ChannelServices.UnregisterChannel(_tcpChannel);

}

}

}

}

 

ctl_App3 :IApp1.cs

 

/*C'est le proxy de l'objet Lib_App1*/

using System;

 

namespace Lib_App1

{

public interface LibApp1

{

void getAgioAndDec(long lIDClient, ref float fDec, ref float fAgio);

int test();

}

}

 

clt_App3 : Form1.cs

 

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.Runtime.Remoting;

using MyTcpChannel = System.Runtime.Remoting.Channels.Tcp.TcpChannel;

using System.Runtime.Remoting.Channels.Tcp;

using System.Runtime.Remoting.Channels;

 

 

namespace clt_App3

{

/// <summary>

/// Description résumée de Form1.

/// </summary>

public class Form1 : System.Windows.Forms.Form

{

private System.Windows.Forms.TextBox textBox1;

private System.Windows.Forms.Button button1;

private System.Windows.Forms.Label label1;

/// <summary>

/// Variable nécessaire au concepteur.

/// </summary>

private System.ComponentModel.Container components = null;

 

public Form1()

{

//

// Requis pour la prise en charge du Concepteur Windows Forms

//

InitializeComponent();

 

//

// TODO : ajoutez le code du constructeur après l'appel à InitializeComponent

//

}

 

/// <summary>

/// Nettoyage des ressources utilisées.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

 

#region Code généré par le Concepteur Windows Form

/// <summary>

/// Méthode requise pour la prise en charge du concepteur - ne modifiez pas

/// le contenu de cette méthode avec l'éditeur de code.

/// </summary>

private void InitializeComponent()

{

this.textBox1 = new System.Windows.Forms.TextBox();

this.button1 = new System.Windows.Forms.Button();

this.label1 = new System.Windows.Forms.Label();

this.SuspendLayout();

//

// textBox1

//

this.textBox1.Location = new System.Drawing.Point(16, 16);

this.textBox1.Name = "textBox1";

this.textBox1.TabIndex = 0;

this.textBox1.Text = "45286";

//

// button1

//

this.button1.Location = new System.Drawing.Point(144, 16);

this.button1.Name = "button1";

this.button1.Size = new System.Drawing.Size(88, 23);

this.button1.TabIndex = 1;

this.button1.Text = "Go";

this.button1.Click += new System.EventHandler(this.button1_Click);

//

// label1

//

this.label1.Location = new System.Drawing.Point(24, 48);

this.label1.Name = "label1";

this.label1.Size = new System.Drawing.Size(528, 376);

this.label1.TabIndex = 2;

this.label1.Text = "Result";

//

// Form1

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.ClientSize = new System.Drawing.Size(584, 446);

this.Controls.Add(this.label1);

this.Controls.Add(this.button1);

this.Controls.Add(this.textBox1);

this.Name = "Form1";

this.Text = "Form1";

this.ResumeLayout(false);

 

}

#endregion

 

/// <summary>

/// Point d'entrée principal de l'application.

/// </summary>

[STAThread]

static void Main()

{

Application.Run(new Form1());

}

/// <summary>

/// Cette methode appel l'objet distant Lib_App1 pour avoir le montant de l'agio et du découvert

/// en se basant sur l'ID du client

/// Pour que cette méthode marche il faut que le serveur Svr_App1 soit démarré

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void button1_Click(object sender, System.EventArgs e)

{

long lIDClient = long.Parse(textBox1.Text);

float fAgio = 0;

float fDec = 0;

 

//(1): Ouverture du canal selon le protocole Tcp

MyTcpChannel _tcpChannel = new MyTcpChannel(0);

 

//(2): Enregistrement du canal ouvert précédemment

ChannelServices.RegisterChannel(_tcpChannel);

 

// (3): Récupération d'une référence de l'objet distant Lib_App1 hebergé par Svr_App1

Lib_App1.LibApp1 pxy_App1 = (Lib_App1.LibApp1)RemotingServices.Connect(typeof(Lib_App1.LibApp1),

"tcp://localhost:1234/Svr_App1");

 

try

{

pxy_App1.getAgioAndDec(lIDClient,ref fDec,ref fAgio);

label1.Text = "Agio = "+fDec+" et Dec ="+ fAgio;

if(fAgio > 15)

label1.Text += "\n Un courrier sera transmis!";

else

label1.Text += "\n Aucun courrier ne sera transmis!";

}

catch(Exception ex)

{

label1.Text = ex.ToString();

}

finally

{

// (4): Fermeture et deréférencement du canal

ChannelServices.UnregisterChannel(_tcpChannel);

}

}

}

}

 

Fonctionnement

 

Bien entendu si vous voulez tester l’application cliente (clt_App3) vous devez d’abord lancer les deux serveurs (Svr_App1 et Svr_App2). Le client utilise uniquement le serveur Svr_App1 (calcul découvert) et ce dernier utilisera le serveur des agios (Svr_App2).

 

aucun commentaire - aucun rétrolien

Enumérateur de string

 

Comme vous le savez très bien il peut être très utile de pouvoir faire des énumérateurs de string (par défaut les enumérateurs contiennent des entiers).

Avec .NET on peut facilement faire cela en ajoutant des descriptions à vos enumérateurs.

Pour cela procédez comme suit :

 

  1. Ajoutez les espaces de noms suivants à votre classe

 

using System.ComponentModel;

using System.Reflection;

 

Créer votre enumérateur (dans mon cas j’ai un énumérateur « Voitures »)

 

enum Voitures{

[Description("Une Renault 12 année 75 -Française-")]R12,

[Description("Une Renault 5 année 60 -Française-")]R5,

[Description("Une Peugeot 607 année 2001 -Française-")]P607

};

 

  1. Ajouter la méthode suivante permettant de récupérer la description d’une voiture

 

private string _GetDesc(Voitures enumConst)

{

FieldInfo finfo = enumConst.GetType().GetField(enumConst.ToString());

object [] descAttr = finfo.GetCustomAttributes(typeof(DescriptionAttribute),false);

 

if(descAttr.Length > 0)

return ((DescriptionAttribute)descAttr[0]).Description;

else

return enumConst.ToString();

}

 

  1. Récupérer la description d’un élément

 

Voitures v_f = Voitures.P607;

string desc = _GetDesc(v_f);//='Une Peugeot 607 année 2001 -Française-'

 

  1. Eh ben c’est parti ….

 

4 commentaires - aucun rétrolien

Comment exécuter un package DTS à partir d’une procédure stockée ?

 

Malheureusement aucunes commandes T-SQL ne permettent d’exécuter un dts, mais il existe cependant deux « solutions de contournement » :

 

  • Passer par xp_cmdshell and dtsrun
  • Utilisez les procedures stockées OLE (sp_OACreate, sp_OAGetErrorInfo, …)

 

Dans cette première partie nous allons utiliser la première méthode car plus facile à mettre en œuvre bien que plus contraignante en terme de gestion de sécurité

 

DTSRUN est un utilitaire qui vous permet d’exécuter un lot, ou le planifier sans utiliser le fameux Microsoft Management Console (MMC). Pour exécuter cette commande vous devez bien sûr avoir MS SQL Server sur votre machine.

Lancer l’invite de commande (démarrer->exécuté puis tapez « cmd ») puis tapez dtsrun pour avoir l’aide concernant l’utilisation de celle-ci.

 

Syntaxe

 

dtsrun
[/?] |
[
    [
        /[~]S server_name[\instance_name]
        { {/[~]U user_name [/[~]P password]} | /E }
    ]
    {    
        {/[~]N package_name }
        | {/[~]G package_guid_string}
        | {/[~]V package_version_guid_string}
    }
    [/[~]M package_password]
    [/[~]F filename]
    [/[~]R repository_database_name]
    [/A global_variable_name:typeid=value]
    [/L log_file_name]
    [/W NT_event_log_completion_status]
    [/Z] [/!X] [/!D] [/!Y] [/!C]
]

 

Utilitaire d’aide à la génération de la commande

 

Il existe un utilitaire qui permet de générer graphiquement la commande nécessaire pour l’exécution d’un lot donnée.

Supposons que nous avons besoin de générer la commande d’exécution du lot suivant

 

Nom : abcdTest

Server : MyServer

User name = sa

Pwd = pwd

Variable globale : NBLigne avec comme valeur 780

Fichier journal : C:\Temp\log.txt

 

Se qu’il faut faire :

 

  • Tapez en ligne de commande «dtsrunui » puis à l’ouverture de l’utilitaire graphique entrez vos paramètres (Emplacement, Nom du serveur, utilisateur, mot de passe puis le nom du lot).
  • Cliquez sur « Avancé » puis choisissez votre variable globale puis entrez la valeur voulue.
  • Choisissez le chemin de votre fichier de log
  • Cliquez sur « Générer… »
  • Copiez le résultat généré

 

NB : cet utilitaire vous donne aussi la possibilité de planifier l’exécution de votre lot.

 

Le résultat doit être semblable à quelque chose comme :

 

DTSRun /S "MyServer " /U "sa" /P "pwd" /N "abcdTest " /G "{5360FD4D-5326-4640-B06C-31E8652F48B3}" /L "C:\Temp\log.txt" /A "NBLignes":"780"="78" /W "0"

 

Vous pouvez tester votre commande en l’exécutant en ligne de commande

 

La seconde étape consiste à exécuter cette commande dans MS SQL Server.

MS SQL Server offre la possibilité d’exécuter des lignes de commande grâce à la procédure stockée xp_cmdshell (à utiliser avec prudence et parcimonie) qui se trouve dans la base master.

 

Ouvrez l’analyseur de requêtes puis tapez exec master..xp_cmdshelldir. Cela aura pour effet de lister les fichiers situés sur le disque dur de la machine sur laquelle SQL Server est installé.

 

Pour exécuter votre commande créez une procédure stockée contenant le code suivant :

 

DECLARE @CMD varchar(1000)

 

SET @CMD = DTSRun /S "MyServer " /U "sa" /P "pwd" /N "abcdTest " /G "{5360FD4D-5326-4640-B06C-31E8652F48B3}" /L "C:\Temp\log.txt" /A "NBLignes":"780"="78" /W "0"

exec master..xp_cmdshell @CMD

 

Et voilà, c’est partiiiiiiii

aucun commentaire - aucun rétrolien

Comment afficher la version et le SP de SQL Sever?

 

Ouvrer l’analyser de requête et tapez ceci

 

SELECT ServerProperty('PRODUCTVERSION') AS VERSION_NUMBER,

ServerProperty ('PRODUCTLEVEL') AS SERVICE_PACK,

ServerProperty ('EDITION') AS EDITION

aucun commentaire - aucun rétrolien

Comment définir un style à la volée pour vos Page ASP .NET?

Pouvoir définir un style à la volée (suivant un utilisateur) en ASP.NET peut être très utile.

J’ai eu à faire cela dans une application web où chaque utilisateur avait son propre style définie dans une base de données (le chemin du fichier CSS).

Si les utilisateurs sont habitués aux styles CSS ils peuvent même écrire leurs propres feuilles de styles en se basant sur un Template prédéfini.

 

Vous devez procéder en 3 étapes

 

  1. Ajouter ceci dans le code html de votre page

 

<HEAD>

…..

<LINK id="stPageStyle" type="text/css" rel="stylesheet" runat="server"></LINK>

…..

</HEAD>

 

  1. Ajouter la variable globale suivante dans votre code behind

 

protected HtmlGenericControl stPageStyle;

 

  1. Procédez comme suit pour charger la feuille de style (dans Page_Load par exemple)

 

/* strCssFile doit contenir le path complet de votre feuille de style.

* Si votre feuille de style s'appel MyStyle.css et est située dans

* un répertoire de votre site web alors vous pouvez faire un Mapping

* pour retrouver le chemin complet. Sinon mettez le en dure ou récupérez

* d'une DB ou d'un fichier .ini.

* */

string strCssFile = Server.MapPath("MyStyle.css");//Mapping

stPageStyle.Attributes.Add("href",strCssFile);

aucun commentaire - aucun rétrolien

DNS -> @IP avec Java (class InetAddress)

InetAddress

 

InetAddress est une classe java fort intéressant car elle permet de retrouver une adresse IP d’un poste à partir de son nom de domaine (DNS). Pour cela java passe par la couche réseau de l’OS pour que celui-ci interroge ces serveurs pour obtenir, soit le nom, soit l’IP.

 

Voici un exemple qui permet d’avoir une adresse IP à partir d’un nom.

 

package dotnet.mabulle.java;

import java.net.* ;

 

public class NomToIp {

public static void main(String[] args){

String m_Name = args[0];

if(m_Name.length()==0){

System.out.println("Saisissez un nom");

}

try{

InetAddress address = InetAddress.getByName(m_Name);

System.out.println("Name: "+ address.getHostName());

System.out.println("Address: "+ address.getHostAddress());

 

}catch(UnknownHostException Unex){

Unex.printStackTrace();

}

}//fin main

}//fin class

 

Si vous donnez google.fr en entrée, vous obtenez:

 

Name: google.fr

Address: 216.239.57.104

 

Si vous donnez dotnet.mabulle.com en entrée, vous obtenez:

 

Name: dotnet.mabulle.com

Address: 213.251.133.165

 

Dans le prochain article je vous expliquerai comment faire un pseudo ping avec java.

A+

 

 

 

aucun commentaire - aucun rétrolien

C#.NET & Control Panels

Il est important de savoir par exemple comment ouvrir un panneau de configuration avec C#

 

Sous .NET il est important de savoir par exemple comment ouvrir un panneau de configuration avec C#.Net car il arrive très souvent qu’on souhaite offrir à l’utilisateur la possibilité de configurer sa machine à la suite d’une levée d’exception (par exemple).

 

  1. Voici comment ouvrir le panneau de configuration Windows à partir d’un programme C# .NET
    System.Diagnostics.Process.Start("rundll32.exe", "shell32.dll, Control_RunDLL");

 

Pour ouvrir un panneau de configuration particulier, il faut savoir ou se trouve le fichier d’extension de ce dernier (*.cpl). Pour les panneaux concernant Windows, la plupart sont dans c:\windows\system32\.

 

  1. Panneau de configuration pour « Internet Explorer (IE) »

System.Diagnostics.Process.Start(Environment.

GetEnvironmentVariable("windir") + "\\system32\\inetcpl.cpl");

 

  1. Panneau de configuration pour « Connexions réseau »

System.Diagnostics.Process.Start(Environment.

GetEnvironmentVariable("windir") + "\\system32\\ncpa.cpl");

 

NB: Vous pouvez faire la même chose pour toutes les applications installées sur votre poste possédant un fichier .cpl.

 

Voici quelques fichiers cpl utiles

 

Accessibilité

access.cpl

Mots de passe

password.cpl

Affichage

desk.cpl

Thèmes du bureau

themes.cpl

Paramètres régionaux

intl.cpl

Internet

inet.cpl

Modem

modem.cpl

Système

sysdm.cpl

Réseau

netcpl.cpl

Profils Microsoft Exchange

mlcfg32.cpl

Logiciels

appwiz.cpl

Souris

main.cpl

Multimédia

mmsys.cpl

Manette de jeu

joy.cpl

Date/heure

timedate.cpl

 

aucun commentaire - aucun rétrolien

Process.Start & empreint d'identité

L’objectif de ce document est d’expliquer dans un premier temps comment l’ancer un processus à partir d’une application

L’objectif de ce document est d’expliquer dans un premier temps comment lancer une application externe (ou processus) à partir d’une application .NET, puis dans un second temps montrer comment lancer ce processus avec un utilisateur particulier.

 

1.     Lancer l’application avec l’utilisateur par défaut

 

//pour lancer IE vous pouvez initialiser appPath à "C:\Program Files\Internet //Explorer\iexplore.exe"

string appPath = System.IO.Path.Combine(Environment.SystemDirectory, "cmd.exe");

System.Diagnostics.Process.Start(appPath);

 

2.     Lancer l’application avec un utilisateur défini

 

Cette option peut être intéressante dans le cas ou vous souhaitez lancer une application avez un utilisateur privilégié ou contrer l’utilisateur par défaut ASPNET (empreint d’identité ou « impersonalisation »).

 

Si vous essayer par exemple de faire System.Diagnostics.Process.Start(« une application sécurisée »); sous ASP .NET, alors vous aurez une exception car l’utilisateur qui sera utilisé est APSNET (droits réduits).

 

Vous-vous dites surement que la solution serait donc d’utiliser la méthode « LogonUser » de l’API « advapi32 » (cf. http://dotnet.mabulle.com/index.php/2005/12/02/24858-empreint-didentite-avec-cnet). Si c’est le cas, alors c’est loupé, car la méthode « Process.Start » utilise toujours le contexte de sécurité du processus parent ASP.NET. Pour résoudre cela il faudra chercher du coté de la méthode « CreateProcessWithLogonW » de la même API (advapi32).

 

  1. Créer une classe nommée « DLLClass » définie comme ceci :

 

using System;

using System.Runtime.InteropServices;

namespace WindowsApplication1

{

/// <summary>

/// Description résumée de DLLClass.

/// </summary>

public class DLLClass

{

[Flags]

public enum LogonFlags

{

LOGON_WITH_PROFILE = 0x00000001,

LOGON_NETCREDENTIALS_ONLY = 0x00000002

}

 

[Flags]

public enum CreationFlags

{

CREATE_SUSPENDED = 0x00000004,

CREATE_NEW_CONSOLE = 0x00000010,

CREATE_NEW_PROCESS_GROUP = 0x00000200,

CREATE_UNICODE_ENVIRONMENT = 0x00000400,

CREATE_SEPARATE_WOW_VDM = 0x00000800,

CREATE_DEFAULT_ERROR_MODE = 0x04000000,

}

 

[StructLayout(LayoutKind.Sequential)]

public struct ProcessInfo

{

public IntPtr hProcess;

public IntPtr hThread;

public uint dwProcessId;

public uint dwThreadId;

}

 

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]

public struct StartupInfo

{

public int cb;

public string reserved1;

public string desktop;

public string title;

public uint dwX;

public uint dwY;

public uint dwXSize;

public uint dwYSize;

public uint dwXCountChars;

public uint dwYCountChars;

public uint dwFillAttribute;

public uint dwFlags;

public ushort wShowWindow;

public short reserved2;

public int reserved3;

public IntPtr hStdInput;

public IntPtr hStdOutput;

public IntPtr hStdError;

}

 

[DllImport("advapi32.dll", CharSet=CharSet.Unicode, ExactSpelling=true, SetLastError=true)]

public static extern bool CreateProcessWithLogonW(

string principal,

string authority,

string password,

LogonFlags logonFlags,

string appName,

string cmdLine,

CreationFlags creationFlags,

IntPtr environmentBlock,

string currentDirectory,

ref StartupInfo startupInfo,

out ProcessInfo processInfo);

 

[DllImport("kernel32.dll")]

public static extern bool CloseHandle(IntPtr h);

 

public DLLClass()

{

//

// TODO : ajoutez ici la logique du constructeur

//

}

}

}

 

  1. Exécuter votre application en faisant ceci au niveau d’un click de bouton, dans la méthode Page_Load, dans le Main ou n’importe où ;)

 

string strError = "";

//DLLClass représente la class que vous avez ajoutez

DLLClass.StartupInfo _StartupInfo = new DLLClass.StartupInfo();

DLLClass.ProcessInfo _ProcessInfo = new DLLClass.ProcessInfo();

string strAppPath = @"C:\Program Files\Internet Explorer\iexplore.exe";

if (DLLClass.CreateProcessWithLogonW("login", "domain", "password",

DLLClass.LogonFlags.LOGON_WITH_PROFILE,

strAppPath, null,

0, IntPtr.Zero, null,

ref _StartupInfo, out _ProcessInfo))

{

DLLClass.CloseHandle(_ProcessInfo.hProcess);

DLLClass.CloseHandle(_ProcessInfo.hThread);

}

else strError = string.Format("Code error: {0}", Marshal.GetLastWin32Error());

/*/libre à vous d'afficher l'erreur

Console.WriteLine(strError);

//ou

label1.Text = strError;

//ou

MessageBox.Show(strError);

*/

 

 

Vous pouvez savoir qu’elle utilisateur a lancé l’application en faisant ceci :

 

string strUserName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

 

 

 

 

 

 

 

aucun commentaire - aucun rétrolien

Serialisation avec java

package blog.tecnoJava.serialization;

 

import java.beans.XMLDecoder;

import java.beans.XMLEncoder;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

 

public class Serialize {

 

            //Cette méthode permet d’écrire (sérialiser) un objet java dans un fichier

            //Binaire:*.dat,*.bin,...

            public void WriteInBinaryFormat(Object oToSerialize,String strDestinationPath) throws IOException{

                        //Create output streams.

                        FileOutputStream fos = new FileOutputStream(strDestinationPath);

                        ObjectOutputStream oos = new ObjectOutputStream(fos);

                        //Write object

                        oos.writeObject(oToSerialize);

            }

//          Cette Methode Permet de lire un objet sérialiser à partir d’un fichier binaire

            public Object ReadFromBinaryFile(String strSourceFilePath) throws IOException, ClassNotFoundException{

                        //Create input streams.

                        FileInputStream fis = new FileInputStream(strSourceFilePath);

                        ObjectInputStream ois = new ObjectInputStream(fis);

                        //Read object

                        return ois.readObject();

            }

           

            //Cette méthode permet d’écrire (archiver) un objet java dans une archive

            //XML comme ci-dessous

            public void WriteInXMLArchiveFormat(Object oToSerialize,String strDestinationPath) throws FileNotFoundException{

//                      Create output stream.

                        FileOutputStream fos = new FileOutputStream(strDestinationPath);

                        //Create XML encoder

                        XMLEncoder Xmlenc = new XMLEncoder(fos);

                        //Write object.

                        Xmlenc.writeObject(oToSerialize);

            }

            public Object ReadFromXMLArchive(String strSourceFilePath) throws FileNotFoundException{

//                      Create input stream.

                        FileInputStream fis = new FileInputStream(strSourceFilePath);

                        //Create XML decoder

                        XMLDecoder Xmldec = new XMLDecoder(fis);

                        //Read object.

                        return Xmldec.readObject();

            }

}

aucun commentaire - aucun rétrolien

Comparatif VS .NET (partie SDE) et eVC++

VS .NET offre un environnement robuste pour créer des applications basées sur le NETCF. Ces applications peuvent tourner sur Pocket PC, Pocket PC 2002(et plus) et Windows CE .NET 4.1 (et plus). L’environnement permet d’inclure facilement des Windows Forms et composants ADO.NET dans les programmes en plus de tout ce qui a attrait au web ( consommer des services web).

 

a)      Design : VS .NET :1 / eVC++ :0

 

A la différence d’eVC++ VS .NET offre un environnement très simple d’utilisation pour tout ce qui concerne le « design » de forms. VS .NET a reprit toutes les bonnes idées de VB concernant le design notamment la notion de form (fichiers *.ebf en VB).

 

b)      Sécurité : VS .NET :2 / eVC++ :0

 

Un autre avantage d’utiliser des assemblies plutôt que des DLLs est que les premiers sont plus sécurisés (chargés dans le runtime avec un niveau de confiance), permettent d’éviter le chainage (système de versionning), gèrent les dépendances, … En un mot, les assemblies permettent de se passer de ce que certains appellent « l’enfer des DLLs ».

 

c)      Performances d’exécution : VS .NET :2 / eVC++ :1

 

L’inconvénient qui résulte de cela (b) est que les assemblies ne peuvent s’exécuter que dans le Runtime .NET (ce qui fait qu’il faut avoir le NETCF installé à la fois sur le PC et le PPC) qui est lui-même est chargé par l’OS ; les DLLs C++ sont directement « consommable » par l’OS (win32) d’une façon native. C’est en partie à cause de se « problème » (et d’autres aussi) que les applications C++/C sont beaucoup plus performant que celles développées avec C# .NET/VB .NET/C++ .NET/Java, …

 

d)      Intégration de composants natifs type ocx : VS .NET :2 / eVC++ :2

 

Annoncé pour la version 2 du NETCF, il n’est toujours pas possible d’ « héberger » des composants ActiveX sous NETCF. Sous eVC++ il suffit d’un clic deux mouvements pour intégrer son contrôle ActiveX dans son programme. Cependant, il est possible de développer une couche supplémentaire au NETCF permettant de résoudre cet handicap. Sinon, la seule alternative est de redévelopper son composant pour le NETCF (paradoxalement, il permet de le faire). Le développement et la mise en place de cette couche est assez complexe mais ils existent des bases (librairies de classes) offertes « gratuitement » par la firme OpenNETCT.

 

Pour que cela fonctionne on doit disposer du proxy sous forme d’Assemby et d’un Wrapper dans un fichier C# (c’est le seul langage dans lequel le Wrapper peut être généré). L’Assembly et le Wrapper sont générés par l’utilitaire de ligne de commande offert avec le FrameWork .NET (Aximp, pour ActiveX IMPort). Cet utilitaire n’étant pas adapté pour le NETCF, il pourrait être nécessaire de modifier la Wrapper à la main dans certain cas (c’est le cas du composant MapX50.dll).

Cependant, sous NETCF il existe toutes les classes nécessaires pour faire du Marshling de type et du Wrapping.

 

e)      Automation OLE : VS .NET :3 / eVC++ :2

 

C# permet beaucoup plus aisément de faire de l’automation (accès aux routines d’un processus) que le C++. On peut très facilement contrôler un processus Word en exécutant ces routines (créer un document, faire des mises en page ou tout simplement générer des rapports Word ou Excel) à partir d’un code managé. Faire ce type de programme en C++ est possible mais pas facile d’accès. o:p>

 

 

 

f)       C# (sous VS .NET) vs C++ (sous eVC++) : VS .NET :3 / eVC++ :2

 

Il n’est tout simplement pas possible de comparer ces deux langages du fait que leurs objectifs ne sont pas les mêmes. Si j’avais à le faire je dirais qu’un programme C# offre très certainement plus de lisibilité (il suffit juste de voir le nombre de ligne de code généré automatique par eVC++ avant même d’avoir écrit une ligne), de productivité (le système de séparation du « code design (interface) » et du « code code (implementation) » - utilisation de Classes partielles- améliore grandement la productivité avec C#) et de facilités de management (gestion du code au sens large) du fait tout simplement que ces concepteurs ont retenu les leçons tirer du C++, Java, Delphi et autres langages.

Cela fait que dans notre cas (programmation PPC) C# est sans aucun doute le langage le plus approprié.

 

g)      Ouverture : VS .NET :4 / eVC++ :2

 

Pour faire des applications mobiles cloisonnées eVC++ pourrait rivaliser avec VS .NET mais du moment que ces applications ont vocation à s’ouvrir sur le web ou interopérer avec d’autres applications (processus, SGBD, supports hybrides, …) on peut dire que VS.NET prend largement le dessus (à savoir qu’à l’origine .NET était définie par Microsoft comme étant une technologie qui permet de « communiquer », le mot –communiquer- souligne l’importance donner au web et à l’interopérabilité).

 

Il convient ainsi de bien étudier les possibles évolutions de notre application avant de choisir à le développer sous eVC++.




h)      Design patterns (ou réutilisation de code) : VS .NET :4 / eVC++ :2

 

Il est bien dommage de remarquer qu’au cours des développements les développeurs sont amenés à créer plusieurs fois les mêmes classes (types), d’exécuter les même procédures, de manipuler les mêmes objets pour accéder aux DB, etc. … tout ça pour dire : réinventer la roue. Une parade à cela est certainement la définition de motifs de conception (design patterns) réutilisable. Le C# et le C++ étant tous les deux très orientés Objet (l’objet étant la base des design patterns) on ne pourrait choisir l’un plutôt que l’autre.

 

1          Résultat 

 

VS .NET remporte 4 points contre 2 pour eVC++. L’avantage donné à VS .NET peut être dut au fait que je maitrise plus celui-ci.

 

 

L’élément le plus important à prendre en compte est l’évolution de l’application.

 

Merci de me signaler les âneries.

4 commentaires - aucun rétrolien

TSQL-Lister les tables d'une DB

Dans ce document je vais expliquer comment lister toutes les tables d’une base de données SQL Server

Dans ce document je vais expliquer comment lister toutes les tables d’une base de données SQL Server.

 

Ce bout de code TSQL (à exécuter dans une procédure stockée par exemple) vous permettra de lister l’ensemble des tables (table_name) de votre DB avec les colonnes (column_name) de chaque table et son type (data_type).

 

--afficher toutes les tables de la db avec les colonnes et leurs type

SELECT

table_name,

column_name,

data_type FROM information_schema.columns

WHERE table_name in (select table_name

FROM Information_Schema.Tables

WHERE Table_Type='Base Table'

)

ORDER BY table_name

 

Ce bout de code spécialisé vous permettra de ne lister que les propriétés d’une table entrée en paramètre (@TableName).

 

DECLARE @TableName as varchar(255)

SET @TableName = 'T_MaTable'

--afficher toutes les tables de la db avec les colonnes et leurs type

SELECT

table_name,

column_name,

data_type FROM information_schema.columns

WHERE table_name in (select table_name

FROM Information_Schema.Tables

WHERE Table_Type='Base Table'

and Table_Name = @TableName

)

ORDER BY table_name

 

 

 

aucun commentaire - aucun rétrolien

IDE pour programmation PDA

  1. SuperWaba : SuperWaba est une JVM qu’on peut faire tourner aussi bien sous Palm OS, Windows CE et AppletViewer. C’est un projet open source. Plus d’info : Superwaba.

 

  1. Waba : C’est un langage de type JAVA qui s'appuie sur une JVM réduite donnant de bonnes performances. Sa diffusion est libre de royalties. Waba permet de développer rapidement des applications à partir d'un langage orienté objet simple mais puissant. Il est aussi Multi-OS (PPC et Palm). Fonctionne sou licence Libre / GPL. Plus d’info : WabaSoft.

 

  1. Microsoft eMbedded Visual C++ : C’est un IDE complet (SDK PPC, WCE .NET, SDK Emulator, …) permettant de créer des applications et composants systèmes pour Windows CE .NET. Le langage de développement est le C++. Pour la programmation de programmes native Win32 et des DLLs.

 

  1. Visual Studio .NET : C’est un IDE qui permet de développer aussi bien des applications Windows basées sur PC que sur PPC. Pour les applications PPC il suffit de se procurer le NETCF (version la plus récente v2).

Pour la programmation en code manage pour le Framework et des Assemblies (cela a la couleur et l’odeur d’une DLL mais ça n’a rien à voir).

1 commentaire - aucun rétrolien

Empreint d'identité avec C#.NET

Il faut savoir que c'est la galére si vous voulez accéder à des fichiers ou ressources du poste local à partir d'une page aspx car par défaut tous les utilisateurs de la page sont représentés parl’utilisateur ASPNET (qui a des droits réduits).
Plusieurs solutions existent et la plus courante consiste à faire de l’ »empreint d’identité » à partir du fichier web.config ou à la volée.
La prémiére donne ceci:
Ajouter dans votre fichier web.config ceci:
<identity impersonate="true" userName="MonDomaine\MonLogin" password="MonMotDePasse" />

La seconde donne ceci:

1. Déclarez la methode extern de l'api "advapi32" comme ceci:

[System.Runtime.InteropServices.DllImport("advapi32.dll")]
public static extern bool LogonUser(
String strUsername,
String strDomain,
String strPassword,
int intLogonType,
int intLogonProvider,
out IntPtr phToken);



2. puis ...

System.IntPtr phToken = IntPtr.Zero;
LogonUser("votre login", "votre domaine(nom de la machine sur le réseau)", "votre mot de passe", 3, 0, out phToken);
WindowsIdentity ImpersonatedIdentity = new WindowsIdentity(phToken);
WindowsImpersonationContext MyImpersonation = ImpersonatedIdentity.Impersonate();

//traitements .....

//Fin empreint d'identité
MyImpersonation.Undo();


ou bien, si vous voulez empreinter l'identité de l'utilisateur connecté, alors ceci conviendra le mieux:
WindowsIdentity ImpersonatedIdentity = System.Security.Principal.WindowsIdentity.GetCurrent();
WindowsImpersonationContext MyImpersonation = ImpersonatedIdentity.Impersonate();

//traitements .....

//Fin empreint d'identité
MyImpersonation.Undo();

aucun commentaire - aucun rétrolien

Probleme d'exécution d'un composant COM avec ASP.NET


Il faut savoir qu'il n'est pas possible (par défaut) d'éxécuter une methode d'un coposant COM à partir d'une page ASP.NET.
Pour comprendre pourquoi cela n'est pas possible, il faut d’abord comprendre le mode de fonctionnement des threads ASP .NET et ceux des composants COM dans la majorité des cas.
L’explication étant trop longue, je résume en disant qu’une application ASP .NET/web services est intrinsèquement définie par un modèle à multiples threads cloisonnés (MTA, Multi-Threaded Apartement)
alors qu’un composant COM utilise en général un modèle dit STA (Single-Threaded Apartment, modèle avec un thread unique cloisonné).
Pour résoudre se problème Microsoft propose une solution peut élégante et gourmande en ressource qui consiste à cloisonner
tous les threads d’une page ASPX (application ASP .NET) en une seule pour simuler le modèle STA. Concrètement, la solution consiste à activer la propriété ASpCompat dans la directive @Page pour avoir ceci :

<%@ Page AspCompat = true language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="WebApplication1.WebForm1" %>

aucun commentaire - aucun rétrolien

Différence entre PPC et Palm

Il faut juste savoir que le Newton, lancé par Apple en 1993, est le pionnier des assistants personnels. Puis deux modèles se sont imposés grâce aux fonctions de synchronisation avec un ordinateur de bureau: le Palm Pilot, commercialisé dès 1996 par US Robotics, et le Psion. Aujourd'hui de nombreuses marques proposent des assistants personnels très sophistiqués, pouvant allier multimédia et accès Internet sans fil : Compaq, Hewlett-Packard, Toshiba, Sagem, etc.

 

La différence majeure entre ces différents modèles est l’OS : les uns utilisent Microsoft Mobile et les autres PalmOS. Pour faire simple nous dirons que ceux fonctionnant sous Microsoft mobile sont des PPC (Pocket PC) et les autres des Palms.

 

Comme dans le monde des Postes de travail (pour ne pas dire PC) il existe deux camps : Microsoft et les autres.

 

Pour faire simple et claire on dira que PPC ~= PC et Palm ~= Mac car PalmOS et Windows Mobile sont deux systèmes d’exploitation bien différents. PalmOS semble toute fois être supérieur à WM en se qui concerne le choix des logicielles, la rapidité d’exécution, le prix, … (pour aller loin : ZDNET).

aucun commentaire - aucun rétrolien