在我无法访问的客户机器(WinXP SP2)上,我有一个在启动时崩溃的Win32 EXE(非托管C ++)。我想解决此问题的最佳方法是获取(小型)转储并稍后使用windbg或类似方法对其进行分析。
现在,我通常会告诉客户安装Windows调试工具并运行
cscript adplus.vbs -crash
但是,您似乎无法将adplus用于在启动时崩溃的应用程序(http://support.microsoft.com/kb/q286350/说“在以下情况下不要使用ADPlus:如果您必须对在此期间意外退出的程序或进程进行故障排除启动”)。同一篇文章说“使用用户模式进程转储”,但我没能成功安装它。
如何获取在Win32上启动时崩溃的进程的转储?
答案 0 :(得分:13)
或者,您可以设置自己的转储生成框架,在遇到任何未处理的异常时自动创建进程转储。这样可以避免客户端安装Windbg。
使用SetUnhandledExceptionFilter Win32 API在应用程序启动时注册应用程序级异常处理程序。只要有任何未处理的异常,就会调用已注册的回调函数。然后,U可以使用DbgHelp.dll中的MiniDumpWriteDump api创建进程转储。
示例代码: -
LONG WINAPI My_UnhandledExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
{
HANDLE hFile = CreateFile("FileName",
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
MINIDUMP_EXCEPTION_INFORMATION aMiniDumpInfo;
aMiniDumpInfo.ThreadId = GetCurrentThreadId();
aMiniDumpInfo.ExceptionPointers = ExceptionInfo;
aMiniDumpInfo.ClientPointers = TRUE;
MiniDumpWriteDump(GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
(MINIDUMP_TYPE) (MiniDumpWithFullMemory|MiniDumpWithHandleData),
&aMiniDumpInfo,
NULL,
NULL);
CloseHandle(hFile);
return EXCEPTION_EXECUTE_HANDLER;
}
int main(int argc, char* argv[])
{
SetUnhandledExceptionFilter(&My_UnhandledExceptionFilter);
// User code throwing exception..
return 0;
}
注意: - 正在调试进程时,不会调用已注册的异常过滤器。因此,在调试期间,如果将断点放在异常过滤器函数中,如果在导致未处理的异常后仍未命中,请不要感到惊讶。
答案 1 :(得分:7)
您可以在客户端计算机上安装WinDBG,然后使用“Image File Execution Options”并在进程启动后将WinDBG设置为打开。然后运行崩溃进程,WinDBG将立即打开。按 g (Go)并等待进程崩溃,然后键入“ .dump / mfh dumpFileName.dmp ”。现在你有了可以调试的转储文件。
答案 2 :(得分:2)
答案 3 :(得分:0)
在客户端计算机上安装开发人员工具将是我最后的选择,我必须承认我讨厌这个想法,特别是在有替代方案适合你的地方。
首先注册WinQual。您现在可以自动访问客户的崩溃转储和其他错误。我记得这是一项免费服务,没有理由不使用它。
由于WinQual可能需要一段时间才能找到崩溃转储,并且总是很高兴能够对客户做出更快的响应,特别是在应用程序崩溃时,使用Dr. Watson。我记得发生崩溃时,在点击对话框之前,您可以从开始 - >运行或命令行运行 drwatsn32 ,然后会弹出Dr Watson。此时,关闭崩溃对话框将生成崩溃转储文件。如果失败,请在命令行上使用 -i 参数运行Dr. Watson。