2011-03-24 102 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; 
     } 
    } 
}