0

近一个星期以来,我一直试图弄清楚如何在 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 和其他几个参数。唯一让我感到困惑的是编组器对数据类型的抱怨。我有一种可能是相关的感觉,但由于它只告诉我它不想要什么,我不知道它想要什么。

关于我如何调用函数:这开始时要简单得多。但是在得到内存违规后,我开始阅读并最终得出结论,确保 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。

4

1 回答 1

1

从 StgCreateStorage 的签名和文档来看,我认为您不应该为它创建一个这样的缓冲区,您只需要一个指针的引用,以便 StgCreateStorage 可以将值设置为创建的对象。

(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);
于 2009-08-11T20:29:50.623 回答