COM Interop - 等待 Excel 完成操作
我正在与 Excel 和其他办公自动化软件进行一些 COM 互操作工作。
一位同事向我提到,在向这些自动化服务器发出命令后,我需要等待它们准备好。
但是,我看不到这样做的目的,因为在自动化服务器完成给定任务之前,所有调用都不会阻塞吗?
例如,我通常会写:
Dim o as AutomationObject = AutomationServer.CreateObject(x, y, z) o.Property ' could throw COM exception!!????
我的同事说我需要在该调用之后睡觉,因为自动化服务器仍然可以创建和初始化对象。
Dim o as AutomationObject = AutomationServer.CreateObject(x, y, z) Threading.Sleep(5000) ' wait for AutomationServer to "become ready" o.Property ' could still throw COM exception!!????
我遇到的问题是,AutomationServer 调用应该阻塞,直到 AutomationServer 完成或完成它正在处理的事情,或者至少应该是一个循环检查“o”是否什么都没有,但这没有意义,因为一旦调用返回完成!
我的问题是,在 AutomationServer 调用后休眠有什么好处吗?是否有一种方法可以“等待”直到 AutomationServer 完成(如果它实际上没有阻塞)?
I am doing some COM Interop work with Excel and other Office Automation Software.
A Co-Worker has mentioned to me that I need to wait for these Automation Servers to become ready after issuing a command to them.
I, however, cannot see the purpose of this as don't all calls block until the automation server completes the given task?
For example I would normally write:
Dim o as AutomationObject = AutomationServer.CreateObject(x, y, z) o.Property ' could throw COM exception!!????
My co-worker says I need to sleep after that call because the the Automation Server could still be working on creating and initializing the object.
Dim o as AutomationObject = AutomationServer.CreateObject(x, y, z) Threading.Sleep(5000) ' wait for AutomationServer to "become ready" o.Property ' could still throw COM exception!!????
The problem I have with this is that the AutomationServer calls should block until the AutomationServer finishes or completes what it was working on or at the very least it should be a loop checking if "o" is nothing, but that makes no sense because once the call returns its done!
My question is, Is there any benefit to Sleeping after an AutomationServer call? Is there a method to "wait" until the AutomationServer finishes (if it does not in fact block)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当访问繁忙的进程外自动化服务器时,您确实可能会遇到异常。对于 Office,发生这种情况的一种方法是,如果您有一个在打开文档时运行的宏。如果您连接到打开了对话框的 Office 应用程序实例,也会遇到问题。
本文介绍了如何避免这种情况:实现 IOleMessageFilter 错误处理程序。本文介绍的是 Visual Studio 的自动化,但其原理和技术对于其他进程外自动化服务器(例如 Office)的自动化是相同的。
You can indeed get an exception when accessing an out-proc Automation server that is busy. In the case of Office, one way this can happen is if you have a macro that runs when you open a document. You will also have problems if you connect to an instance of an Office application that has a dialog box open.
This article describes how you can avoid this by implementing IOleMessageFilter error handlers. The article is about automation of Visual Studio, but the principles and techniques are the same for automating other out-proc automation servers such as Office.
处理这个问题的简单方法如下。我最近必须与 Visual Studio 进行交互,我发现如果您愿意在 COM 对象变得无限繁忙时快速失败,那么这种方法效果很好。看看这是否适合您:
在范围内拥有此委托和方法之后,下面是使用匿名委托的方法调用和属性访问的示例。
我故意隐藏了 COMException,因为我不想要它,但如果您需要它,只需在 MakeRiskyCOMCall 方法中设置一个 COMException 变量,该变量的范围在调用方法内。您还可以检查指示等待繁忙进程的特定 HResult,并检查其他 HResult 更快地失败。这个解决方案速度很快,并且避免了所有 COM 互操作的混乱,它的缺点是它不太漂亮,但它有效,并且对于代码的维护者来说更容易理解(我认为)。
A simple way to deal with this is below. I had to interface with Visual Studio recently, and I found this worked well, if you are willing to fail out quickly on the COM object becoming infinitely busy. See if this will work for you:
After you have this delegate and method in scope, then here are examples of a method call and a property access using anonymous delegation.
I deliberately hid the COMException, since I didn't want it, but if you need it just set a COMException variable within the MakeRiskyCOMCall method that is scoped within the calling method. You could also check for the specific HResult that indicates waiting for a busy process and fail more quickly for other HResults. This solution is quick and avoids all the COM interop messiness, and it's downside is that it isn't pretty, but it works and is easier to figure out for the maintainers of your code (I think).