【问题标题】:Invalid FORMATETC structure when calling CreateObjectFromFile调用 CreateObjectFromFile 时 FORMATETC 结构无效
【发布时间】:2012-11-29 16:14:54
【问题描述】:

我正在使用 Delphi 7 尝试将 Word 文档加载到 OLEContainer 中。该程序在终端服务 (Windows 2003) 环境中运行。

以下代码会为某些用户生成错误:

procedure TForm1.Button1Click(Sender: TObject);
begin
  OleContainer1.CreateObjectFromFile('c:\tmp\test.doc', false);
end;

这是一个简单的应用程序,带有一个 OLEContainer 和一个窗体上的按钮。 c:\tmp\test.doc 是 Word 2003 文档。

对于某些用户,此代码会生成错误

FORMATETC 结构无效。

对于其他人则不然。所有用户都在同一台终端服务器上运行,因此运行同一程序访问同一 Word 文档。此外,所有用户都是使用脚本创建的,因此它们具有完全相同的设置,当然除了用户名等。

我已尝试将所有用户设置为管理员,但这并没有改变行为。

有人知道问题可能是什么吗?

【问题讨论】:

  • 可能是并发问题。您的所有用户都必须使用同一个文档,或者您可以为每个用户提供一份副本吗?
  • 错误信息包含其他信息(可能是错误号)还是只是无效的FORMATETC结构
  • 您使用的是哪个 Delphi 版本?我在 XE3 中的 OleCreateFromFile 调用只是将 nil (null) 传递给 lpFormatEtc 参数,并将 OLERENDER_DRAW 传递给 renderopt。在我看来,这不是失败的重点。你可以重试吗?或者为失败生成一个 StackTrace 以查看它发生在哪一点?
  • 不是并发问题。我尝试登录,首先是用户 A,然后是用户 B。适用于 A,而不是 B。可能更多的是错误消息,尚未检查。我无法重现错误,也无法访问发生错误的环境。它是用 delphi 7 编写的。

标签: windows delphi ms-word ole


【解决方案1】:

我相信 Word 自动化支持 IPersistFile,这应该提供另一种加载文件的方法。 See more here.

【讨论】:

    【解决方案2】:

    经过一些测试,我发现 TOleContainer.LoadFromStream 方法始终有效。问题是这个方法需要一个 OLE 流,而不是一个包含 word 文档的流。我对 OLE 流的格式进行了逆向工程,并通过编写页眉、word 文档和页脚手动创建了一个。看起来,页脚由偶数 256 字节的 ASCII-0 组成。

    以下是创建OLE-stream的代码:

    function OLEStreamFromDoc(const inDocFileName : String) : TMemoryStream;
    var
      aFileStream : TMemoryStream;
      aPadding    : Array[1..256] of byte;
      aHeader     : Array[1..12] of byte;
      aSize       : int64;
      i           : integer;
    begin
      for i := low(aHeader) to High(aHeader) do
        aHeader[i] := 0;
    
      for i := low(aPadding) to High(aPadding) do
        aPadding[i] := 0;
    
      Result := TMemoryStream.Create;
      aFileStream := TMemoryStream.Create;
      try
        aFileStream.LoadFromFile(inDocFileName);
        aFileStream.Seek(0,0);
        aSize := aFileStream.Size + SizeOf(aPadding);
    
        aHeader[1] := Ord('B');
        aHeader[2] := Ord('D');
        aHeader[3] := Ord('O');
        aHeader[4] := Ord('C');
        aHeader[5] := 1;
        aHeader[9]  := aSize and 255;
        aHeader[10] := (aSize shr 8) and 255;
        aHeader[11] := (aSize shr 16) and 255;
        aHeader[12] := (aSize shr 24) and 255;
        Result.Write(aHeader, SizeOf(aHeader));
        aFileStream.SaveToStream(Result);
        Result.Write(aPadding, sizeof(aPadding));
        Result.Seek(0,0);
      finally
        aFileStream.Free;
      end;
    end;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-15
      • 2017-04-20
      • 1970-01-01
      • 1970-01-01
      • 2013-06-09
      • 1970-01-01
      • 2011-11-13
      • 2021-11-24
      相关资源
      最近更新 更多