提交后,iStorage未解锁

2cmtqfgy  于 2022-09-21  发布在  其他
关注(0)|答案(2)|浏览(141)

当我运行下面的程序时,stgOpenStorage的结果值是STG_E_SHAREVIOLATION。我应该如何关闭iStorage才能将其解锁?

procedure TForm1.btnSaveClick(Sender: TObject);
var
  fileName : string;
  streamName : string;

  procedure storeTextIntoStorageStream( text_ : string );
  var
    documentStorage : IStorage;
    levelIStream : IStream;
    i, j : integer;
  begin
    if ( fileExists( fileName ) ) then
      deleteFile( fileName );
    stgCreateDocfile( @fileName[1], STGM_WRITE or STGM_SHARE_EXCLUSIVE or STGM_DIRECT or STGM_CREATE, 0, documentStorage );
    try
      documentStorage.CreateStream( @streamName[1], STGM_WRITE or STGM_SHARE_EXCLUSIVE or STGM_DIRECT, 0, 0, levelIStream );
      try
        i := length( text_ );
        levelIStream.write( @i, sizeOf( integer ), @j );
        levelIStream.write( @text_[1], i*sizeOf( char ), @j );
      finally
        levelIStream.Commit( 0 );
        levelIStream := NIL;
      end;
    finally
      documentStorage.Commit( 0 );
      documentStorage := NIL;
    end;
  end;

  function readTextFromStorageStream : string;
  var
    documentStorage : IStorage;
    levelIStream : IStream;
    i, j : integer;
  begin
    i := stgOpenStorage( @fileName[1], NIL, STGM_READ or STGM_SHARE_EXCLUSIVE or STGM_DIRECT, NIL, 0, documentStorage );
    try
      documentStorage.OpenStream( @streamName[1], NIL, STGM_READ or STGM_SHARE_EXCLUSIVE or STGM_DIRECT, 0, levelIStream );
      try
        levelIStream.read( @i, sizeOf( integer ), @j );
        setLength( result, i );
        levelIStream.read( @result[1], i*sizeOf( char ), @j );
      finally
        levelIStream := NIL;
      end;
    finally
      documentStorage := NIL;
    end;
  end;

begin
  fileName := 'c:temptest.stg';
  streamName := 'Stream-0';
  storeTextIntoStorageStream( memo1.Lines.DelimitedText );
  memo1.Lines.DelimitedText := readTextFromStorageStream;
end;

如何设置IStorage/IStream默认大小/大小步长?因为我的测试1.6K字节的内容存储在16K。

7gcisfzg

7gcisfzg1#

将引用设置为零是不够的。由操作系统内存管理器创建的IStorage/IStream示例,而不是分配给应用程序的示例。如果我们将app变量的值设置为nil,则只会自动调用app内存管理器。唯一可以释放分配给该示例的内存的是操作系统内存管理器。对示例的释放调用调用此内存管理器。

在设置为nil之前调用接口上的Release方法:

levelIStream.Release;
levelIStream := NIL

documentIStorage.Release;
documentIStorage := NIL
hgqdbh6s

hgqdbh6s2#

代码看起来没问题,所以我觉得这个问题是由于您使用STGM_SHARE_EXCLUSIVE造成的。当你试图打开文件时,文件正在使用中,所以我打赌是你的OS/AV让文件保持打开(即扫描其内容),而不是storeTextIntoStorageStream()中的界面,当readTextFromStorageStream()进入时,这些界面早就消失了。

他说:嗯,除了缺乏足够的错误处理外。以及接口变量的冗余nil‘ing。并且,可以考虑将字符串索引替换为PChar()强制转换。

readTextFromStorageStream()中,尝试用STGM_SHARE_DENY_WRITE替换STGM_SHARE_EXCLUSIVE(这对写入器有意义,但对读取器没有意义),并查看错误是否消失:

procedure TForm1.btnSaveClick(Sender: TObject);
var
  fileName : string;
  streamName : string;

  procedure storeTextIntoStorageStream( const text_ : string );
  var
    documentStorage : IStorage;
    levelIStream : IStream;
    i, j : integer;
  begin
    if ( FileExists( fileName ) ) then
      DeleteFile( fileName );
    OleCheck( StgCreateDocFile( PChar(fileName), STGM_WRITE or STGM_SHARE_EXCLUSIVE or STGM_DIRECT or STGM_CREATE, 0, documentStorage ));
    try
      OleCheck( documentStorage.CreateStream( PChar(streamName), STGM_WRITE or STGM_SHARE_EXCLUSIVE or STGM_DIRECT, 0, 0, levelIStream ) );
      try
        i := Length( text_ );
        OleCheck( levelIStream.Write( @i, SizeOf( i ), @j ) );
        if ( i > 0 ) then
          OleCheck( levelIStream.Write( PChar(text_), i * SizeOf( Char ), @j ) );
      finally
        levelIStream.Commit( 0 );
      end;
    finally
      documentStorage.Commit( 0 );
    end;
  end;

  function readTextFromStorageStream : string;
  var
    documentStorage : IStorage;
    levelIStream : IStream;
    i, j : integer;
  begin
    Result := '';
    OleCheck( StgOpenStorage( PChar(fileName), nil, STGM_READ or STGM_SHARE_DENY_WRITE or STGM_DIRECT, NIL, 0, documentStorage ) );
    OleCheck( documentStorage.OpenStream( PChar(streamName), nil, STGM_READ or STGM_SHARE_DENY_WRITE or STGM_DIRECT, 0, levelIStream ) );
    OleCheck( levelIStream.Read( @i, SizeOf( i ), @j ) );
    if ( i > 0 ) then
    begin
      SetLength( Result, i );
      OleCheck( levelIStream.Read( PChar(Result), i * SizeOf( Char ), @j ) );
    end;
  end;

begin
  fileName := 'c:temptest.stg';
  streamName := 'Stream-0';
  storeTextIntoStorageStream( Memo1.Lines.DelimitedText );
  Memo1.Lines.DelimitedText := readTextFromStorageStream;
end;

相关问题