2012-03-28 20 views
7

Ho un servizio Windows per l'elaborazione dei messaggi MSMQ. Si basa sulla seguente logicaElaborazione del messaggio MSMQ nel servizio Windows

· C'è un timer nel servizio di Windows. Ogni dieci minuti eseguirà il metodo denominato "ProcessMessages".

· All'interno di questo metodo, crea innanzitutto un elenco di messageId esistenti chiamando il metodo GetAllMessages della coda.

· Per ogni messageId, si riceve il messaggio (utilizzando ReceiveById) e lo memorizza in un file

C'è un modo migliore per ottenere l'elaborazione dei messaggi?

Riferimento: http://www.switchonthecode.com/tutorials/creating-a-simple-windows-service-in-csharp

Nota: Il seguente codice non dà il risultato desiderato quando ho fatto come un servizio; tuttavia non vi è alcun errore nel visualizzatore di eventi (non sto facendo alcuna registrazione esplicita). Stava funzionando bene quando si trattava di una semplice app per console. Come correggerlo? [Ora funziona quando ho cambiato l'account in "Utente" come shwon nei commenti sotto]

Il mio requisito di accesso è di elaborare tutti i messaggi in fasce orarie fisse - diciamo solo alle 10 e alle 11 (in ogni giorno). Qual è l'approccio migliore per farlo?

namespace ConsoleSwitchApp 
{ 
    class Program : ServiceBase 
    { 
     private static Timer scheduleTimer = null; 
     static MessageQueue helpRequestQueue = null; 
     static System.Messaging.XmlMessageFormatter stringFormatter = null; 

     static void Main(string[] args) 
     { 
      ServiceBase.Run(new Program()); 
     } 

     public Program() 
     { 
      this.ServiceName = "LijosService6"; 

      //Queue initialize 
      helpRequestQueue = new MessageQueue(@".\Private$\MyPrivateQueue", false); 
      stringFormatter = new System.Messaging.XmlMessageFormatter(new string[] { "System.String" }); 

      //Set Message Filters 
      MessagePropertyFilter filter = new MessagePropertyFilter(); 
      filter.ClearAll(); 
      filter.Body = true; 
      filter.Label = true; 
      filter.Priority = true; 
      filter.Id = true; 
      helpRequestQueue.MessageReadPropertyFilter = filter; 

      //Start a timer 
      scheduleTimer = new Timer(); 
      scheduleTimer.Enabled = true; 
      scheduleTimer.Interval = 120000;//2 mins 
      scheduleTimer.AutoReset = true; 
      scheduleTimer.Start(); 
      scheduleTimer.Elapsed += new ElapsedEventHandler(scheduleTimer_Elapsed); 
     } 

     protected static void scheduleTimer_Elapsed(object sender, ElapsedEventArgs e) 
     { 
      ProcessMessages(); 
     } 

     private static void ProcessMessages() 
     { 
      string messageString = "1"; 

      //Message Processing 
      List<string> messageIdList = GetAllMessageId(); 
      foreach (string messageId in messageIdList) 
      { 
       System.Messaging.Message messages = helpRequestQueue.ReceiveById(messageId); 
       //Store the message into database 

       messages.Formatter = stringFormatter; 
       string messageBody = System.Convert.ToString(messages.Body); 

       if (String.IsNullOrEmpty(messageString)) 
       { 
        messageString = messageBody; 
       } 
       else 
       { 
        messageString = messageString + "___________" + messageBody; 
       } 
      } 

      //Write File 
      string lines = DateTime.Now.ToString(); 
      lines = lines.Replace("/", "-"); 
      lines = lines.Replace(":", "_"); 
      System.IO.StreamWriter file = new System.IO.StreamWriter("c:\\test" + lines + ".txt"); 
      file.WriteLine(messageString); 
      file.Close(); 
     } 

     private static List<string> GetAllMessageId() 
     { 
      List<string> messageIdList = new List<string>(); 

      DataTable messageTable = new DataTable(); 
      messageTable.Columns.Add("Label"); 
      messageTable.Columns.Add("Body"); 

      //Get All Messages 
      System.Messaging.Message[] messages = helpRequestQueue.GetAllMessages(); 
      for (int index = 0; index < messages.Length; index++) 
      { 
       string messageId = (System.Convert.ToString(messages[index].Id)); 
       messageIdList.Add(messageId); 

       messages[index].Formatter = stringFormatter; 
       messageTable.Rows.Add(new string[] { messages[index].Label, messages[index].Body.ToString() }); 
      } 

      return messageIdList; 
     } 


     protected override void OnStart(string[] args) 
     { 
      base.OnStart(args); 
     } 

     protected override void OnStop() 
     { 
      base.OnStop(); 
     } 
    } 
} 

namespace ConsoleSwitchApp 
{ 
    [RunInstaller(true)] 
    public class MyWindowsServiceInstaller : Installer 
    { 
     public MyWindowsServiceInstaller() 
     { 
      var processInstaller = new ServiceProcessInstaller(); 
      var serviceInstaller = new ServiceInstaller(); 

      //set the privileges 
      processInstaller.Account = ServiceAccount.LocalSystem; 
      serviceInstaller.DisplayName = "LijosService6"; 
      serviceInstaller.StartType = ServiceStartMode.Manual; 

      //must be the same as what was set in Program's constructor 

      serviceInstaller.ServiceName = "LijosService6"; 

      this.Installers.Add(processInstaller); 
      this.Installers.Add(serviceInstaller); 
     } 
    } 
} 
+1

È probabilmente un problema di autorizzazioni. Prova a utilizzare uno degli altri account predefiniti. –

+0

@ M.Babcock Grazie .. Il servizio ha funzionato quando ho usato ServiceAccount.User e ho dato il mio nome utente e password. Qual è l'account suggerito qui? – Lijo

+1

Consiglio vivamente ** non ** utilizzando un account utente dedicato in un ambiente di produzione per questo. Il problema è probabilmente correlato a [questo articolo della Knowledge Base] (http://support.microsoft.com/kb/952569) (si tratta di Vista, ma probabilmente lo stesso problema sarebbe presente in 7 e nel 2008). –

risposta

14

Una bella alternativa all'utilizzo di un timer è quello di utilizzare il metodo MessageQueue.BeginReceive e fare il lavoro in caso ReceiveCompleted. In questo modo il codice attenderà fino a quando non ci sarà un messaggio in coda e quindi elaborerà immediatamente il messaggio, quindi verificherà il messaggio successivo.

A breve stub (un esempio completo in questo articolo di MSDN collegato.)

private void Start() 
{ 
    MessageQueue myQueue = new MessageQueue(".\\myQueue"); 

    myQueue.ReceiveCompleted += 
     new ReceiveCompletedEventHandler(MyReceiveCompleted); 

    myQueue.BeginReceive(); 
} 

private static void MyReceiveCompleted(Object source, 
    ReceiveCompletedEventArgs asyncResult) 
{ 
    try 
    { 
     MessageQueue mq = (MessageQueue)source; 
     Message m = mq.EndReceive(asyncResult.AsyncResult); 

     // TODO: Process the m message here 

     // Restart the asynchronous receive operation. 
     mq.BeginReceive(); 
    } 
    catch(MessageQueueException) 
    { 
     // Handle sources of MessageQueueException. 
    } 

    return; 
} 
+0

Il mio requisito è quello di elaborare tutti i messaggi in fasce orarie fisse - diciamo solo alle 10.00 e alle 11.00 (ogni giorno). Qual è l'approccio migliore per farlo? – Lijo

+6

Utilizzare l'Utilità di pianificazione di Windows per eseguire un'applicazione console. – Tommassiov

2

Perché non aderire a ReceiveCompleted evento? Un'altra opzione, se sia il mittente che il sottoscrittore sono progetti .Net su cui stai lavorando, usa WCF over MSMQ.

+0

Il mio requisito è quello di elaborare tutti i messaggi in fasce orarie fisse - diciamo solo alle 10:00 e alle 11:00 (ogni giorno). Qual è l'approccio migliore per farlo? – Lijo

+1

Potrebbe essere necessario concedere l'accesso a MSMQ all'account di dominio anonimo – paramosh

Problemi correlati