我正在迈出COM的第一步,但我一直在收到System.AccessViolationException,这是一个不会告诉你任何价值的例外情况。我正在尝试使用SHCreateItemFromParsingName创建一个IShellItem。我从另一个项目中复制了界面的定义,所以我知道它没有任何问题,问题很可能发生在我的函数定义/调用中,我自己为了学习目的而编写。
我想调用非托管函数,而不返回IShellItem接口,而是将它的引用传递给调用中的最后一个参数。
函数声明:
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
internal static extern uint SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IBindCtx pbc, Guid riid, out IShellItem ppv);
函数调用:
IShellItem file;
SHCreateItemFromParsingName(@"C:\file.txt", null, typeof(IShellItem).GUID, out file);
我发现IDL相当神秘,但我的理由是:
答案 0 :(得分:1)
问题来自REFIID类型参数。它不是GUID(16字节结构),而是GUID引用( REF IID),一个指针(所以4或8个字节取决于进程位数)。
所以你可以使用ref
关键字来定义这样的方法(所以结构将通过引用传递,作为指针):
internal static extern uint SHCreateItemFromParsingName(
[MarshalAs(UnmanagedType.LPWStr)] string pszPath,
IBindCtx pbc,
ref Guid riid,
out IShellItem ppv);
但我建议这种方式更容易使用,并避免创建/复制GUID(您将以与您相同的方式调用它):
internal static extern uint SHCreateItemFromParsingName(
[MarshalAs(UnmanagedType.LPWStr)] string pszPath,
IBindCtx pbc,
[MarshalAs(UnmanagedType.LPStruct)] Guid riid,
out IShellItem ppv);