PB à toute heure et à tout moment. (à parcourir avec modération)

Le forum (ô combien francophone) des utilisateurs de Powerbuilder.

Recherche rapide

Annonce

Certaines rubriques, dont des cours, sont uniquement visibles par les membres du forum ^^.
Dans la rubrique Liens & Références, vous avez accès à un sommaire de téléchargement, profitez-en !
Il existe maintenant un nouveau TOPIC "Votre CV en Ligne" accessible uniquement par demande.

#1 02-10-2013 14:43:16

Dadone  
Membre Power Geek
Lieu: Avon (Seine et Marne)
Date d'inscription: 19-02-2007
Messages: 252
Pépites: 985
Banque: 0
Site web

Mail slot C#

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 !

Code: C#

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

 

Pied de page des forums

Propulsé par FluxBB 1.2.22