当从TOleContainer提取文档的数据时,DoVerb(ovInplaceActivate)崩溃,出现各种错误消息

一个客户在使用OLE处理Office文档时,会遇到与我们的软件有些奇怪的行为。 当一些派生的TOleContainer类的实例尝试通过DoVerb(ovInPlaceActivate)调用激活OLE对象时,代码崩溃。

有各种错误消息,包括:

  • (0x80030002) %1找不到。
  • (0x80030005) 访问被拒绝。
  • (0x800706BE) 远程过程调用失败。

看我的代码:

 function TfrmOleOffice.SaveToStream: TStream; var LOleContainerState: TObjectState; LModified: Boolean; begin Result := TMemoryStream.Create; if IsEmpty and OleOfficeAvailable then exit; if OleOfficeAvailable then begin LOleContainerStateBefore := FOleContainer.State; LModified := FOleContainer.Modified; // 'FOleContainer.Modified' could be changed by 'FOleContainer.Close' FOleContainer.Close; FValue.Position := 0; if LModified then // otherwise, take stored 'FValue' (see below) FOleContainer.SaveToStream(FValue); if LOleContainerStateBefore in [osUIActive] then ActivateContainer; // reactivate the container end; Result.CopyFrom(FValue, 0); end; //--------------------------------------------------- procedure THKSOleContainer.SaveToStream(Stream: TStream); var TempLockBytes: ILockBytes; TempStorage: IStorage; DataHandle: HGlobal; Buffer: Pointer; Header: TStreamHeader; R: TRect; LFileName: String; LFileStream: TFileStream; begin CheckObject; if FModSinceSave then SaveObject; // the following block might be obsolete if FCopyOnSave then begin OleCheck(CreateILockBytesOnHGlobal(0, True, TempLockBytes)); OleCheck(StgCreateDocfileOnILockBytes(TempLockBytes, STGM_READWRITE or STGM_SHARE_EXCLUSIVE or STGM_CREATE, 0, TempStorage)); OleCheck(FStorage.CopyTo(0, nil, nil, TempStorage)); OleCheck(TempStorage.Commit(STGC_DEFAULT)); OleCheck(GetHGlobalFromILockBytes(TempLockBytes, DataHandle)); end else OleCheck(GetHGlobalFromILockBytes(FLockBytes, DataHandle)); // save the document as a temporary file and read it into a TFileStream LFileName := IncludeTrailingPathDelimiter(GetMainTempFolder) + TPath.GetGUIDFileName + ExtractFileExt(FOriginalFileName); // get a unique temporary filename SaveOleObject(LFileName); try LFileStream := TFileStream.Create(LFileName, fmOpenRead or fmShareDenyNone); try Stream.CopyFrom(LFileStream, 0); finally FreeAndNil(LFileStream); end; finally SysUtils.DeleteFile(LFileName); end; FModified := False; end; procedure THKSOleContainer.SaveOleObject(AFileName: String = ''); var LActivatedBefore: Boolean; begin LActivatedBefore := GetIsActivated; DoVerb(ovInPlaceActivate, False); // <-- this call crashes with various error messages on several systems of a client ForceDirectories(ExtractFilePath(AFileName)); OleObject.SaveAs(AFileName); if not LActivatedBefore then Close(OLECLOSE_NOSAVE, False); end; 

代码应该做什么?THKSOleContainer重新实现SaveToStream而不是保存一些内部的OLEstream,只有OLE容器可以正常打开它将容器的内容保存到一些临时文件中,并将其读回到TFileStream 。 结果应该是本地文档作为stream。 TfrmOleOffice是显示THKSOleContainer实例的THKSOleContainer

什么情况下正确运行,什么不是? 首先,在我的电脑上,一切运行良好。 我也不知道有任何其他客户遇到这个问题。 但是,在客户的计算机上,当文档被编辑并且在窗体的确认中调用SaveToStream时,它会崩溃。 如果文档已被加载但未被激活,则不会崩溃。 实际上, SaveToStream被调用,但是成功了。

我使用Microsoft Excel 2010 – 家庭和企业 ,而客户安装了Microsoft Excel 2010 – Professional Plus 。 我的系统和他的系统是Windows 7 x64

任何想法可能是错的?


“常问问题”

GSerg:他们有一个杀毒软件,你不?

  • 我们通过暂时停用防病毒来检查,但没有效果。 我们甚至重新启动计算机(并确保防病毒仍然被禁用)。

似乎是,调用FOleContainer.Close函数TfrmOleOffice.SaveToStream导致保存上的问题。 在我提供了一个版本, 这个调用被注释掉后,客户没有再保存任何错误

我们还发现了另一个麻烦制造者Microsoft Dynamics NAV的Excel COM加载项。 在停用之后,加载时也不会出现更多的错误。 Excel有时会在OleCreateFromFile调用上冻结。 现在我们将尝试更改其加载行为,以便只在需要时加载它。 这可能是,这也导致了一些节省的问题。