简体   繁体   English

C#中的StgCreateStorageEx提供AccessViolationException

[英]StgCreateStorageEx in C# gives AccessViolationException

I've been trying to figure out for nearly a week now how to call StgCreateStorageEx in C#, and all I've got to show for it is an AccessViolationException and a headache. 我已经尝试找出将近一个星期的方法来使用C#调用StgCreateStorageEx,为此我要展示的只是AccessViolationException和令人头疼的问题。

I'm not even sure how I should declare the function. 我什至不确定如何声明该函数。 I've seen a zillion websites declare it a zillion different ways. 我见过无数的网站以不同的方式声明它。 But this is what I currently have: 但这是我目前拥有的:

[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)

I've seen sites tell me I need to use MarshalAs on the last parameter, and I've tried using IUnknown, Interface, LPStruct, and several others. 我已经看到网站告诉我我需要在最后一个参数上使用MarshalAs,并且我尝试使用IUnknown,Interface,LPStruct和其他几个参数。 The only thing that got me was the marshaller griping about data types. 吸引我的唯一一件事就是封送员对数据类型的关注。 I get the feeling that is probably related, but since it only tells me what it doesn't want, I have no idea what it does wants. 我得到的感觉可能与之相关,但是由于它只告诉我不想要的东西,所以我不知道它想要什么。

On to how I call the function: This started out much simpler. 关于如何调用该函数:开始时要简单得多。 But after getting the memory violations I started reading and finally came to the conclusion that the only way to be sure the GC wasn't screwing me over was to manage the memory myself, thus you have this mess: 但是在遇到内存违规问题之后,我开始阅读并最终得出结论,确保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());

Anybody got any ideas on how to straighten this mess out and make it actually work? 有人对如何弄清这一混乱并使之真正起作用有任何想法吗?

By the way, the ultimate goal here is to be able to drag a folder from a TreeView into Windows Explorer and have it write that folder and all of its contents to wherever it dropped. 顺便说一句,这里的最终目标是能够将文件夹从TreeView拖动到Windows资源管理器中,并使其将该文件夹及其所有内容写入到放置的任何位置。 The catch is the TreeView represents a file system stored entirely in a database. 所捕获的是TreeView代表完全存储在数据库中的文件系统。 The only way I could find to do that was to pass an IStorage, hence the need for a call to StgCreateStorageEx. 我能找到的唯一方法是传递IStorage,因此需要调用StgCreateStorageEx。

From StgCreateStorage's signature and documentation, I don't think you're supposed to be creating a buffer like that for it, you just need a reference to a pointer so that StgCreateStorage can set the value to the created object. 从StgCreateStorage的签名和文档中,我认为您不应该为此创建一个缓冲区,只需要引用一个指针,以便StgCreateStorage可以将值设置为所创建的对象。

(void**) can be interperated as ref object where object == (void*) (void **)可以作为ref对象插入,其中object ==(void *)

I think the key problem here that is causing the access violation is that riid is REFID which is a typedef for (IID*) and thus should be ref Guid , the 我认为这里导致访问冲突的关键问题是riid是REFID,它是(IID *)的typedef,因此应参考guid

pinvoke should be able to handle this using: 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM