3

我创建了一个用户控件(windows 窗体应用程序)来获取 Word 的一个实例(活动的或新的),并提供一个按钮来使用文件对话框选择器将文档打开到该实例中。

该表单包含 2 个按钮,1 个用于获取单词实例,另一个用于打开文档。它还包含一个用于显示打开文档的列表框和一个 openfiledialog 控件,用于提供选择要打开的文档的方法。

我正在处理 Application.DocumentOpen 事件以填充列表框...

m_wordApp.DocumentOpen += new msoWord.ApplicationEvents4_DocumentOpenEventHandler(m_wordApp_DocumentOpen);

我正在确定何时需要重新调用填充列表框的方法,以确保对控件的访问位于创建它的同一线程上......

private void AddDocument(string name)
{
    try
    {
        if (m_documentsListBox.InvokeRequired && m_documentsListBox.IsHandleCreated&&!m_documentsListBox.IsDisposed)
        {
            this.Invoke(m_AddDocument, new object[] { name });
            return;
        }

        if (!m_documentsListBox.Items.Contains(name))
            m_documentsListBox.Items.Add(name);
    }
    catch (Exception ex)
    {
    }
}

我没有使用 2 个点,我相信我正确地释放了任何 COM 对象。

为什么应用程序会挂在打开文档的代码行中...

WordDoc = m_wordDocs.Open(ref fileName);

或重新调用 AddDocument() 方法的行...

this.Invoke(m_AddDocument, new object[] { name });

我想我一定是遇到了线程问题,因为只有当我选择使用按钮打开文档而不是直接从 Word 应用程序中打开文档时才会发生挂起。

完整代码如下...


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Runtime.InteropServices;

//  use these for the core office & word references
using msoWord = Microsoft.Office.Interop.Word;


namespace MCDevNET.Office.Word.TestUIControls
{
    public partial class OpenWordDocument : Form
    {
        public OpenWordDocument()
        {
            InitializeComponent();

            m_openWordButton.Click += new EventHandler(buttonOpenWordApp_Click);
            m_openDocumentButton.Click += new EventHandler(buttonOpenDocument_Click);

            m_AddDocument = new UpdateListControl(AddDocument);
        }

        #region Form: control eventHandlers

        void buttonOpenWordApp_Click(object sender, EventArgs e)
        {
            try
            {
                if (!IsValid(m_wordApp))
                    WordApp = GetInstance();
                AddAllDocuments();
            }
            catch (Exception ex)
            {
            }
        }

        void buttonOpenDocument_Click(object sender, EventArgs e)
        {
            OpenWordDoc();
        }

        public delegate void UpdateListControl(string name);
        private UpdateListControl m_AddDocument;

    private void AddDocument(string name)
    {
        try
        {
            if (m_documentsListBox.InvokeRequired && m_documentsListBox.IsHandleCreated&&!m_documentsListBox.IsDisposed)
            {
                this.Invoke(m_AddDocument, new object[] { name });
                return;
            }

            if (!m_documentsListBox.Items.Contains(name))
                m_documentsListBox.Items.Add(name);
        }
        catch (Exception ex)
        {
        }
    }

        private void AddAllDocuments()
        {
            try
            {
                m_documentsListBox.Items.Clear();
                if (m_wordDocs != null)
                {
                    for (int i = 1; i <= m_wordDocs.Count; i++)
                        AddDocument(m_wordDocs[i].Name);
                }
            }
            catch (Exception ex)
            {
            }
        }

        #endregion


        #region Word: properties & eventhandlers

        private msoWord.Document m_wordDoc;
        public msoWord.Document WordDoc
        {
            get { return m_wordDoc; }
            private set
            {
                try
                {
                    if (m_wordDoc != value)
                    {
                        ReleaseCOMObject(m_wordDoc);
                        m_wordDoc = value;
                    }
                }
                catch (Exception ex)
                {
                }
            }
        }

        private msoWord.Documents m_wordDocs;
        public msoWord.Documents WordDocs
        {
            get { return m_wordDocs; }
            private set
            {
                try
                {
                    if (m_wordDocs != value)
                    {
                        ReleaseCOMObject(m_wordDocs);
                        m_wordDocs = value;
                    }
                }
                catch (Exception ex)
                {
                }
            }
        }

        private msoWord.Application m_wordApp;
        public msoWord.Application WordApp
        {
            get { return m_wordApp; }
            set
            {
                try
                {
                    if (m_wordApp != value)
                    {
                        if (m_wordApp != null)
                        {
                            m_wordApp.DocumentOpen -= new msoWord.ApplicationEvents4_DocumentOpenEventHandler(m_wordApp_DocumentOpen);
                            ReleaseCOMObject(m_wordApp);
                        }

                        m_wordApp = value;

                        if (IsValid(m_wordApp))
                        {
    m_wordApp.DocumentOpen += new msoWord.ApplicationEvents4_DocumentOpenEventHandler(m_wordApp_DocumentOpen);
                            WordDocs = m_wordApp.Documents;
                        }
                    }
                }
                catch (Exception ex)
                {
                }
            }
        }

        void m_wordApp_DocumentOpen(msoWord.Document doc)
        {
            try
            {
                string name = doc.Name;
                AddDocument(name);
            }
            catch (Exception ex)
            {
            }
            finally
            {
                ReleaseCOMObject(doc);
                doc = null;
            }
        }

        private msoWord.Application GetInstance()
        {
            msoWord.Application app = null;
            try
            {
                app = (msoWord.Application)Marshal.GetActiveObject("Word.Application");
            }
            catch (Exception ex)
            {
                if (app == null)
                    app = new msoWord.Application();
            }
            finally
            {
                if (IsValid(app))
                {
                    app.Visible = true;
                    app.Activate();
                }
            }
            return app;
        }

        private void OpenWordDoc()
        {
            try
            {
                m_openFileDialog.AddExtension = true;
                m_openFileDialog.Filter = "All Word (*.docx; *.docm; *.doc; *.dotx; *.dotm; *.dot)|*.docx;*.docm;*.doc;*.dotx;*.dotm;*.dot|Word Documents (*.docx)|*.docx|Word Macro-Enabled Documents (*.docm)|*.docm|Word 97-2003 Documents (*.doc)|*.doc|All Word Templates (*.dotx; *.dotm; *.dot)|*.dotx;*.dotm;*.dot|Word Templates (*.dotx)|*.dotx|Word Macro-Enabled Templates (*.dotm)|*.dotm)";
                m_openFileDialog.FilterIndex = 1;
                m_openFileDialog.Multiselect = false;
                m_openFileDialog.Title = "Open Word Document";

                if (m_openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    object fileName = m_openFileDialog.FileName;
                    WordDoc = m_wordDocs.Open(ref fileName);
                }
            }
            catch (Exception ex)
            {
            }
        }

        private bool IsValid(msoWord.Application app)
        {
            try
            {
                if (app != null)
                {
                    string name = app.Caption;
                    return true;
                }
            }
            catch (Exception ex)
            {
            }
            return false;
        }
        #endregion

        private void ReleaseCOMObject(object comObject)
        {
            try
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
                GC.WaitForPendingFinalizers();

                if (comObject != null && Marshal.IsComObject(comObject))
                    Marshal.ReleaseComObject(comObject);

            }
            catch (Exception ex)
            {
            }
        }
    }
}
namespace MCDevNET.Office.Word.TestUIControls
{
    partial class OpenWordDocument
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.m_documentsListBox = new System.Windows.Forms.ListBox();
            this.m_openDocumentButton = new System.Windows.Forms.Button();
            this.m_openWordButton = new System.Windows.Forms.Button();
            this.m_openFileDialog = new System.Windows.Forms.OpenFileDialog();
            this.SuspendLayout();
            // 
            // lb_Documents
            // 
            this.m_documentsListBox.FormattingEnabled = true;
            this.m_documentsListBox.Location = new System.Drawing.Point(12, 41);
            this.m_documentsListBox.Name = "lb_Documents";
            this.m_documentsListBox.Size = new System.Drawing.Size(156, 134);
            this.m_documentsListBox.TabIndex = 8;
            // 
            // m_openDocumentButton
            // 
            this.m_openDocumentButton.Location = new System.Drawing.Point(93, 12);
            this.m_openDocumentButton.Name = "m_openDocumentButton";
            this.m_openDocumentButton.Size = new System.Drawing.Size(75, 23);
            this.m_openDocumentButton.TabIndex = 7;
            this.m_openDocumentButton.Text = "Doc";
            this.m_openDocumentButton.UseVisualStyleBackColor = true;
            // 
            // m_openWordButton
            // 
            this.m_openWordButton.Location = new System.Drawing.Point(12, 12);
            this.m_openWordButton.Name = "m_openWordButton";
            this.m_openWordButton.Size = new System.Drawing.Size(75, 23);
            this.m_openWordButton.TabIndex = 6;
            this.m_openWordButton.Text = "Word";
            this.m_openWordButton.UseVisualStyleBackColor = true;
            // 
            // m_openFileDialog
            // 
            this.m_openFileDialog.FileName = "openFileDialog1";
            // 
            // OpenWordDocument
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(182, 184);
            this.Controls.Add(this.m_documentsListBox);
            this.Controls.Add(this.m_openDocumentButton);
            this.Controls.Add(this.m_openWordButton);
            this.Name = "OpenWordDocument";
            this.Text = "OpenWordDocument";
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.ListBox m_documentsListBox;
        private System.Windows.Forms.Button m_openDocumentButton;
        private System.Windows.Forms.Button m_openWordButton;
        private System.Windows.Forms.OpenFileDialog m_openFileDialog;
    }
}
4

1 回答 1

1

挂起发生在调用Documents.Open(fileName)

您有一个为Application.DocumentOpen事件连接的事件处理程序。删除此事件处理程序后,不再发生挂起。

我认为问题的原因是您陷入僵局,因为 Word 试图在Documents.Open调用返回之前触发该事件。这意味着处理事件的线程仍然很忙。

更换

WordDoc = m_wordDocs.Open(ref fileName)

 new System.Threading.Tasks.Task(() => WordDoc = m_wordDocs.Open(ref fileName))
                           .Start();

在不同的线程上打开文档似乎可以解决问题。

于 2013-05-30T16:26:09.097 回答