通过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();
        }

通过OleCreateFromFile在C#中调用OLE对pdf文件无效

实际上,要在OpenXML中嵌入文件,必须使用好的旧OLE函数。没有其他办法,因为你需要得到两块:

  • 要嵌入的文件
  • 显示文件内容的图片,通常是第一页的屏幕截图

我确实写了一篇关于这方面的博客:使用openxml将pdf嵌入powerpoint。这并不完全是您的要求,但它的工作原理完全相同。

当涉及到嵌入时,pdfs有两个问题:

  • 嵌入的pdf文档与原始pdf文件具有不同的内容。对于我所知道的所有其他OLE格式(excel、word、powerpoint…),情况并非如此。你可以只使用硬盘上的文件,对于pdf你不能
  • 你需要拍下第一页的照片。你可以使用pdfium或类似的工具——有很多工具可以渲染pdf,但adobe阅读器是免费的,可以100%完成任务