好的……烧掉了这一天……整天都在挠头.我有一个非常简单的单用途c DLL(StartApplication.dll)用于启动应用程序.
>在WinXP中运行良好,但在win7中运行不正常
>使用带有DEBUG_PROCESS的CreateProcess()(所以我可以等待程序在终止之前完成).
>如果我在任务管理器中监视进程,我可以看到进程开始,但没有创建窗口,也没有进一步发生
>如果我改为norMAL_PRIORITY_CLASS,程序将按原样执行(但我在终止之前无法等待,因为我只能在调试时执行此操作)
>错误代码给了我STATUS_ACCESS_VIOLATION
>我关闭了UAC并将可执行文件设置为以管理员身份运行,并且与WinXP兼容无效
继承人的代码.任何想法将不胜感激
//...blah blah...handful of stuff preceding this to set up command line and
//directories etc....not of use here probably...
Security_ATTRIBUTES sa = {0}; sa.nLength = sizeof(Security_ATTRIBUTES);
sa.bInheritHandle = TRUE;
STARTUPINFO si = {0}; si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = (NULL == stdOutFileName)? INVALID_HANDLE_VALUE :
::CreateFile(stdOutFileName, GENERIC_WRITE, FILE_SHARE_READ, &sa
, CREATE_ALWAYS, 0, NULL);
si.hStdError = (NULL == stdErrFileName)? INVALID_HANDLE_VALUE :
::CreateFile(stdErrFileName, GENERIC_WRITE, FILE_SHARE_READ, &sa
, CREATE_ALWAYS, 0, NULL)
PROCESS_informatION pi = {0};
if (::CreateProcess(useApplicationName? applicationName : NULL, processCommandLine
, NULL, NULL, TRUE, /*norMAL_PRIORITY_CLASS*/DEBUG_PROCESS, NULL, currentDirectory, &si, &pi))
{
BOOL cont = TRUE;
while (cont)
{
DWORD continueStatus = DBG_CONTINUE;
DEBUG_EVENT debugEvent = {0};
if (!::WaitForDebugEvent(&debugEvent, INFINITE))
{
errorCode = ErrorCode_Other;
::TerminateProcess(pi.hProcess, 0);
break;
}
else
{
switch (debugEvent.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
switch (debugEvent.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
case EXCEPTION_DATATYPE_MISALIGNMENT:
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
case EXCEPTION_FLT_DEnorMAL_OPERAND:
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_FLT_INEXACT_RESULT:
case EXCEPTION_FLT_INVALID_OPERATION:
case EXCEPTION_FLT_OVERFLOW:
case EXCEPTION_FLT_STACK_CHECK:
case EXCEPTION_FLT_UNDERFLOW:
case EXCEPTION_INT_DIVIDE_BY_ZERO:
case EXCEPTION_INT_OVERFLOW:
case EXCEPTION_PRIV_INSTRUCTION:
case EXCEPTION_IN_PAGE_ERROR:
case EXCEPTION_ILLEgal_INSTRUCTION:
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
case EXCEPTION_STACK_OVERFLOW:
case EXCEPTION_INVALID_disPOSITION:
case EXCEPTION_INVALID_HANDLE:
errorCode = ErrorCode_ApplicationException;
*exceptionCode = debugEvent.u.Exception.
ExceptionRecord.ExceptionCode;
::TerminateProcess(pi.hProcess, 0);
break;
default:
;
}
break;
case EXIT_PROCESS_DEBUG_EVENT:
cont = FALSE;
break;
default:
;
}
::ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId
, continueStatus);
}
}
::GetExitCodeProcess(pi.hProcess, reinterpret_cast<LPDWORD>(exitCode));
::CloseHandle(pi.hProcess);
::CloseHandle(pi.hThread);
}
if (INVALID_HANDLE_VALUE != si.hStdOutput)
::CloseHandle(si.hStdOutput);
if (INVALID_HANDLE_VALUE != si.hStdError)
::CloseHandle(si.hStdError);
return errorCode;
}
解决方法:
在第一个异常发生后,您的代码将终止整个过程.
通常,您应该让程序处理异常,只有在未处理异常时才会终止进程.
要查看异常是否致命(即第一次没有处理),请检查u.Exception.dwFirstChance:
>如果为0,请相应地设置错误代码并终止.
>否则,第一次发生异常,您应该使用DBG_EXCEPTION_NOT_HANDLED调用ContinueDebugEvent将异常传递给进程.
编辑
如果您只想查看异常而不是从调试器中处理异常,则应始终继续使用DBG_EXCEPTION_NOT_HANDLED.
有一个问题:
在主线程启动之前,Windows引发了一个INT3异常,需要将该异常传递给进程(DBG_CONTINUE).
伪代码:
bool FirstInt3 = true;
while (cont)
{
DWORD continueStatus = DBG_EXCEPTION_NOT_HANDLED;
// ....
switch(...)
{
case EXCEPTION_DEBUG_EVENT:
if(!FirstChance)
{
// Fatal exception
// Log Exception that terminated the program here
// Don't do anything else, Windows automatically terminates the process
// You will get an EXIT_PROCESS_DEBUG_EVENT on the next event
}
switch (debugEvent.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_BREAKPOINT:
if(FirstInt3)
{
FirstInt3 = false;
continueStatus = DBG_CONTINUE;
break;
}
default:
// Log ExceptionCode here
break;
}
break;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。