「呼叫被被叫方拒絕」是Word處於交互狀態時總是得到的,即顯示對話框。這不限於Word。它也發生在Excel中,例如當用戶編輯單元格時。在用戶界面中也不一定非常明顯。當你開始編輯一個單元格時,將焦點移動到另一個應用程序並回到Excel中,UI不會給你提示,但它仍然處於「交互」模式,並會拒絕自動化調用,「調用被調用者拒絕」錯誤。
因此,基本上當您結合用戶交互(而不僅僅是在後臺進程中使用Word)自動化Word時,您應該準備好獲取並處理這些錯誤。
編輯 如果你想知道Excel或Word是否在交互模式調用任何其他COM方法之前:剛纔問的COM服務器是否是「就緒」:
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」屬性(誰說微軟是一致的?)。在這種情況下,您需要通過在實際調用之前調用簡單(和快速)的屬性來自己決定是否準備就緒,並假設當拋出異常時,Word還沒有準備好。在上面的例子中,版本在Ready屬性之前被檢索。如果拋出異常,我們只是假設應用程序(在這種情況下爲Excel)尚未準備就緒,並據此進行操作。
線沿線的東西:
while Tries <= MaxTries do
try
Version := Word.Version;
Tries := MaxTries + 1; // Indicate success
Word.TheCallYouReallyWantToDo;
except
Inc(Tries);
sleep(0);
end;
注意 Word.Version不不拋出一個異常,當一個對話框打開,這樣是沒有用搞清楚Word是否已準備就緒。 :(你將不得不嘗試找到一個可以做到的事情
當然,我知道那就是爲什麼我實施了這個IMessageFilter。這樣,當Word處於模態狀態(如顯示字體對話框)時,我可以顯示「服務器正忙」對話框。問題是,當在TOleContainer上調用DoVerb時,我的IMessageFilter實現不起作用。 – 2010-10-12 11:06:24
@The_Fox:你是說在TOleContainer上調用DoVerb,即使Word不顯示對話或以其他方式「參與」?如果是這樣的話,那麼你的問題對我來說就不清楚了。 – 2010-10-12 11:15:33
不,我的意思是:當我在Word顯示模型對話框時調用DoVerb時,出現提到的錯誤,註冊了IMessageFilter。 – 2010-10-12 11:36:06