mercredi 26 septembre 2007

Article: Comment créer un service Windows présentant des objets .Net Remoting

Article: Comment créer un service Windows présentant des objets .Net Remoting

Langage: C#
Environnement: Visual Studio 2005
Description:
Les services Windows sont assez pratiques pour maintenir des processus en tâche de fond. Par ailleurs, le .Net Remoting est assez puissant puisqu'il permet à un client de récuperer un pseudo-objet (le véritable objet étant côté serveur), et d'en appeller les méthodes comme s'il été une véritable instance de l'objet (en pratique, des connections Tcp assurent la liaison avec le serveur).

Cet article a pour but de présenter un service présentant un objet Logger, ainsi que son client (un application console), qui pourra logger des informations, ainsi que lire et effacer les logs existants.
Premier point: L'interface
Permet de définir l'interface de l'objet présenté en .Net Remoting.
Créez un projet Log.Serivce.Interface de type Class Library, avec un fichier ILogger.cs
ILogger.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace Log.Service.Interface
{
public interface ILogger
{
void AddLog(string log);
void ClearLogs();
string Logs { get ;}
}
}
Second point: Le service
Permet de créer le service à proprement parler.
Créez un projet Log.Service de type Windows Service, avec une classe Logger.cs, et renommez Service1.cs en Service.cs
Ajoutez une réference vers Log.Service.Interface et une autre vers System.Runtime.Remoting
Logger.cs
using System;
using System.Collections.Generic;
using System.Text;
using Log.Service.Interface;
namespace Log.Service
{
//MarshalByRef est la classe de base des objets présentable en remoting
internal class Logger : MarshalByRefObject, ILogger
{
private StringBuilder _logs;
//Permet de déclarer une durée de vie infinie pour cet objet
public override object InitializeLifetimeService()
{
return null ;
}
public Logger()
{
_logs = new StringBuilder();
}

#region ILogger Members
public void AddLog(string log)
{
_logs.AppendLine(String.Format( "{0} : {1}", DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss" ), log));
}
public void ClearLogs()
{
_logs = new StringBuilder();
}
public string Logs { get { return _logs.ToString(); } }
#endregion
}
}

Service.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting;
namespace Log.Service
{
public partial class Service : ServiceBase
{
//Declaration d'un channel
private TcpChannel _channel;
public Service()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
//Initialisation du channel
_channel = new TcpChannel(12345);
ChannelServices .RegisterChannel(_channel);
//Enregistrement d'un objet remoting de type logger, en mode singleton
//Le mode singleton permet de garder toujours la même instance de Logger
//(à la différence de SingleCall)
RemotingConfiguration .RegisterWellKnownServiceType(
typeof (Logger),
"Logger" ,
WellKnownObjectMode .Singleton);
}
protected override void OnStop() { }
}
}

Troisième point: Le client
Permet d'utiliser l'objet ILogger présenté par le service
Créez un projet Log.Client de type Console Application, avec une réference vers Log.Service.Interface et System.Runtime.Remoting
Program.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels;
using Log.Service.Interface;
namespace Log.Client
{
class Program
{
//Declaration d'un channel et d'un ILogger
private static TcpChannel _channel;
private static ILogger _logger;
static void Main(string[] args)
{
if (args.Length == 0)
{
Console .WriteLine("Log.Client");
Console .WriteLine("Syntax:");
Console .WriteLine("Log.Client /c\t\tClears the logs");
Console .WriteLine("Log.Client /g\t\tGets current logged text");
Console .WriteLine("Log.Client TEXT\t\tLogs the current text");
return ;
}
//Initialisation du channel
_channel = new TcpChannel();
ChannelServices .RegisterChannel(_channel);
//Recuperation du ILogger
_logger = Activator .GetObject(typeof(ILogger), "tcp://localhost:12345/Logger" ) as ILogger;
if (args[0] == "/c")
{
_logger.ClearLogs();
Console .WriteLine("Logs cleared");
return ;
}
if (args[0] == "/g")
{
Console .WriteLine(_logger.Logs);
return ;
}
StringBuilder message = new StringBuilder();
foreach ( string arg in args)
message.Append(arg + " ");
_logger.AddLog(message.ToString());
Console.WriteLine( "Message {0} logged", message.ToString());
}
}
}

Dernier point: Vérifier que tout marche bien
Création du service: via le Visual Studio 2005 Command Prompt, tapez (l'espace entre "binpath=" et le chemin est nécessaire)
sc create Log.Service binpath=
Lancement du service: via le Visual Studio 2005 Command Prompt, tapez:
net start Log.Service
Test de l'application: essayez les commandes suivantes
Log.Client , plusieurs fois avec différents messages, puis
Log.Client /g pour tout récuperer, et enfin
Log.Client /c pour tout effacer.
Optionnel:
Pour arrêter le service:
net stop Log.Service
Pour supprimer le service:
sc delete Log.Service
Et voilà, libre à vous d'imaginer de nouveaux modes d'utilisation sur le même principe.
David

Aucun commentaire: