我一直在努力弄清楚如何在C#中调用StgCreateStorageEx,而且我必须为它展示的是一个AccessViolationException并且很头疼。
我甚至不确定我应该如何宣布这个功能。我看到有数十亿个网站宣布它有多种不同的方式。但这就是我现在所拥有的:
[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)
我看过网站告诉我,我需要在最后一个参数上使用MarshalAs,我尝试过使用IUnknown,Interface,LPStruct和其他几个参数。唯一让我感到困惑的是关于数据类型的marshaller。我觉得这可能是相关的,但由于它只告诉我它不想要什么,我不知道它想要什么。
关于如何调用函数:这开始变得更简单了。但是在得到内存违规后我开始阅读并最终得出结论,确保GC没有搞砸我的唯一方法是自己管理内存,因此你有这个混乱:
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());
任何人都有任何关于如何理顺这个混乱并使其真正起作用的想法?
顺便说一句,这里的最终目标是能够将文件夹从TreeView拖到Windows资源管理器中,并让它将该文件夹及其所有内容写入删除的任何位置。问题是TreeView表示完全存储在数据库中的文件系统。我能找到的唯一方法就是传递一个IStorage,因此需要调用StgCreateStorageEx。
答案 0 :(得分:1)
从StgCreateStorage的签名和文档中,我认为你不应该为它创建一个类似的缓冲区,你只需要一个指针引用,这样StgCreateStorage就可以为创建的对象设置值。 p>
(void **)可以作为ref对象与object ==(void *)
进行交互我认为导致访问冲突的关键问题是riid是REFID,它是(IID *)的typedef,因此应该是 ref Guid ,
pinvoke应该能够使用:
来处理这个问题
[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);