C# 从DBGHELP使用SymSrvStoreFileW
我正在尝试从DBGHELP.DLL调用C# 从DBGHELP使用SymSrvStoreFileW,c#,c++,interop,pinvoke,C#,C++,Interop,Pinvoke,我正在尝试从DBGHELP.DLL调用SymSrvStoreFileW(之前尝试使SymSrvGetFileIndexInfoW工作失败后)。重要功能在MSDN中定义如下: BOOL WINAPI SymInitialize( _In_ HANDLE hProcess, _In_opt_ PCTSTR UserSearchPath, // null is documented as fine _In_ BOOL fInvadeProcess // false )
SymSrvStoreFileW
(之前尝试使SymSrvGetFileIndexInfoW
工作失败后)。重要功能在MSDN中定义如下:
BOOL WINAPI SymInitialize(
_In_ HANDLE hProcess,
_In_opt_ PCTSTR UserSearchPath, // null is documented as fine
_In_ BOOL fInvadeProcess // false
);
PCTSTR WINAPI SymSrvStoreFile(
_In_ HANDLE hProcess,
_In_opt_ PCTSTR SrvPath, // e.g. "srv*C:\symbols"
_In_ PCTSTR File, // e.g. "C:\myapp.pdb"
_In_ DWORD Flags // I am using SYMSTOREOPT_RETURNINDEX (0x04)
);
BOOL WINAPI SymCleanup(
_In_ HANDLE hProcess
);
hProcess有点奇怪,据我推测,只要你保持一致,你传递给它的内容实际上并不重要。我使用了当前进程ID和“任何旧值”ID。两者都不起作用
我做了以下外部操作
:
[DllImport("dbghelp.dll", EntryPoint = "SymInitializeW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern bool SymInitialize(
IntPtr process,
[param: MarshalAs(UnmanagedType.LPTStr)]
string searchPath,
bool invadeProcess);
[DllImport("dbghelp.dll", EntryPoint = "SymCleanup", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern bool SymCleanup(IntPtr process);
[DllImport("dbghelp.dll", EntryPoint = "SymSrvStoreFileW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.LPTStr)]
public static extern string SymSrvStoreFile(
IntPtr process,
[param: MarshalAs(UnmanagedType.LPTStr)]
string srvPath,
[param: MarshalAs(UnmanagedType.LPTStr)]
string file,
SymStoreOpt options);
enum SymStoreOpt : uint
{
None = 0x00,
Compress = 0x01,
Overwrite = 0x02,
Pointer = 0x08,
ReturnIndex = 0x04,
PassIfExists = 0x40,
}
并尝试呼叫:
var processId = IntPtr.Zero;
try
{
// This succeeds.
processId = new IntPtr(Process.GetCurrentProcess().Id);
if (!NativeMethods.SymInitialize(processId, null, false))
{
processId = IntPtr.Zero;
throw new Win32Exception(Marshal.GetLastWin32Error());
}
// This fails.
var storageLocation = NativeMethods.SymSrvStoreFile(processId, "srv*C:\\vssym", "C:\\test\\mscorlib.pdb", SymStoreOpt.ReturnIndex);
if (storageLocation == null)
{
// Errors under various circumstances.
// - The operation completed successfully (but storageLocation is still null)
// - The specified module could not be found
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
finally
{
if (processId != IntPtr.Zero)
NativeMethods.SymCleanup(processId);
}
我的extern
声明有错误吗?或者,有人知道如何获取PDB/PE(而不仅仅是.Net)的符号存储位置吗?我还尝试了其他SymStoreOpt
标志,但一无所获
在某个时刻(我不记得我做了什么),文件出现在符号存储位置(即使使用了ReturnIndex
),但在那个时候,我的进程将崩溃(调试器甚至无法捕获它的进程之一),再次运行它将导致“操作成功”,而没有返回值
<强> >:,并且仍然得到相同的行为——显然,我不想走那个路由,因为P/Unjk有架构中性的优点。
是<代码> > PraceSeSID<代码> >在您的代码> SysRvStReFiFLIs//Case>一个类型错误中。它实际上也在C++中发生。“有什么想法吗?”理查德:是的,谢谢。实际上,我把它从包装器类中拉了出来,使事情变得更简单,但效果仍然是一样的。好吧,我唯一的另一个想法是对PCTSTR
字符串进行编组。我认为您需要使用Marshal.StringToHGlobalUni
来处理这些问题:尽管稍后的回答建议UnmanagedType.LPTStr
应该可以: