当通过OLE嵌入文档时,Word插件可以保持Word进程的活动 [英] Word Add-in keeps Word process alive when document is embedded via OLE

查看:337
本文介绍了当通过OLE嵌入文档时,Word插件可以保持Word进程的活动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我建立了一个Word加载项,当用户关闭文档时,它必须执行一个任务。我为 Application 对象的 DocumentBeforeClose 事件安装了一个事件处理程序。问题是,当我在Excel工作簿中嵌入现有的Word文档时,事件处理程序似乎阻止Word进程退出。



当我嵌入Excel中的文档插入>对象>从文件创建,然后选择一个Word文档。然后将文档加载到工作簿中。当我关闭Excel winword.exe仍然运行,并且窗口是不可见的。



当我禁用我的加载项,winword.exe只运行了一秒钟嵌入文档。这是我想要与我的加载项启用的行为。



为了缩小问题,我创建了一个简单的VSTO Word加载项进行测试。这些是我对Visual Studio生成的类的更改:

  private void ThisAddIn_Startup(object sender,System.EventArgs e) 
{
Application.DocumentBeforeClose + = Application_DocumentBeforeClose;
}

void Application_DocumentBeforeClose(Word.Document Doc,ref bool Cancel)
{
System.Windows.Forms.MessageBox.Show(Application_DocumentBeforeClose);
}

private void ThisAddIn_Shutdown(object sender,System.EventArgs e)
{
System.Windows.Forms.MessageBox.Show(ThisAddIn_Shutdown);
}

当我启动Word并再次关闭时,此加载项显示消息箱子如预期。当我在Excel工作簿中嵌入Word文档时,DocumentBeforeClose消息稍后弹出一秒钟,但关闭消息不会出现。 winword.exe即使在关闭Excel之后仍会继续运行。



删除事件处理程序挂接的行会导致加载项显示关闭消息1



这导致我认为事件处理程序引起Word的Application对象的引用,这阻止了它从关闭。所以我测试它的方式,因为我也有一个Excel加载项执行相同的任务。为了测试,我创建了一个Excel加载项就像上面的Word加载项,嵌入一个工作簿在Word文档和Excel加载项显示这两个消息,而不留下一个excel.exe过程。



为了找出问题的本质,我试着在DocumentBeforeClose中解开事件处理函数:

  Application.DocumentBeforeClose  -  = Application_DocumentBeforeClose; 
GC.Collect();

这允许winword.exe关闭,但也禁用我的加载项的功能。我不能使用该解决方案,因为事件也会发生,如果只有一个文档,用户关闭它,但想继续使用Word。



我期望Word文档也会嵌入到其他第三方应用程序中,并且嵌入Outlook电子邮件中的文档。


I have built a Word Add-in which has to do a task when the user closes the document. I installed an event handler for the DocumentBeforeClose event of the Application object to do that. The problem is that the event handler appears to prevent the Word process from exiting when I embed an existing Word document in an Excel workbook for example.

The problem occurs when I embed the document in Excel via the Ribbon Insert > Object > Create from File and then select a Word document. The document is then loaded into the workbook. When I close Excel winword.exe is still running and the window is invisible.

When I disable my Add-in, winword.exe is running only for about a second to embed the document. That is the behaviour I want with my Add-in enabled as well.

To narrow down the problem I created a simple VSTO Word Add-in for testing. These are the changes I made to the class generated by Visual Studio:

    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        Application.DocumentBeforeClose += Application_DocumentBeforeClose;
    }

    void Application_DocumentBeforeClose(Word.Document Doc, ref bool Cancel)
    {
        System.Windows.Forms.MessageBox.Show("Application_DocumentBeforeClose");
    }

    private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
    {
        System.Windows.Forms.MessageBox.Show("ThisAddIn_Shutdown");
    }

When I start Word and close it again, this Add-in shows both message boxes as expected. When I embed a Word document in an Excel workbook, the "DocumentBeforeClose" message pops up a second later or so, but the "Shutdown" message does not appear. winword.exe keeps running even after I have closed Excel.

Removing the line where the event handler is hooked up causes the Add-in to show the "Shutdown" message 1 second after the document has been embedded and winword.exe quits.

This led me to think that the event handler causes a reference to the Application-object of Word, which prevents it from shutting down. So I tested it the other way around because I also have an Excel Add-in which does the same task. To test that, I built an Excel Add-in just like the Word Add-in above, embedded a workbook in a Word document and the Excel Add-in shows both messages without leaving behind an excel.exe process.

To figure out the nature of the problem, I tried unhooking the event handler in DocumentBeforeClose:

        Application.DocumentBeforeClose -= Application_DocumentBeforeClose;
        GC.Collect();

This allows winword.exe to shutdown but also disables functionality of my Add-in. I can not use that solution because the event also occurs if there is only one document and the users closes it but wants to keep working with Word. The Add-in has to keep working then as well.

I expect that Word documents will also be embedded in other 3rd party applications and not embedding it will not work for me either.

This problem occurs at least with the VSTO 2007 add-in shown above and a Word 2013 add-in using the PIAs.

I don't think weak event handlers will work because weak references to COM objects are not possible, right?

Can I prevent the event handler from keeping the Word process alive? Are there any other ways to hook the DocumentBeforeClose event or COM events in .NET?

Edit: I was also able to reproduce the problem with an Add-in written in Visual Basic 6 in Word 2003. So it doesn't even seem to be .NET related.

解决方案

Instead of attaching the DocumentBeforeClose event handler on application startup, consider attaching it on document open—and only if it's not an embedded object.

The tricky part is determining whether the document being opened is an embedded object.

I haven't found any documented way to explicitly check whether an Automation application is currently in embedded mode, but there are a number of things you can check to infer that it is.

For example, I've highlighted some properties of Word's Application object below that are not avaiable when the document being opened is an embedded object. If you want to check whether they're available, you may need to use exception handling, since attempting to access such properties may be invalid.

Another thing you can check is that in the WindowActivate event, the document object has a different value for the Kind property when opened as an embedded object. There's an example described here for a document embedded in an Outlook email.

这篇关于当通过OLE嵌入文档时,Word插件可以保持Word进程的活动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆