通过OleCreateFromFile在C#中调用OLE对pdf文件无效
本文关键字:pdf 文件 无效 OLE 调用 OleCreateFromFile 通过 | 更新日期: 2023-09-27 18:23:47
我正在尝试将pdf文件嵌入到OPEN XML文档中。这需要创建*.bin文件。我不想使用自动化。
我从这个问题中得到的方法适用于我测试的所有文件类型,除了*.pdf.
由于某些原因,pdf文件总是从OleCreateFromFile(..)获得0x80004005的结果,并且pOle为NULL。
我是调用和OLE领域的新手。这种方法不适用于PDF的原因是什么?(我有最新的Adobe Reader,Win8,调用到Ole32.dll,项目构建目标是x86,我测试调用CoUninitialize()和CoInitializeEx((System.IntPtr)null,Ole32.CoInit.ApartmentThreaded),我可以在MSWORD应用程序中嵌入pdf文件)。
这是我为它使用的一个函数:
public static string ExportOleFile(string _inputFileName, string oleOutputFileName, string emfOutputFileName)
{
StringBuilder resultString = new StringBuilder();
string newInput = MultibyteToUnicodeNETOnly(_inputFileName, 1252);
Microsoft.VisualStudio.OLE.Interop.IStorage storage;
var result = OLE32.StgCreateStorageEx(oleOutputFileName,
Convert.ToInt32(OLE32.STGM.STGM_READWRITE | OLE32.STGM.STGM_SHARE_EXCLUSIVE | OLE32.STGM.STGM_CREATE | OLE32.STGM.STGM_TRANSACTED),
Convert.ToInt32(OLE32.STGFMT.STGFMT_DOCFILE),
0,
IntPtr.Zero,
IntPtr.Zero,
ref OLE32.IID_IStorage,
out storage
);//vytvoří bin
resultString.AppendLine("CreateStorageEx Result: " + result.ToString());
var CLSID_NULL = Guid.Empty;
Microsoft.VisualStudio.OLE.Interop.FORMATETC f = new FORMATETC();
Microsoft.VisualStudio.OLE.Interop.IOleObject pOle;
result = OLE32.OleCreateFromFile(
ref CLSID_NULL,
newInput,
ref OLE32.IID_IOleObject,
(uint)Microsoft.VisualStudio.OLE.Interop.OLERENDER.OLERENDER_NONE,
ref f,
null,
storage,
out pOle
);
resultString.AppendLine("OleCreateFromFile Result: " + result.ToString());
try
{
result = OLE32.OleRun(pOle);
}
catch (Exception ex)
{
resultString.AppendLine(ex.ToString());
return resultString.ToString();
}
resultString.AppendLine("OleRun Result: " + result.ToString());
try
{
IntPtr unknownFromOle = Marshal.GetIUnknownForObject(pOle);
IntPtr unknownForDataObj;
Marshal.QueryInterface(unknownFromOle, ref OLE32.IID_IDataObject, out unknownForDataObj);
var pdo = Marshal.GetObjectForIUnknown(unknownForDataObj) as System.Runtime.InteropServices.ComTypes.IDataObject;
var fetc = new System.Runtime.InteropServices.ComTypes.FORMATETC();
fetc.cfFormat = (short)OLE32.CLIPFORMAT.CF_ENHMETAFILE;
fetc.dwAspect = System.Runtime.InteropServices.ComTypes.DVASPECT.DVASPECT_CONTENT;
fetc.lindex = -1;
fetc.ptd = IntPtr.Zero;
fetc.tymed = System.Runtime.InteropServices.ComTypes.TYMED.TYMED_ENHMF;
var stgm = new System.Runtime.InteropServices.ComTypes.STGMEDIUM();
stgm.unionmember = IntPtr.Zero;
stgm.tymed = System.Runtime.InteropServices.ComTypes.TYMED.TYMED_ENHMF;
pdo.GetData(ref fetc, out stgm);
var hemf = GDI32.CopyEnhMetaFile(stgm.unionmember, emfOutputFileName);
storage.Commit((int)OLE32.STGC.DEFAULT);
pOle.Close(0);
GDI32.DeleteEnhMetaFile(stgm.unionmember);
GDI32.DeleteEnhMetaFile(hemf);
}
catch (Exception ex)
{
resultString.AppendLine(ex.ToString());
return resultString.ToString();
}
return resultString.ToString();
}
实际上,要在OpenXML中嵌入文件,必须使用好的旧OLE函数。没有其他办法,因为你需要得到两块:
- 要嵌入的文件
- 显示文件内容的图片,通常是第一页的屏幕截图
我确实写了一篇关于这方面的博客:使用openxml将pdf嵌入powerpoint。这并不完全是您的要求,但它的工作原理完全相同。
当涉及到嵌入时,pdfs有两个问题:
- 嵌入的pdf文档与原始pdf文件具有不同的内容。对于我所知道的所有其他OLE格式(excel、word、powerpoint…),情况并非如此。你可以只使用硬盘上的文件,对于pdf你不能
- 你需要拍下第一页的照片。你可以使用pdfium或类似的工具——有很多工具可以渲染pdf,但adobe阅读器是免费的,可以100%完成任务