我一直在尝试这个新功能,并决定使用
dbghelp.dll
s
SymGetModuleInfo64
作为一个例子。我编写了自定义封送器,我可以运行它(下面是生成的代码),但当结果为
ConvertToManaged
被重新分配给ref。ref参数需要特殊处理吗?目前,我只是在实例化一个
IMAGEHELP_MODULE64
并设置其
SizeOfStruct
在将其传递给
SymGetModuleInfo64
.
public unsafe partial class Test
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Interop.LibraryImportGenerator", "7.0.10.26716")]
[System.Runtime.CompilerServices.SkipLocalsInitAttribute]
private static partial bool SymGetModuleInfo64(nint hProcess, long ModuleBase64, ref global::Test.Test.IMAGEHELP_MODULE64 imgHelpModule)
{
int __lastError;
global::Test.Test.IMAGEHELP_MODULE64_Marshaller.Unmanaged __imgHelpModule_native;
bool __retVal;
int __retVal_native;
// Marshal - Convert managed data to native data.
__imgHelpModule_native = global::Test.Test.IMAGEHELP_MODULE64_Marshaller.ConvertToUnmanaged(imgHelpModule);
{
System.Runtime.InteropServices.Marshal.SetLastSystemError(0);
__retVal_native = __PInvoke(hProcess, ModuleBase64, &__imgHelpModule_native);
__lastError = System.Runtime.InteropServices.Marshal.GetLastSystemError();
}
// Unmarshal - Convert native data to managed data.
__retVal = __retVal_native != 0;
-----> imgHelpModule = global::Test.Test.IMAGEHELP_MODULE64_Marshaller.ConvertToManaged(__imgHelpModule_native);
System.Runtime.InteropServices.Marshal.SetLastPInvokeError(__lastError);
return __retVal;
// Local P/Invoke
[System.Runtime.InteropServices.DllImportAttribute("dbghelp.dll", EntryPoint = "SymGetModuleInfo64", ExactSpelling = true)]
static extern unsafe int __PInvoke(nint hProcess, long ModuleBase64, global::Test.Test.IMAGEHELP_MODULE64_Marshaller.Unmanaged* imgHelpModule);
}
}
我尝试为参数分配内存,以确保我拥有它,但无论我做什么,我仍然会得到
AccessViolationException
.
这是什么
Test
生成上述代码的类看起来像(注意:我只对
LoadedPdbName
所以我没有为整个结构体实现编组,但这应该没关系,PInvoke调用成功了):
public unsafe partial class Test
{
[StructLayout(LayoutKind.Sequential)]
[NativeMarshalling(typeof(IMAGEHELP_MODULE64_Marshaller))]
private struct IMAGEHELP_MODULE64
{
public int SizeOfStruct;
public long BaseOfImage;
public int ImageSize;
public int TimeDateStamp;
public int CheckSum;
public int NumSyms;
public SymType SymType;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string ModuleName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string ImageName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string LoadedImageName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string LoadedPdbName;
public int CVSig;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 780)]
public string CVData;
public int PdbSig;
public GUID PdbSig70;
public int PdbAge;
public bool PdbUnmatched;
public bool DbgUnmatched;
public bool LineNumbers;
public bool GlobalSymbols;
public bool TypeInfo;
public bool SourceIndexed;
public bool Publics;
public int MachineType;
public int Reserved;
}
[StructLayout(LayoutKind.Sequential)]
private struct GUID
{
public int Data1;
public ushort Data2;
public ushort Data3;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] data4;
}
[Flags]
private enum SymType : uint
{
SymNone,
SymCoff,
SymCv,
SymPdb,
SymExport,
SymDeferred,
SymSym,
SymDia,
SymVirtual,
}
[CustomMarshaller(typeof(IMAGEHELP_MODULE64), MarshalMode.Default, typeof(IMAGEHELP_MODULE64_Marshaller))]
private static unsafe class IMAGEHELP_MODULE64_Marshaller
{
[StructLayout(LayoutKind.Explicit)]
public ref struct Unmanaged
{
[FieldOffset(0)] public int SizeOfStruct;
[FieldOffset(580)] public fixed byte LoadedPdbName[256];
}
public static Unmanaged ConvertToUnmanaged(IMAGEHELP_MODULE64 managed)
{
return new Unmanaged
{
SizeOfStruct = managed.SizeOfStruct
};
}
public static IMAGEHELP_MODULE64 ConvertToManaged(Unmanaged unmanaged)
{
return new IMAGEHELP_MODULE64
{
LoadedPdbName = AnsiStringMarshaller.ConvertToManaged(unmanaged.LoadedPdbName)
};
}
}
[LibraryImport("dbghelp.dll", StringMarshalling = StringMarshalling.Utf8, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static partial bool SymGetModuleInfo64(nint hProcess, long ModuleBase64,
ref IMAGEHELP_MODULE64 imgHelpModule);
}
以下是它的使用方式:
var moduleInfo = new IMAGEHELP_MODULE64();
moduleInfo.SizeOfStruct = Marshal.SizeOf(moduleInfo);
if (!SymGetModuleInfo64(_processPtr, _baseOfDll, ref moduleInfo))
throw new Win32Exception(Marshal.GetLastWin32Error());