首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我的IMessageFilter并不总是有效?

为什么我的IMessageFilter并不总是有效?
EN

Stack Overflow用户
提问于 2010-10-12 18:03:47
回答 2查看 1.9K关注 0票数 3

我正在研究Word自动化,为了消除"Call was rejected by callee“/ "the message filter表明应用程序正忙”的错误,我实现了一个IMessageFilter。当我直接自动化Word时,messagefilter的工作方式就像一个护身符:

代码语言:javascript
复制
Word.Documents.Open(...)
Document.SaveAs(...)

但是,当我调用TOleContainer.DoVerb(ovPrimary)时,当Word显示模式对话框时,仍然会出现错误。为什么TOleContainers DoVerb方法不支持MessageFilter?

EN

回答 2

Stack Overflow用户

发布于 2010-10-12 18:38:42

"Call is rejected by callee“是当Word处于交互状态时总是会得到的结果,即显示一个对话框。这并不限于Word。在Excel中也会发生这种情况,例如当用户编辑单元格时。而且它在用户界面中也不需要很明显。当您开始编辑单元格,将焦点移动到另一个应用程序并返回到Excel时,UI不会给您提供线索,但它仍处于“交互”模式,并将拒绝自动化调用,并显示"Call was rejected by callee“错误。

因此,基本上,当您将Word与用户交互(而不仅仅是后台进程中的Word )一起自动化时,您应该准备好获取和处理这些错误。

编辑如果您想在调用任何其他COM方法之前知道Excel或Word是否处于交互模式:只需询问COM服务器是否已准备就绪:

代码语言:javascript
复制
Result := _GetActiveOleObject('Excel.Application');

try
  aSharedInstance := not VarIsClear(Result);
  if aSharedInstance then
    Version := Result.Version;  // If this produces an exception, then use a dedicated instance.

  // In case checking the version does not produce an exception, but Excel still isn't
  // ready, we'll check that as well.
  // By the way, for some unclear reason, partial evaluation does not work on .Ready, 
  // so we'll do it like this:
  if aSharedInstance and (StrToIntDef(StringBefore('.', Version), 0) >= EXCEL_VERSION_2002) then
    aSharedInstance := Result.Ready;
except
  aSharedInstance := False;
end;

if not aSharedInstance then
  Result := CreateOleObject('Excel.Application');

微软更新显然没有“就绪”属性(谁说微软是一致的?)。在这种情况下,您需要在实际调用之前调用一个简单(且快速)的属性,并假设当抛出异常时,Word还没有准备好,从而自己确定它是否就绪。在上面的示例中,在Ready属性之前检索版本。如果抛出异常,我们就假定应用程序(在本例中是Excel)还没有准备好,并相应地进行处理。

大致是这样的:

代码语言:javascript
复制
while Tries <= MaxTries do
  try
    Version := Word.Version;
    Tries := MaxTries + 1; // Indicate success
    Word.TheCallYouReallyWantToDo;
  except
    Inc(Tries);
    sleep(0);
  end;

备注 Word.Version在打开对话框时不会抛出异常,因此这对于确定Word是否准备就绪没有任何用处。:(你必须进行实验,才能找到一个这样的人。

票数 8
EN

Stack Overflow用户

发布于 2013-01-30 11:42:06

IMessageFilter不能处理所有异常,例如,在某些情况下,office应用程序“挂起”它们的对象模型,此时它不能被调用并抛出:0x800AC472 (VBA_E_IGNORE)

为了解决这个问题,你必须把你的调用放在一个循环中,并等待它成功:

代码语言:javascript
复制
while(true)
{
    try
    {
        office_app.DoSomething();
        break;
    }
    catch(COMException ce)
    {
        LOG(ce.Message);
    }
}

// continue after successful call

有关更多详细信息,请参阅here

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3913469

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档