我一直在Word2010.pas
過去一週的工作,一切都很順利,直到我發現如果你打開一個手動文件,編輯它(但不保存),按Alt + F4,一個提示將顯示說如果你想保存你的文件或不,保持這樣的。 進入代碼並嘗試訪問該文檔,所有調用將導致EOleException: Call was rejected by callee
。一旦你取消Word保存提示,一切工作正常。`EOleException:呼叫被拒絕被調用者`同時迭代'Office.Interop.Word.Documents`
我在編寫定期檢查文檔是否打開的代碼時遇到了這個問題。下面是一個檢查,如果該文件是開放的功能:(功能運行在一個計時器每2秒)
function IsWordDocumentOpen(FileName: string): Boolean;
var
WordApp: TWordApplication;
I: Integer;
begin
Result := False;
try
WordApp := TWordApplication.Create(nil);
try
WordApp.Connect;
for I := 1 to WordApp.Documents.Count do
begin
try
if WordApp.Documents.Item(I).FullName = FileName then
begin
Result := True;
System.Break;
end;
except
on E: EOleException do
// I always end up here while the document has the prompt
end;
end;
finally
FreeAndNil(WordApp);
end;
finally
//
end;
end;
有沒有人有這方面的經驗?有沒有我不知道的某種鎖?
更新#1:到目前爲止,我唯一能找到的解決方案是實現IOleMessageFilter
,這樣一來我沒有收到任何異常,但程序停止,等待上線WordApp.Documents.Item(I).FullName
,但是這不是我想要的。的IOleMessageFilter
實現是這樣的:
type
IOleMessageFilter = class(TInterfacedObject, IMessageFilter)
public
function HandleInComingCall(dwCallType: Longint; htaskCaller: HTask;
dwTickCount: Longint; lpInterfaceInfo: PInterfaceInfo): Longint;stdcall;
function RetryRejectedCall(htaskCallee: HTask; dwTickCount: Longint;
dwRejectType: Longint): Longint;stdcall;
function MessagePending(htaskCallee: HTask; dwTickCount: Longint;
dwPendingType: Longint): Longint;stdcall;
procedure RegisterFilter();
procedure RevokeFilter();
end;
implementation
function IOleMessageFilter.HandleInComingCall(dwCallType: Integer; htaskCaller: HTask; dwTickCount: Integer; lpInterfaceInfo: PInterfaceInfo): Longint;
begin
Result := 0;
end;
function IOleMessageFilter.MessagePending(htaskCallee: HTask; dwTickCount, dwPendingType: Integer): Longint;
begin
Result := 2 //PENDINGMSG_WAITDEFPROCESS
end;
procedure IOleMessageFilter.RegisterFilter;
var
OldFilter: IMessageFilter;
NewFilter: IMessageFilter;
begin
OldFilter := nil;
NewFilter := IOleMessageFilter.Create;
CoRegisterMessageFilter(NewFilter,OldFilter);
end;
function IOleMessageFilter.RetryRejectedCall(htaskCallee: HTask; dwTickCount, dwRejectType: Integer): Longint;
begin
Result := -1;
if dwRejectType = 2 then
Result := 99;
end;
procedure IOleMessageFilter.RevokeFilter;
var
OldFilter: IMessageFilter;
NewFilter: IMessageFilter;
begin
OldFilter := nil;
NewFilter := nil;
CoRegisterMessageFilter(NewFilter,OldFilter);
end;
end;
最好的解決方案FAR:我用IOleMessageFilter
實現這樣的:(記住這將停止,等待就行了,我以前有一個例外)
function IsWordDocumentOpen(FileName: string): Boolean;
var
OleMessageFilter: IOleMessageFilter;
WordApp: TWordApplication;
I: Integer;
begin
Result := False;
try
OleMessageFilter := IOleMessageFilter.Create;
OleMessageFilter.RegisterFilter;
WordApp := TWordApplication.Create(nil);
try
WordApp.Connect;
for I := 1 to WordApp.Documents.Count do
begin
if WordApp.Documents.Item(I).FullName = FileName then
begin
Result := True;
System.Break;
end;
end;
finally
OleMessageFilter.RevokeFilter;
FreeAndNil(WordApp);
FreeAndNil(OleMessageFilter);
end;
finally
//
end;
end;
我試過OnDocumentBeforeClose事件,但似乎無法啓動並運行。我寧願手動執行此檢查,所以如果您知道一種方法來檢查Word是否忙碌,那就太棒了! – Eric
我會去的,但首先(我應該問早些時候)它是什麼**完全**,你試圖做的「呼叫被拒絕被調用者」阻止? – MartynA
獲取'WordDocument'的'FullName','WordApp.Documents.Item(I).FullName'這是崩潰的地方。 – Eric