2013-02-15 30 views
1

我想利用C#在這個崗位轉換的代碼在: Releasing an OLE IStorage file handle in C#調用OLE使用OleCreateFromFile返回0x800004016使用的需要DDE窗口OLE1服務C#是禁用

在這篇文章中,OP看起來創建了一個自定義類OLE32,它使用pinvoke來聲明IStorage和IOleObject接口以及不同的方法。我做了同樣的事情。我的問題是,當我嘗試調用OLE32.OleCreateFromFile時,我得到的返回值是-2147467242。

此返回值轉換爲0x80004016十六進制,其中,根據一切我能找到,是以下錯誤:

使用的需要DDE窗口OLE1服務被禁用

的方法應該吐出的IOleObject,而是pOle是空的,接下來的方法失敗。

有沒有人知道我爲什麼會出現這個錯誤,以及如何修復它?下面我已經包含了完整的代碼以及我的OLE32類。

的方法:

public static string ExportOleFile(string _inputFileName, string oleOutputFileName, string emfOutputFileName) 
    { 
     StringBuilder resultString = new StringBuilder(); 

     string newInput = MultibyteToUnicodeNETOnly(_inputFileName, 1252); 


     OLE32.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 
     ); 

     resultString.AppendLine("CreateStorageEx Result: " + result.ToString()); 

     var CLSID_NULL = Guid.Empty; 

     OLE32.IOleObject pOle; 
     result = OLE32.OleCreateFromFile(
      ref CLSID_NULL, 
      _inputFileName, 
      ref OLE32.IID_IOleObject, 
      (uint)OLE32.OLERENDER.OLERENDER_NONE, 
      IntPtr.Zero, 
      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(); 

    } 

OLE32.cs:

public static class OLE32 
    { 
     [StructLayout(LayoutKind.Sequential)] 
     public struct STGOPTIONS 
     { 
      ushort usVersion; 
      ushort reserved; 
      ulong ulSectorSize; 
      [MarshalAsAttribute(UnmanagedType.LPWStr)] 
      public string pwcsTemplateFile; 
     }; 

     public enum OLERENDER 
     { 
      OLERENDER_NONE = 0, 
      OLERENDER_DRAW = 1, 
      OLERENDER_FORMAT = 2, 
      OLERENDER_ASIS = 3 
     } 

     internal enum CLIPFORMAT : int 
     { 
      CF_TEXT = 1, 
      CF_BITMAP = 2, 
      CF_METAFILEPICT = 3, 
      CF_SYLK = 4, 
      CF_DIF = 5, 
      CF_TIFF = 6, 
      CF_OEMTEXT = 7, 
      CF_DIB = 8, 
      CF_PALETTE = 9, 
      CF_PENDATA = 10, 
      CF_RIFF = 11, 
      CF_WAVE = 12, 
      CF_UNICODETEXT = 13, 
      CF_ENHMETAFILE = 14, 
      CF_HDROP = 15, 
      CF_LOCALE = 16, 
      CF_MAX = 17, 
      CF_OWNERDISPLAY = 0x80, 
      CF_DSPTEXT = 0x81, 
      CF_DSPBITMAP = 0x82, 
      CF_DSPMETAFILEPICT = 0x83, 
      CF_DSPENHMETAFILE = 0x8E, 
     } 

     internal enum STGFMT : int 
     { 
      STGFMT_STORAGE = 0, 
      STGFMT_FILE = 3, 
      STGFMT_ANY = 4, 
      STGFMT_DOCFILE = 5 
     } 

     [Flags] 
     internal enum STGM : int 
     { 
      STGM_READ = 0x0, 
      STGM_WRITE = 0x1, 
      STGM_READWRITE = 0x2, 
      STGM_SHARE_DENY_NONE = 0x40, 
      STGM_SHARE_DENY_READ = 0x30, 
      STGM_SHARE_DENY_WRITE = 0x20, 
      STGM_SHARE_EXCLUSIVE = 0x10, 
      STGM_PRIORITY = 0x40000, 
      STGM_CREATE = 0x1000, 
      STGM_CONVERT = 0x20000, 
      STGM_FAILIFTHERE = 0x0, 
      STGM_DIRECT = 0x0, 
      STGM_TRANSACTED = 0x10000, 
      STGM_NOSCRATCH = 0x100000, 
      STGM_NOSNAPSHOT = 0x200000, 
      STGM_SIMPLE = 0x8000000, 
      STGM_DIRECT_SWMR = 0x400000, 
      STGM_DELETEONRELEASE = 0x4000000 
     } 

     public enum STGC 
     { 
      DEFAULT = 0, 
      OVERWRITE = 1, 
      ONLYIFCURRENT = 2, 
      DANGEROUSLYCOMMITMERELYTODISKCACHE = 4, 
      CONSOLIDATE = 8 
     } 


     public static Guid IID_IDataObject = new Guid("{0000010e-0000-0000-C000-000000000046}"); 

     public static Guid IID_IOleObject = new Guid("{00000112-0000-0000-C000-000000000046}"); 

     public static Guid IID_IStorage = new Guid("0000000B-0000-0000-C000-000000000046"); 



     [DllImport("ole32.dll")] 
     public static extern int StgCreateStorageEx([MarshalAs(UnmanagedType.LPWStr)] string 
      pwcsName, int grfMode, int stgfmt, int grfAttrs, IntPtr pStgOptions, IntPtr reserved2, ref Guid riid, 
      out IStorage ppObjectOpen); 


     [DllImport("ole32.dll")] 
     public static extern int OleCreateFromFile([In] ref Guid rclsid, 
      [MarshalAs(UnmanagedType.LPWStr)] string lpszFileName, ref Guid riid, 
      uint renderopt, IntPtr pFormatEtc, IOleClientSite pClientSite, 
      IStorage pStg, out IOleObject ppvObj); 

     [DllImport("ole32.dll")] 
     public static extern int OleRun([MarshalAs(UnmanagedType.IUnknown)] object pUnknown); 


     [ComImport] 
     [Guid("00000118-0000-0000-C000-000000000046")] 
     [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
     public interface IOleClientSite 
     { 
      void SaveObject(); 
      void GetMoniker(uint dwAssign, uint dwWhichMoniker, ref object ppmk); 
      void GetContainer(ref object ppContainer); 
      void ShowObject(); 
      void OnShowWindow(bool fShow); 
      void RequestNewObjectLayout(); 
     } 




     [ComImport] 
     [Guid("0000000b-0000-0000-C000-000000000046")] 
     [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
     public interface IStorage 
     { 
      void CreateStream(
       /* [string][in] */ string pwcsName, 
       /* [in] */ uint grfMode, 
       /* [in] */ uint reserved1, 
       /* [in] */ uint reserved2, 
       /* [out] */ out IStream ppstm); 

      void OpenStream(
       /* [string][in] */ string pwcsName, 
       /* [unique][in] */ IntPtr reserved1, 
       /* [in] */ uint grfMode, 
       /* [in] */ uint reserved2, 
       /* [out] */ out IStream ppstm); 

      void CreateStorage(
       /* [string][in] */ string pwcsName, 
       /* [in] */ uint grfMode, 
       /* [in] */ uint reserved1, 
       /* [in] */ uint reserved2, 
       /* [out] */ out IStorage ppstg); 

      void OpenStorage(
       /* [string][unique][in] */ string pwcsName, 
       /* [unique][in] */ IStorage pstgPriority, 
       /* [in] */ uint grfMode, 
       /* [unique][in] */ IntPtr snbExclude, 
       /* [in] */ uint reserved, 
       /* [out] */ out IStorage ppstg); 

      void CopyTo(
       /* [in] */ uint ciidExclude, 
       /* [size_is][unique][in] */ Guid rgiidExclude, // should this be an array? 
       /* [unique][in] */ IntPtr snbExclude, 
       /* [unique][in] */ IStorage pstgDest); 

      void MoveElementTo(
       /* [string][in] */ string pwcsName, 
       /* [unique][in] */ IStorage pstgDest, 
       /* [string][in] */ string pwcsNewName, 
       /* [in] */ uint grfFlags); 

      void Commit(
       /* [in] */ uint grfCommitFlags); 

      void Revert(); 

      void EnumElements(
       /* [in] */ uint reserved1, 
       /* [size_is][unique][in] */ IntPtr reserved2, 
       /* [in] */ uint reserved3, 
       /* [out] */ out IEnumSTATSTG ppenum); 

      void DestroyElement(
       /* [string][in] */ string pwcsName); 

      void RenameElement(
       /* [string][in] */ string pwcsOldName, 
       /* [string][in] */ string pwcsNewName); 

      void SetElementTimes(
       /* [string][unique][in] */ string pwcsName, 
       /* [unique][in] */ System.Runtime.InteropServices.FILETIME pctime, 
       /* [unique][in] */ System.Runtime.InteropServices.FILETIME patime, 
       /* [unique][in] */ System.Runtime.InteropServices.FILETIME pmtime); 

      void SetClass(
       /* [in] */ Guid clsid); 

      void SetStateBits(
       /* [in] */ uint grfStateBits, 
       /* [in] */ uint grfMask); 

      void Stat(
       /* [out] */ out System.Runtime.InteropServices.STATSTG pstatstg, 
       /* [in] */ uint grfStatFlag); 

     } 

     [ComImport] 
     [Guid("00000112-0000-0000-C000-000000000046")] 
     [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
     public interface IOleObject 
     { 
      void SetClientSite(IOleClientSite pClientSite); 
      void GetClientSite(ref IOleClientSite ppClientSite); 
      void SetHostNames(object szContainerApp, object szContainerObj); 
      void Close(uint dwSaveOption); 
      void SetMoniker(uint dwWhichMoniker, object pmk); 
      void GetMoniker(uint dwAssign, uint dwWhichMoniker, object ppmk); 
      void InitFromData(IDataObject pDataObject, bool fCreation, uint dwReserved); 
      void GetClipboardData(uint dwReserved, ref IDataObject ppDataObject); 
      void DoVerb(uint iVerb, uint lpmsg, object pActiveSite, uint lindex, uint hwndParent, uint lprcPosRect); 
      void EnumVerbs(ref object ppEnumOleVerb); 
      void Update(); 
      void IsUpToDate(); 
      void GetUserClassID(uint pClsid); 
      void GetUserType(uint dwFormOfType, uint pszUserType); 
      void SetExtent(uint dwDrawAspect, uint psizel); 
      void GetExtent(uint dwDrawAspect, uint psizel); 
      void Advise(object pAdvSink, uint pdwConnection); 
      void Unadvise(uint dwConnection); 
      void EnumAdvise(ref object ppenumAdvise); 
      void GetMiscStatus(uint dwAspect, uint pdwStatus); 
      void SetColorScheme(object pLogpal); 
     }; 

     [ComImport] 
     [Guid("0000000d-0000-0000-C000-000000000046")] 
     [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
     public interface IEnumSTATSTG 
     { 
      // The user needs to allocate an STATSTG array whose size is celt. 
      [PreserveSig] 
      uint 
      Next(
      uint celt, 
      [MarshalAs(UnmanagedType.LPArray), Out] 
    System.Runtime.InteropServices.STATSTG[] rgelt, 
      out uint pceltFetched 
      ); 

      void Skip(uint celt); 

      void Reset(); 

      [return: MarshalAs(UnmanagedType.Interface)] 
      IEnumSTATSTG Clone(); 
     } 


     [ComImport, Guid("0000000c-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
     public interface IStream 
     { 
      void Read([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, uint cb, out uint pcbRead); 
      void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, uint cb, out uint pcbWritten); 
      void Seek(long dlibMove, uint dwOrigin, out long plibNewPosition); 
      void SetSize(long libNewSize); 
      void CopyTo(IStream pstm, long cb, out long pcbRead, out long pcbWritten); 
      void Commit(uint grfCommitFlags); 
      void Revert(); 
      void LockRegion(long libOffset, long cb, uint dwLockType); 
      void UnlockRegion(long libOffset, long cb, uint dwLockType); 
      void Stat(out System.Runtime.InteropServices.STATSTG pstatstg, uint grfStatFlag); 
      void Clone(out IStream ppstm); 
     } 


     [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0000010E-0000-0000-C000-000000000046")] 
     public interface IDataObject 
     { 
      void GetData([In] ref FORMATETC format, out STGMEDIUM medium); 
      void GetDataHere([In] ref FORMATETC format, ref STGMEDIUM medium); 
      [PreserveSig] 
      int QueryGetData([In] ref FORMATETC format); 
      [PreserveSig] 
      int GetCanonicalFormatEtc([In] ref FORMATETC formatIn, out FORMATETC formatOut); 
      void SetData([In] ref FORMATETC formatIn, [In] ref STGMEDIUM medium, [MarshalAs(UnmanagedType.Bool)] bool release); 
      IEnumFORMATETC EnumFormatEtc(DATADIR direction); 
      [PreserveSig] 
      int DAdvise([In] ref FORMATETC pFormatetc, ADVF advf, IAdviseSink adviseSink, out int connection); 
      void DUnadvise(int connection); 
      [PreserveSig] 
      int EnumDAdvise(out IEnumSTATDATA enumAdvise); 
     } 











    } 
+0

請問您可以添加進口或整個代碼的地方?謝謝! – 4F2E4A2E 2015-07-27 05:41:50

回答

2

沒有什麼明顯的錯誤的代碼是,添加缺少的聲明後,我可以運行它高達pdo.GetData()調用在.NET 3.5和4.5上。我沒有正確的輸入文件來繼續。

0x80004016錯誤代碼只有一個體面的解釋。如果運行此代碼的線程使用COINIT_DISABLE_OLE1DDE選項調用OleInitializeEx(),則會發生這種情況。 .NET不這樣做。因此,我必須猜測該線程是由本機代碼開始的,並轉換爲此託管代碼。它適合於那種代碼,這通常會用C++編寫。

您需要搜索OleInitializeEx調用並更改它。如果這很困難,那麼您可以考慮啓動自己的線程來運行此代碼,以免它受調用本機線程的錯誤狀態影響。

+0

謝謝你的迴應漢斯! 我會試着通過解釋一些關於環境的猜測來解開你的猜測: 我打算將其作爲Web服務運行。它在.NET 3.5上。它以託管代碼的形式開始並貫穿始終。在IIS的某個地方,我的Web服務配置或服務器上的某個設置有可能導致設置COINIT_DISABLE_OLE1DDE選項? – 2013-02-18 01:26:06

+0

你的回答讓我走上了正確的道路。我開始了一個新的線程,並立即調用CoUninitialize();.之後,我調用CoInitializeEx((System.IntPtr)null,OLE32.CoInit.ApartmentThreaded);這一切都很完美。 – 2013-02-18 05:21:59

+0

根據代碼,解決此問題的另一個方法是在Main入口點函數中添加STAThread屬性。 – 2017-04-11 10:46:14