我正在尝试使用此处描述的 OLE 技术将 PDF 文件嵌入 Word 文档: https ://docs.microsoft.com/en-us/archive/blogs/brian_jones/embedding-any-file-type-like- pdf-in-an-open-xml 文件
我试图实现 C# 中提供的 C++ 代码,以便整个项目都在一个地方,并且几乎就在那里,除了一个障碍。当我尝试将生成的 OLE 对象二进制数据输入 Word 文档时,我得到一个 IOException。
IOException:该进程无法访问文件“C:\Wherever\Whatever.pdf.bin”,因为它正被另一个进程使用。
有一个文件句柄打开 .bin 文件(下面的“oleOutputFileName”),我不知道如何摆脱它。我对 COM 知之甚少——我在这里讨论它——而且我不知道文件句柄在哪里或如何释放它。
这是我的 C# 化代码的样子。我错过了什么?
public void ExportOleFile(string oleOutputFileName, string emfOutputFileName)
{
OLE32.IStorage storage;
var result = OLE32.StgCreateStorageEx(
oleOutputFileName,
OLE32.STGM.STGM_READWRITE | OLE32.STGM.STGM_SHARE_EXCLUSIVE | OLE32.STGM.STGM_CREATE | OLE32.STGM.STGM_TRANSACTED,
OLE32.STGFMT.STGFMT_DOCFILE,
0,
IntPtr.Zero,
IntPtr.Zero,
ref OLE32.IID_IStorage,
out storage
);
var CLSID_NULL = Guid.Empty;
OLE32.IOleObject pOle;
result = OLE32.OleCreateFromFile(
ref CLSID_NULL,
_inputFileName,
ref OLE32.IID_IOleObject,
OLE32.OLERENDER.OLERENDER_NONE,
IntPtr.Zero,
null,
storage,
out pOle
);
result = OLE32.OleRun(pOle);
IntPtr unknownFromOle = Marshal.GetIUnknownForObject(pOle);
IntPtr unknownForDataObj;
Marshal.QueryInterface(unknownFromOle, ref OLE32.IID_IDataObject, out unknownForDataObj);
var pdo = Marshal.GetObjectForIUnknown(unknownForDataObj) as IDataObject;
var fetc = new FORMATETC();
fetc.cfFormat = (short)OLE32.CLIPFORMAT.CF_ENHMETAFILE;
fetc.dwAspect = DVASPECT.DVASPECT_CONTENT;
fetc.lindex = -1;
fetc.ptd = IntPtr.Zero;
fetc.tymed = TYMED.TYMED_ENHMF;
var stgm = new STGMEDIUM();
stgm.unionmember = IntPtr.Zero;
stgm.tymed = TYMED.TYMED_ENHMF;
pdo.GetData(ref fetc, out stgm);
var hemf = GDI32.CopyEnhMetaFile(stgm.unionmember, emfOutputFileName);
storage.Commit((int)OLE32.STGC.STGC_DEFAULT);
pOle.Close(0);
GDI32.DeleteEnhMetaFile(stgm.unionmember);
GDI32.DeleteEnhMetaFile(hemf);
}
更新 1:澄清了我所说的“.bin 文件”是指哪个文件。
更新 2:我没有使用“使用”块,因为我想要摆脱的东西不是一次性的。(老实说,我不确定我需要释放什么来删除文件句柄,COM 对我来说是一门外语。)