One customer experiences some strange behaviour with our software when working with Office documents via OLE. The code crashes when an instance of some derived TOleContainer
class tries to activate the OLE object via DoVerb(ovInPlaceActivate)
call.
There are various error messages, including:
See my code:
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;
What is the code supposed to do? Class THKSOleContainer
reimplements SaveToStream
but instead of saving some internal OLE stream that only the OLE container can open properly it saves the container's content into some temporary file and reads it back into a TFileStream
. Result should be the native document as a stream.
TfrmOleOffice
is a form on which the instance of THKSOleContainer
is displayed.
What cases run properly, what do not? First of all, on my computer, everything runs fine. I don't know of any other customer experiencing this problem neither.
But on that customer's computers it crashes when a document has been edited and SaveToStream
is called on form's confirmation. If the document has been loaded but not activated, it does not crash. Actually, SaveToStream
is called then, too, but it succeeds.
I use Microsoft Excel 2010 - Home and Business, whereas the customer has Microsoft Excel 2010 - Professional Plus installed. My system and his system are Windows 7 x64.
Any ideas on what could be wrong?
GSerg: They have an antivirus and you don't?
Seems to be, that call of FOleContainer.Close
in function TfrmOleOffice.SaveToStream
caused the problems on saving. The customer got no errors on saving anymore after I provided a version in which this call was commented out.
We also detected another trouble-maker: an Excel COM-add-in for Microsoft Dynamics NAV. After it has been deactivated, there occured no more errors on loading, neither. Excel froze there on OleCreateFromFile
call sometimes. We'll now try to change its load behaviour, so that it is only loaded if needed. It might be, that this caused some of the problems on saving, too.
User contributions licensed under CC BY-SA 3.0