Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Traduction pratiquement instruction par instruction du mail slot PowerBuilder
Enfin presque par ce que C# c'est quant même un peu plus complexe que PB (voir nettement plus complexe).
A vous de juger !
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using MailSlotCSharp; namespace MailSlotCSharp { /// <summary> /// Classe qui dépose ou lit de l'information dans un fichier virtuel (mail slot) par rapport à un chemin /// Cette classe permet une communication inter-application via des fichiers virtuels. /// </summary> /// <remarks> /// Au niveau de la génération du projet, la plate forme doit être placée à "Any CPU" ou X64 et doit autoriser du code unsafe. /// </remarks> /// <example>Principe de fonctionnement /// Un composant P crée deux instances de cette classe : /// - La première (C1) crée un mailslot "CSHarp", C1 est capable de lire et d'écrire dans ce dernier. /// - La seconde (C2) peut envoyer un message à un mail slot ouvert par un tiers issu ou non d'un environnement autre que C# /// mais il est capable d'envoyer un message à un mail slot ouvert par autre composant /// Ainsi P à travers C1 peut envoyer un message dans le mailslot "CSHarp" /// à travers C2 lire un message qui a été envoyé par un autre composant /// Une communication bi directionnelle s'établit donc entre le composant P est un composant extérieur /// <seealso lien="http://msdn.microsoft.com/en-us/library/aa365147(VS.85).aspx"></seealso> public class MailSlot { /// <param name="path">Chemin complet où se situe le mailSlot</param> /// <param name="messageSize">Optionel, taille maximale des messages, la taille /// par défaut est la taille maximale pour l'API window soit 65536</param> /// <param name="timeOutInitial">Temps pour le timeout initial du mail slot</param> public MailSlot(string path, int messageSize = MAX_API_MESSAGE_SIZE, int timeOutInitial = 0) { mailSlotPath = path; messageMaxSize = messageSize; timeOut = timeOutInitial; } #region Routines externes (DLL Imports) /// <summary>dll de l'API windows qui permet la création d'un canal de communication</summary> [DllImport("kernel32.dll")] protected static extern IntPtr CreateMailslot(string lpName, int nMaxMessageSize, int lReadTimeout, IntPtr lpSecurityAttributes); /// <summary>ddl de l'API windows qui récupère des informations concerneant un mail slot</summary> [DllImport("kernel32.dll")] private static extern bool GetMailslotInfo(int hMailslot, ref int lpMaxMessageSize, ref int lpNextSize, ref int lpMessageCount, ref int lpReadTimeout); /// <summary>ddl de l'API windows qui crée un fichier virtuel par rapport au canal de communication précédemment ouvert</summary> [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern Int32 CreateFileW(string lpFileName, uint dwDesiredAccess, uint dwShareMode, int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile); /// <summary>ddl de l'API windows qui permet de lire un message dans un fichier virtuel</summary> [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool ReadFile(int handle, byte[] bytes, int numBytesToRead, out int numBytesRead, int overlapped); /// <summary>ddl de l'API windows qui permet d'écrire un message dans un fichier virtuel</summary> [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool WriteFile(long handle, byte[] bytes, int numBytesToWrite, out int numBytesWritten, int overlapped); /// <summary>ddl de l'API windows qui permet Fermeture du fichier virtuel</summary> [DllImport("kernel32.dll", SetLastError = true)] private static extern bool CloseHandle(int hObject); /// <summary>ddl de l'API windows qui permet de modifier le timeout sur le canal de communication précédemment ouvert</summary> [DllImport("kernel32.dll", SetLastError = true)] private static extern bool SetMailSlotInfo(int hMailslot, int lReadTimeout); #endregion #region Propriétés constantes /// <summary>Taille maximale pour l'API window</summary> protected const int MAX_API_MESSAGE_SIZE = 65536; private const int INVALID_HANDLE_VALUE = -1; //File access private const uint GENERIC_READ = 2147483648; //0x80000000 private const uint GENERIC_WRITE = 1073741824; //0x40000000 //File shares private const int FILE_SHARE_READ = 1; //Creation types private const int CREATE_ALWAYS = 2; private const int OPEN_EXISTING = 3; //File attributes private const int FILE_ATTRIBUTE_NORMAL = 128; #endregion #region Propriétés /// <summary>Taille des messages du mailslot, affecté lors de l'instanciation</summary> protected int messageMaxSize; /// <summary>Chemin complet du mailSlot, affecté lors de l'instanciation</summary> protected string mailSlotPath; /// <summary>le time Out du mail slot, affecté lors de l'instanciation</summary> protected int timeOut; #endregion #region Routines /// <summary> /// Récupère des informations concernant le mailSlot /// </summary> /// <param name="slotHandle">Identifiant du mailSlot</param> /// <param name="maxmsg">Nombre maximum de messages </param> /// <param name="nextmsg">Indicateur du prochain message</param> /// <param name="msgcount">Nombre de messages en attente</param> /// <param name="timeOut">timeout du mailSlot</param> /// <returns> true, la récupération des informations du mailslot a réussie /// false impossible de récupérer les informations concernant le malislot /// </returns> public bool getMailSlotData(int slotHandle, ref int maxmsg, ref int nextmsg, ref int msgcount, ref int timeOut) { bool bret; bret = GetMailslotInfo(slotHandle, ref maxmsg, ref nextmsg, ref msgcount, ref timeOut); return bret; } /// <summary> /// Création du canal de communication /// </summary> /// <param name="maxSize">Taille maximale pour le mailslot</param> /// <returns> 1, la création a réussie /// -1, la création a échoué /// </returns> public int CreateMailSlot(uint maxSize) { int ret; ret = (int)CreateMailslot(mailSlotPath, 0, timeOut, IntPtr.Zero); return ret; } /// <summary> /// Envoie le message au mailslot. /// Le mailslot doit avoit été ouvert /// </summary> /// <param name="message">Le message a envoyer au mailslot</param> /// <returns> 1, l'écriture dans le mail slot a réussie /// -1, une erreur est survenue qui n'a pas permis l'envoi du message /// -2, le fichier associé au mailslot n'existe pas ou n'a pas pu être ouvert /// -3, le message comporte trop de caractères /// -4, le message ne comporte aucun caractère /// </returns> public int SendMail(string message) { bool retWriteFile = false; int retCreateFile; // Identifiant du fichier mailSlot, -1 si le mailslot n'a pu être crée int writen; try { if (message.Length == 0) return -4; if (message.Length > (long)messageMaxSize) return -3; byte[] bMessage = Encoding.Unicode.GetBytes(message); retCreateFile = CreateFileW(mailSlotPath, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); switch (retCreateFile) { case (INVALID_HANDLE_VALUE): return -2; default: retWriteFile = WriteFile(retCreateFile, bMessage, bMessage.Length, out writen, 0); if (retWriteFile) { CloseHandle(retCreateFile); return 1; } else { return -1; } } } catch (Exception ) { return -1; } } /// <summary> /// Lit le prochain message depuis le fichier virtuel du mailslot /// </summary> /// <param name="message">Le message lu dans l afile d'attent du mailslot</param> /// <param name="slotMailHandle">La valeur du poiteur qui identifie l'emplacement du mailslot</param> /// <returns> 1, le message a été correctement lu /// 0, aucun message n'a été lu, file d'attente vide /// -1, une erreur est survenue ne permettant pas de lire le message /// -2, erreur lors de la récupération des données du mailslot /// -3, le mailslot n'a pas été ouvert /// </returns> public int ReadMail(ref string message, int slotMailHandle) { int maxMessageSize = 0; // Longueur maximum du message int nextMessageSize = 0; // Longueur du messages prêt à être lu dans le slotMail int messageCount = 0; // Nombre de messages dans la file d'attente du mailSlot int timeout = 0; // TimeOut défini pour le mailSlot int read = 0; // Longueur du message lut bool RetInfoData = false; try { if (mailSlotExist() == false) return - 3; RetInfoData = getMailSlotData(slotMailHandle, ref maxMessageSize, ref nextMessageSize, ref messageCount, ref timeout); if (RetInfoData == false) return -2; if (messageCount == 0) return 0; var bBuffer = new byte[nextMessageSize]; if (ReadFile(slotMailHandle, bBuffer, nextMessageSize, out read, 0) == false) return -1; else message = Encoding.Unicode.GetString(bBuffer); return 1; // le message a été correctement lu } catch (Exception ) { return -1; } } /// <summary> /// Test l'existence du mail slot /// </summary> /// <returns> true, le mailslot existe /// false, le maislot n'existe pas /// </returns> public bool mailSlotExist() { try { // /// <summary>Identifiant du fichier virtuel</summary> int fileHandle; fileHandle = CreateFileW(mailSlotPath, GENERIC_READ + GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (fileHandle == INVALID_HANDLE_VALUE) { return false; } CloseHandle(fileHandle); return true; } catch (Exception) { return false; } } /// <summary> Fermeture du mailslot </summary> /// <returns> Code retour de closeHandle(aul_slot) </returns> public bool closeMailSlot(int slothandle) { return CloseHandle(slothandle); } /// <summary>Retourne le nombre de messages en attente dans le mailSlot </summary> /// <param name="slotHandle">identifiant du canal de communication</param> /// <returns>Nombres de message dans la file d'attente du mailslot /// -1 si une erreur est survenue </returns> public long getMessageNumber(int slotHandle) { int msgcount = 0; // Nombre de messages en attente int maxmsg = 0; // Paramètres nécessaires à la fonction of_getMailSlotInfo() int nextmsg = 0; int timeout = 0; try { if (getMailSlotData(slotHandle, ref maxmsg, ref nextmsg, ref msgcount, ref timeout)) return (long)msgcount; else return -1; } catch (Exception) { return -1; } } /// <summary> Modifie le timeout du mailSlot</summary> /// <param name="slotHandle">identifiant du canal de communication</param> /// <param name="newtimeOut">le nouveau timeout qui va être affecté au mailslot</param> /// <returns>retour de la fontion setMailSlotInfo() /// false si une erreur est survenue /// </returns> public bool setIimeOut(int slotHandle, int newtimeOut) { try { timeOut = newtimeOut; return SetMailSlotInfo(slotHandle, timeOut); } catch (Exception) { return false; } } #endregion } }
Dernière modification par Dadone (02-10-2013 20:52:50)
Hors ligne