【问题标题】:C# VSTO Outlook Add-in - Debugging Text Selection Event?C# VSTO Outlook 加载项 - 调试文本选择事件?
【发布时间】:2017-04-06 06:24:50
【问题描述】:

我正在构建一个 Outlook 插件,我想对电子邮件正文中的文本选择更改做出反应。

为此,我将WindowSelectionChange event 附加到邮件项目检查器内的 Word 对象。

if (inspector.IsWordMail())
  {
      wordDoc = inspector.WordEditor as Word.Document;
      wordDoc.Application.WindowSelectionChange += new Microsoft.Office.Interop.Word.ApplicationEvents4_WindowSelectionChangeEventHandler(text_selected);
  }

这有点效果,但随后事件停止触发选择,似乎是随机的。我整天都在做这个,并且无法解决这个问题。

环顾四周后,我读到可能是 wordDoc 对象正在被垃圾收集,因此我确保将其设置为类变量。

无论如何,也许没有整个项目,很难确定问题的确切原因......我的问题更多,我将如何调试这个?如果事件没有被触发,我就没有什么可以断点了。如果事件侦听器不是 wordDoc 应用程序中的属性,我该如何监控它们的状态?

以下是相关类的大部分代码,删除了一些代码。我为这个烂摊子道歉 - 我正在学习这个......

 public class InspectorWrapper
        {
            private Outlook.Inspector inspector;
            private CustomTaskPane taskPane;
            private Dictionary<string, List<ScanResult>> mailItemEntities;

            private bool activated, loaded;
            private Word.Document wordDoc;

            public InspectorWrapper(Outlook.Inspector Inspector)
            {
                inspector = Inspector;

                loaded = false;
                activated = false;

                ((Outlook.InspectorEvents_Event)inspector).Close +=
                    new Outlook.InspectorEvents_CloseEventHandler(InspectorWrapper_Close);

                taskPane = Globals.ThisAddIn.CustomTaskPanes.Add(
                    new TaskPaneControl(), "Addin", inspector);
                taskPane.VisibleChanged += new EventHandler(TaskPane_VisibleChanged);

                mailItemEntities = new Dictionary<string, List<ScanResult>>();

                ((Outlook.InspectorEvents_10_Event)inspector).Activate += new Outlook.InspectorEvents_10_ActivateEventHandler(ThisAddIn_Activate);
            }

            void ThisAddIn_Activate()
            {
                activated = true;
            }

            void text_selected(Word.Selection selected_text)
            {
                if (activated && loaded)
                {
                    ((TaskPaneControl)this.CustomTaskPane.Control).text_selected(selected_text.Text, selected_text.End - selected_text.Start);

                }
            }

            void TaskPane_VisibleChanged(object sender, EventArgs e)
            {
                Globals.Ribbons[inspector].Ribbon1.toggleButton1.Checked = taskPane.Visible;
                if (!loaded) {
                    process_email(this.inspector.CurrentItem as Outlook.MailItem);
                    if (inspector.IsWordMail())
                    {
                        wordDoc = inspector.WordEditor as Word.Document;
                        wordDoc.Application.WindowSelectionChange += new Microsoft.Office.Interop.Word.ApplicationEvents4_WindowSelectionChangeEventHandler(text_selected);
                    }
                    loaded = true;
                }
            }

            void InspectorWrapper_Close()
            {
                if (taskPane != null)
                {
                    Globals.ThisAddIn.CustomTaskPanes.Remove(taskPane);
                }

                activated = false;
                loaded = false;
                taskPane = null;
                Globals.ThisAddIn.InspectorWrappers.Remove(inspector);
                ((Outlook.InspectorEvents_Event)inspector).Close -=
                    new Outlook.InspectorEvents_CloseEventHandler(InspectorWrapper_Close);
                ((Outlook.InspectorEvents_10_Event)inspector).Activate -=
                    new Outlook.InspectorEvents_10_ActivateEventHandler(ThisAddIn_Activate);
                inspector = null;
            }
        }

这是我的主要插件类,以防万一:

    public partial class ThisAddIn
    {
        Outlook.Inspectors inspectors;
        Outlook.MailItem mailItem;
        private string last_id = "";
        private Dictionary<Outlook.Inspector, InspectorWrapper> inspectorWrappersValue =
             new Dictionary<Outlook.Inspector, InspectorWrapper>();
        private Outlook.Inspector ins;

        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            inspectors = this.Application.Inspectors;

            inspectors.NewInspector += new Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);

        }

        void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
        {

            ins = Inspector;
            Outlook.MailItem mailItem = ins.CurrentItem as Outlook.MailItem;
            if (mailItem != null)
            {
                inspectorWrappersValue.Add(ins, new InspectorWrapper(ins));
            }
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
            // Note: Outlook no longer raises this event. If you have code that 
            //    must run when Outlook shuts down, see http://go.microsoft.com/fwlink/?LinkId=506785
            inspectors.NewInspector -=
                new Outlook.InspectorsEvents_NewInspectorEventHandler(
                Inspectors_NewInspector);
            inspectors = null;
            inspectorWrappersValue = null;
        }

        public Dictionary<Outlook.Inspector, InspectorWrapper> InspectorWrappers
        {
            get
            {
                return inspectorWrappersValue;
            }
        }

        #region VSTO generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }

        #endregion
    }

【问题讨论】:

    标签: c# events outlook ms-word vsto


    【解决方案1】:

    引发事件并正在被垃圾收集的不是 wordDoc 变量。就是wordDoc.Application返回的Application对象:

    private Word.Application wordApp;
    ...
    wordApp = wordDoc.Application;
    wordApp.WindowSelectionChange += new Microsoft.Office.Interop.Word.ApplicationEvents4_WindowSelectionChangeEventHandler(text_selected);
    

    【讨论】:

    • 似乎奏效了。有一次我怀疑这是问题的根源,但没有采取行动。 (“显然,如果文档已打开,则应用程序必须打开......无法收集。”)我想这只是意味着我不了解收集。所以,谢谢你——但我认为部分问题仍然存在。出于调试目的,我有什么方法可以更密切地跟踪侦听器的生命周期?
    • 收集的不是内部对象或 GUI 对象,而是 COM 对象。一个 COM 对象(或多个对象 - 您可以让多个 COM 对象包装同一个 GUI 对象)即使它包装的对象仍然非常活跃也会被释放。
    猜你喜欢
    • 1970-01-01
    • 2017-11-04
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-02
    相关资源
    最近更新 更多