2012-01-06 16 views
3

ok ...これを焼き切って...一日中私の頭を傷つける。私は非常にシンプルな、アプリケーションを起動するために使用される単一の目的のC + +のDLL(StartApplication.dll)があります。Windows 7 - DEBUG_PROCESSを持つCreateProcessアクセス違反

  • は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; 

}

答えて

3

をいただければ幸いあなたのコードでは、最初の例外occures後に全体の処理を終了します。 例外が処理されなかった場合にのみ、プログラムが例外を処理するようにする必要があります。

例外が致命的だったかどうかを確認するために(。つまり、最初の頃は取り扱っておりません)u.Exception.dwFirstChanceを確認してください。

  • それが0なら、それに応じてエラーコードを設定して終了します。
  • 例外が初めて発生した場合は、ContinueDebugEventDBG_EXCEPTION_NOT_HANDLEDを呼び出して例外をプロセスに渡す必要があります。

EDIT

あなたが唯一の例外を見ていないデバッガ内部からそれらを処理したい場合は、常にDBG_EXCEPTION_NOT_HANDLEDを継続する必要があります。

1つのキャッチあります:

右メインスレッドを開始する前に、Windowsがニーズがプロセス(DBG_CONTINUE)へを渡されるINT3の例外が発生します。

擬似コード:

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; 
    } 
+0

@Ajay:EXCEPTION_DEBUG_EVENTスイッチで終了する前にcontinueStatusを設定して、 ".dwFirstChance!= 0"条件を追加しました。単に別のループを実行し、次のループで終了します。私は自分自身をコーディングする初心者のビットです(私はこれを元々書いていませんでした)。もし私が悪いところに置いたら、私に知らせてください。 (またはプロセスの一部がある場合は、私は完全に核にすることができます)。私は物事を並べ替える場合、私はcmdをウィンドウが必要に応じてポップアップを得ることができますが、それはハングアップし、終了するまで何もしません。適切に実行するためにいくつかの種類のウィンドウ7の許可を設定する必要がありますか? – 0xDEADFACE

+0

@ 0xDEADFACEが私の答えを更新しました。 – pezcode

+0

ああそこに行きます。 INT3例外を処理することはそこに欠落していました。正常に終了を処理するために少し調整する必要があったが、それは魅力的だった。おかげで束の間人。 – 0xDEADFACE

1

@pezcodeは右である - ちょうどデバッグ対象から最初の例外を受信するプロセスを終了していない、それが正常に実行してみましょう。デバッガ(あなたのコード)は、とにかくdebuggee(最初のチャンスの例外)で発生するすべての例外を受け取ります。

まず、デバッガのループロジックを最小限に抑え、プロセスにアタッチして処理しないようにしてください。最初は単純にしておいてください。

2

正しく理解していれば、プロセスが終了するまで待つことができるように、DEBUG_PROCESSを使用しています。それは大きな過労です。

プロセスが終了するまで待機するには、pi.hProcessでWaitForSingleObject(または必要に応じて別の待機関数)を使用します。

+0

よく、私はデバッグプロセスが必要なので、すべての例外コードを送り返す必要があります。私のイントロでは言葉が貧弱だと思います – 0xDEADFACE

関連する問題