2009-08-11 6 views
0

Ich habe seit fast einer Woche versucht, herauszufinden, wie StgCreateStorageEx in C# aufrufen, und alles, was ich zeigen muss, ist eine AccessViolationException und Kopfschmerzen.StgCreateStorageEx in C# gibt AccessViolationException

Ich bin nicht einmal sicher, wie ich die Funktion erklären sollte. Ich habe eine Zillion Websites gesehen, die es auf unzählige Arten erklären. Aber das ist, was ich derzeit haben:

[DllImport("ole32.dll")] 
     public unsafe static extern UInt32 StgCreateStorageEx([MarshalAs(UnmanagedType.LPWStr)] string 
      pwcsName, long grfMode, STGFMT stgfmt, uint grfAttrs, IntPtr pStgOptions, IntPtr reserved2, [In] Guid riid, void** ppObjectOpen) 

Ich habe gesehen, Websites, sagen Sie mir, ich brauche MarshalAs auf dem letzten Parameter zu verwenden, und ich habe versucht mit IUnknown, Schnittstelle, LPStruct, und einige andere. Das einzige, was mich erwischte, war der Marshaller, der sich über Datentypen klagte. Ich habe das Gefühl, dass das wahrscheinlich verwandt ist, aber da es mir nur sagt was es nicht will, habe ich keine Ahnung was es will.

An wie ich die Funktion rufe: Dies begann viel einfacher. Aber nachdem die Speicherverletzungen immer begann ich zu lesen und kam schließlich zu dem Schluss, dass der einzige Weg, der GC sicher sein nicht mir Einschrauben über war die Erinnerung selbst zu verwalten, so haben Sie diese Verwirrung:

IntPtr ptr2ptr2ptr = Marshal.AllocHGlobal(IntPtr.Size); 
IntPtr ptr2ptr = Marshal.AllocHGlobal(IntPtr.Size); 
IntPtr ptr2data = Marshal.AllocHGlobal(104857600); // pretty sure that's enough for whatever StgCreateStorageEx wants to do. 
Marshal.WriteIntPtr(ptr2ptr,ptr2data); 
Marshal.WriteIntPtr(ptr2ptr2ptr, ptr2ptr); 
Guid IID_IStorage = new Guid("0000000B-0000-0000-C000-000000000046"); 
UInt32 results; 

results = NativeMethods.StgCreateStorageEx(null, NativeMethods.STGM_READWRITE + NativeMethods.STGM_SHARE_EXCLUSIVE, 
        NativeMethods.STGFMT.STGFMT_STORAGE, 0, IntPtr.Zero, IntPtr.Zero, IID_IStorage, (void**)Marshal.ReadIntPtr(ptr2ptr2ptr).ToPointer()); 

Hat jemand irgendwelche Ideen, wie man dieses Durcheinander glätten und es wirklich arbeiten lassen kann?

Übrigens ist das ultimative Ziel hier, einen Ordner von einem TreeView in Windows Explorer ziehen zu können und diesen Ordner und seinen gesamten Inhalt dorthin schreiben zu lassen, wo er abgelegt wurde. Der Catch ist das TreeView repräsentiert ein Dateisystem komplett in einer Datenbank gespeichert. Die einzige Möglichkeit, dies zu tun, bestand darin, eine IStorage zu übergeben, daher musste StgCreateStorageEx aufgerufen werden.

+0

Haben Sie versucht pinvoke.net? http://pinvoke.net/default.aspx/ole32/StgCreateStorageEx.html sagt, dass es einen verwalteten Wrapper für OLE-strukturierten Speicher gibt, der möglicherweise verwendet werden kann. –

+0

Dort fing ich an. Soweit ich das beurteilen kann, eignet sich System.IO.Packaging hervorragend für die Arbeit mit bereits vorhandenen Speichern, Sie können jedoch keine neuen erstellen. –

Antwort

1

Aus der Signatur und Dokumentation von StgCreateStorage, ich glaube nicht, dass Sie einen Puffer wie diesen dafür erstellen sollen, Sie brauchen nur einen Verweis auf einen Zeiger, damit StgCreateStorage den Wert auf das erstellte Objekt setzen kann.

(void **) als ref Objekt werden kann interperated wo Objekt == (void *)

ich hier das Hauptproblem denken, dass die Zugriffsverletzung verursacht wird, dass riid ist REFID, die für ein typedef ist (IID *) und sollte daher sein ref Guid, die

pinvoke der Lage sein sollte, dies umgehen mit:


     [DllImport("ole32.dll")] 
     public static extern UInt32 StgCreateStorageEx(
      [MarshalAs(UnmanagedType.LPWStr), In] string pwcsName, 
      int grfMode, 
      int stgfmt, 
      uint grfAttrs, 
      [In] IntPtr pStgOptions, 
      [In] IntPtr reserved2, 
      [In] ref Guid riid, 
      [MarshalAs(UnmanagedType.IUnknown), Out] out object ppObjectOpen); 
+0

Also deklariere ich einfach "object ppObjectOpen;" und dann das als letzten Parameter übergeben? Ich bekomme die Zugriffsverletzung immer noch so. Ich werde den modifizierten Code veröffentlichen, wenn ich herausfinden kann, wie ich aus dieser kleinen Kommentarbox herauskommen kann. –

+0

Ich reparierte die Methodensignatur, grfMode sollte ein Int nicht lange sein. –

+0

Fühlen Sie sich frei, stgfmt und grfmode durch enums zu ersetzen, stellen Sie einfach sicher, dass der Enum-Typ int ist. –

Verwandte Themen