2016-08-03 37 views
1

在我的自定义Outlook插件中,该插件用于加载(托管)一个包含一些文本框和登录按钮的WPF用户控件。在一个单独的线程中运行自定义Outlook插件功能,而不会使Outlook挂起

这是我的登录按钮单击事件处理程序

private void lblbtnLogin_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
     { 

      try 
      { 

       //this.Dispatcher.Invoke((Action)(() =>Login())); 
       this.Dispatcher.InvokeAsync((Action)(() => Login())); 
       //Thread loginThread = new Thread(new ThreadStart(Login)); 
       //loginThread.SetApartmentState(ApartmentState.STA); 
       //loginThread.IsBackground = true; 
       //loginThread.Start(); 
       //th.Start(); 
      } 
      catch (Exception exp) 
      { 
       string msg = exp.Message; 
      } 
     } 

,登录方法的代码是

public void Login() 
     { 
      try 
      { 
       if (txtWSUrl.Text == "Enter WebService URL" || txtWSUrl.Text == string.Empty) 
       { 
        MessageBox.Show("WebService URL Cannot be Empty", string.Empty, MessageBoxButton.OK); 
       } 
       else if (txtEmailId.Text == "Enter Email ID" || txtEmailId.Text == string.Empty) 
       { 
        MessageBox.Show("Email ID Cannot be Empty", string.Empty, MessageBoxButton.OK); 
       } 
       else if (txtPwd.Password == "********" || txtPwd.Password == string.Empty) 
       { 
        MessageBox.Show("Password Cannot be Empty", string.Empty, MessageBoxButton.OK); 
       } 
       else 
       { 
        Globals.ThisAddIn.url = txtWSUrl.Text; 
        Summit_BLL.ProxyParamDetails ppd = new Summit_BLL.ProxyParamDetails(); 
        ppd.UserName = txtEmailId.Text; 
        ppd.Password = txtPwd.Password; 
        CommonParameters cp = new CommonParameters(); 
        cp._ProxyDetails = ppd; 

        //Summit_RESTWCF rest = new Summit_RESTWCF(); 
        //string o=rest.LoginApp(ppd); 

        string strJson = Newtonsoft.Json.JsonConvert.SerializeObject(cp); 
        string strMethod = "LoginApp"; 
        string output = WSConsumer.GetWSResult(ref strJson, ref strMethod); 

        OutputParam op = Newtonsoft.Json.JsonConvert.DeserializeObject<OutputParam>(output); 
        if (op.Errors == string.Empty) 
        { 
         string objJson = op.Output; 
         AppUser obj = Newtonsoft.Json.JsonConvert.DeserializeObject<AppUser>(objJson); 
         if (obj.User.UserDetails.Count > 0) 
         { 
          foreach (UserDetail ud in obj.User.UserDetails) 
          { 

          } 
         } 
         //string Feedback = ConfigurationManager.AppSettings["App:RequiredFeedbackModule"].IsNotNullAndEmpty() ? ConfigurationManager.AppSettings["App:RequiredFeedbackModule"].ToString().ToUpper() : "NULL"; 
         WPFUCMaster master = WPFUCMaster.Instance; 
         WPFUCHome home = new WPFUCHome(); 
         master.AddControl(home); 
         //System.Windows.Threading.Dispatcher.Run(); 
        } 
        else 
        { 
         MessageBox.Show(op.Errors, string.Empty, MessageBoxButton.OK); 
        } 

       } 
      } 
      catch (Exception exp) 
      { 
       string msg = exp.Message; 
      } 
     } 

在这里,我试图与调度员和以及与新线程的IM运行此同时,也将前景挂起或没有响应,直到下一个屏幕被加载。

如果我使用新的线程,并通过登录方法构造其抛出异常喜欢

调用线程,因为不同的 线程拥有它不能访问该对象。

任何人都可以请帮助我吗?

+0

这是正常的,UI项目无法访问或更具体地从UI线程外部更改。 – BugFinder

回答

0

Outlook对象模型对象不能通过主线程以外的线程上的插件访问。当您从外部应用程序访问OOM对象时,所有调用都编组到主Outlook线程中。

一些对象用于在辅助线程上工作(几乎碰到和错过),但是对于Outlook 2016,OOM会在检测到辅助线程访问时立即引发异常。

有两件事情可以做:

  1. 如果您只需要几个简单属性,读他们的主线程上到变量并从您的辅助线程访问这些变量。

  2. 如果#1是不是一种选择,你可以使用扩展MAPI(C++或Delphi只),或Redemption(任何语言) - 在Namespace.MAPIOBJECT属性(它返回IMAPISession MAPI对象)的值保存到一个变量。在辅助线程上,创建RDOSession对象的实例,设置RDOSession.MAPIOBJECT属性 - 这样它将共享主Outlook会话。然后,您将能够访问任何存储RDOSession的商店或地址簿对象(大致相当于Namespace对象)。

相关问题