Я пытаюсь встроить PDF-файлы в открытый документ XML. Это требует создания * .bin файлов. Я не хочу использовать автоматизацию.
Подход, который я взял из этот вопрос работает для всех типов файлов, которые я тестировал, кроме * .pdf.
По некоторым причинам pdf-файлы всегда получают результат из OleCreateFromFile (..), равный 0x80004005, а pOle равен NULL.
Я новичок в области вызова и OLE. Что может быть причиной того, что этот подход не работает для PDF?
(У меня есть новейшая версия Adobe Reader, Win8, которая вызывается в Ole32.dll, цель сборки проектов — x86, и я тестирую для вызова CoUninitialize () и CoInitializeEx ((System.IntPtr) null, OLE32.CoInit.ApartmentThreaded), я могу встроить PDF-файлы в приложении MSWORD).
Вот функция, которую я использую для этого:
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-функциями. Другого пути нет, так как вам нужно получить две части:
Я написал запись в блоге об этом: Вставить PDF в PowerPoint с использованием OpenXML. Это не совсем ваше требование, но оно работает идентично.
Когда дело доходит до встраивания, у pdf есть две проблемы:
Других решений пока нет …