2011-03-24 57 views
3

如果啓動Outlook,您將在下面找到一個旨在在Outlook上下文菜單中添加按鈕的類的提取。 未啓動Outlook時,將啓動啓動EventWatcher以檢測Outlook啓動。 關閉EventWatcher也被設置爲在Outlook關閉時允許清理資源。監視Outlook啓動/關閉

我在管理員模式下運行該代碼,但應用隨機崩潰。如果我禁用EventWatchers周圍的所有代碼,它是穩定的。我找不到這些崩潰的起因,你能幫我嗎? (請原諒我在法文中的評論)。

入口點是tryHook方法。

public class OutlookIF 
{ 
    // Attributs métiers  
    private Outlook.Application outlook = null; 

    // Process watch 
    private ManagementEventWatcher startWatch = 
     new ManagementEventWatcher(new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace WHERE ProcessName = 'OUTLOOK.EXE'")); 
    private ManagementEventWatcher stopWatch = 
     new ManagementEventWatcher(new WqlEventQuery("SELECT * FROM Win32_ProcessStopTrace WHERE ProcessName = 'OUTLOOK.EXE'"));  

    // Gestion du singleton 
    private static OutlookIF v_instance = null; 
    public static OutlookIF Instance 
    { 
     get 
     { 
      if (v_instance == null) 
       v_instance = new OutlookIF(); 

      return v_instance; 
     } 
    } 

    private OutlookIF() 
    { 
     // Récupération des évènements EventArrived 
     startWatch.EventArrived += new EventArrivedEventHandler(startWatch_EventArrived); 
     stopWatch.EventArrived += new EventArrivedEventHandler(stopWatch_EventArrived);   
    } 

    // Vérification de la présence d'un process Outlook running 
    private bool outlookIsLaunched = (Process.GetProcessesByName("outlook").Count() > 0); 

    //Tentative de connexion à Outlook 
    public void tryHook() 
    { 
     if (this.outlookIsLaunched) 
     { 
      this.hookOutlook(); 
      this.stopWatch.Start(); 
     } 
     else 
      this.startWatch.Start();  
    } 

    // Ajout du menu contextuel à Outlook 
    private void hookOutlook() 
    { 
     // Création de l'objet application 
     if (this.outlookIsLaunched) 
      this.outlook = Marshal.GetActiveObject("Outlook.Application") as Outlook.Application; 
     else 
      this.outlook = new Outlook.ApplicationClass(); 

     // Création de l'entrée dans le menu contextuel   
     this.outlook.ItemContextMenuDisplay += new Outlook.ApplicationEvents_11_ItemContextMenuDisplayEventHandler(addEntrytoContextMenu);   
    } 

    // Nettoyage des objets 
    private void clean() 
    { 
     Marshal.FinalReleaseComObject(this.outlook); 
     this.outlook = null; 
    } 

    private void startWatch_EventArrived(object sender, EventArrivedEventArgs e) 
    { 
     // Arrêt de l'écoute de l'ouverture 
     this.startWatch.Stop(); 

     TrayIcon.afficheMessage("ProcessWatch", "Ouverture d'Outlook");   
     this.hookOutlook(); 

     // Démarrage de l'écoute de la fermeture 
     this.stopWatch.Start(); 
    } 

    private void stopWatch_EventArrived(object sender, EventArrivedEventArgs e) 
    { 
     // Arrêt de l'écoute de la fermeture 
     this.stopWatch.Stop(); 

     TrayIcon.afficheMessage("ProcessWatch", "Fermeture d'Outlook");   
     this.clean(); 

     // Démarrage de l'écoute de l'ouverture 
     this.startWatch.Start(); 
    } 
} 

回答

0

我簡化了代碼,並將其放入一個線程中,它似乎工作。儘管如此,還是有一個巨大的缺點:Oulook和程序都應該以管理員模式運行。 我對新命題的限制較少。

下面是創建線程:

Thread outlThread = new Thread(new ThreadStart(OutlookIF.Instance.tryHook)); 
     outlThread.Start(); 

而且新類:

public class OutlookIF 
{ 
    // Attributs métiers  
    private Outlook.Application outlook; 
    private String messageIDParam = "http://schemas.microsoft.com/mapi/proptag/0x1035001E"; 

    // Process watch 
    private ManagementEventWatcher startWatch; 
    private ManagementEventWatcher stopWatch; 

    // Static Initialization Singleton Pattern 
    private static readonly OutlookIF v_instance = new OutlookIF(); 
    public static OutlookIF Instance{get{return v_instance;}} 

    private OutlookIF() 
    { 
     // Création des processWatchers 
     startWatch = new ManagementEventWatcher(new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace WHERE ProcessName = 'OUTLOOK.EXE'")); 
     stopWatch = new ManagementEventWatcher(new WqlEventQuery("SELECT * FROM Win32_ProcessStopTrace WHERE ProcessName = 'OUTLOOK.EXE'"));  
    } 

    //Tentative de connexion à Outlook 
    public void tryHook() 
    { 
     while(true) 
     { 
      if (Process.GetProcessesByName("outlook").Length == 0) 
       startWatch.WaitForNextEvent(); 

      try 
      { 
       this.outlook = new Outlook.ApplicationClass();  
       this.outlook.ItemContextMenuDisplay += new Outlook.ApplicationEvents_11_ItemContextMenuDisplayEventHandler(addEntrytoContextMenu); 
      } 
      catch(Exception e) 
      { 
       MessageBox.Show(e.ToString()); 
      } 

      stopWatch.WaitForNextEvent(); 
      Marshal.FinalReleaseComObject(this.outlook); 
      this.outlook = null; 
     } 
    } 
}