2010-04-08 5 views
1

내 응용 프로그램의 MiniDump를 만들 수있는 최종 사용자 용 도구를 만들려고합니다 (예 : 앱 외부). 내 내부 MiniDumper 같은 코드를 사용하지만 응용 프로그램의 핸들 및 processid 함께하지만 MiniDumpWriteDump 호출 할 때 오류 코드 0xD0000024 점점 계속. 어떤 아이디어?실행중인 프로세스의 미니 덤프 만들기

void produceDump(const char* exe) 
{ 
    DWORD processId = 0; 
    HANDLE process = findProcess(exe, processId); 

    if (!process || processId == 0) 
    { 
     printf("Unable to find exe %s to produce dump.\n", exe); 
     return; 
    } 

    LONG retval = EXCEPTION_CONTINUE_SEARCH; 
    HWND hParent = NULL;      // find a better value for your app 

    // firstly see if dbghelp.dll is around and has the function we need 
    // look next to the EXE first, as the one in System32 might be old 
    // (e.g. Windows 2000) 
    HMODULE hDll = NULL; 
    char szDbgHelpPath[_MAX_PATH]; 

    if (GetModuleFileName(NULL, szDbgHelpPath, _MAX_PATH)) 
    { 
     char *pSlash = _tcsrchr(szDbgHelpPath, '\\'); 
     if (pSlash) 
     { 
      _tcscpy(pSlash+1, "DBGHELP.DLL"); 
      hDll = ::LoadLibrary(szDbgHelpPath); 
     } 
    } 

    if (hDll==NULL) 
    { 
     // load any version we can 
     hDll = ::LoadLibrary("DBGHELP.DLL"); 
    } 

    LPCTSTR szResult = NULL; 

    int err = 0; 

    if (hDll) 
    { 
     MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress(hDll, "MiniDumpWriteDump"); 
     if (pDump) 
     { 
      char szDumpPath[_MAX_PATH]; 
      char szScratch [_MAX_PATH]; 

      time_t rawtime; 
      struct tm * timeinfo; 

      time (&rawtime); 
      timeinfo = localtime (&rawtime); 

      char comAppPath[MAX_PATH]; 
      SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA , NULL, SHGFP_TYPE_CURRENT, comAppPath); 


      //COMMONAPP_PATH 
      _snprintf(szDumpPath, _MAX_PATH, "%s\\DN", comAppPath); 
      CreateDirectory(szDumpPath, NULL); 

      _snprintf(szDumpPath, _MAX_PATH, "%s\\DN\\D", comAppPath); 
      CreateDirectory(szDumpPath, NULL); 

      _snprintf(szDumpPath, _MAX_PATH, "%s\\DN\\D\\dumps", comAppPath); 
      CreateDirectory(szDumpPath, NULL); 

      char fileName[_MAX_PATH]; 
      _snprintf(fileName, _MAX_PATH, "%s_Dump_%04d%02d%02d_%02d%02d%02d.dmp", exe, timeinfo->tm_year+1900, timeinfo->tm_mon, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); 
      _snprintf(szDumpPath, _MAX_PATH, "%s\\DN\\D\\dumps\\%s", comAppPath, fileName); 

      // create the file 
      HANDLE hFile = ::CreateFile(szDumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
      if (hFile!=INVALID_HANDLE_VALUE) 
      { 
       MINIDUMP_CALLBACK_INFORMATION mci; 

       mci.CallbackRoutine  = (MINIDUMP_CALLBACK_ROUTINE)MyMiniDumpCallback; 
       mci.CallbackParam  = 0; 

       MINIDUMP_TYPE mdt  = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory | 
                  MiniDumpWithDataSegs | 
                  MiniDumpWithHandleData | 
                  //MiniDumpWithFullMemoryInfo | 
                  //MiniDumpWithThreadInfo | 
                  MiniDumpWithProcessThreadData | 
                  MiniDumpWithUnloadedModules); 

       // write the dump 
       BOOL bOK = pDump(process, processId, hFile, mdt, NULL, NULL, &mci); 
       DWORD lastErr = GetLastError(); 

       if (bOK) 
       { 
        printf("Crash dump saved to: %s\n", szDumpPath); 
        return; 
       } 
       else 
       { 
        _snprintf(szScratch, _MAX_PATH, "Failed to save dump file to '%s' (error %u)", szDumpPath, lastErr); 
        szResult = szScratch; 
        err = ERR_CANTSAVEFILE; 
       } 
       ::CloseHandle(hFile); 
      } 
      else 
      { 
       _snprintf(szScratch, _MAX_PATH, "Failed to create dump file '%s' (error %u)", szDumpPath, GetLastError()); 
       szResult = szScratch; 
       err = ERR_CANTMAKEFILE; 
      } 
     } 
     else 
     { 
      szResult = "DBGHELP.DLL too old"; 
      err = ERR_DBGHELP_TOOLD; 
     } 
    } 
    else 
    { 
     szResult = "DBGHELP.DLL not found"; 
     err = ERR_DBGHELP_NOTFOUND; 
    } 

    printf("Could not produce a crash dump of %s.\n\n[error: %u %s].\n", exe, err, szResult); 
    return; 
} 

이 코드는 100 % 일 때

+0

ADPlus (Windows 용 무료 디버깅 도구의 일부)를 가리 키지 않는 이유는 무엇입니까? http://stackoverflow.com/questions/2591406/how-to-print-stack-trace-of-stackoverflowexception/2591466#2591466 – Richard

+0

@richard 1 exe 솔루션이 좋겠지 만 확인해 보겠습니다. – Lodle

+0

게시 할 수 있습니까? findProcess()에 코드? – bk1e

답변

1

당신이 필요한 액세스 권한으로 프로세스를 열고있다 (즉에 SetUnhandledExceptionFilter와) 과정에 내부? MiniDumpWriteDump()PROCESS_QUERY_INFORMATIONPROCESS_VM_READ 액세스 권한을 사용하여 프로세스 핸들을 열어야합니다. GetCurrentProcess()을 사용할 때는 자동으로 허용되지만, OpenProcess()을 사용하여 다른 프로세스를 열면이 권한을 요청해야합니다.

이렇게하려면 enable SeDebugPrivilege이어야하며 계정에 해당 권한이없는 사용자에게는 문제가 발생할 수 있습니다. 그러나 특히 동일한 사용자 계정으로 실행중인 프로세스를 여는 경우 PROCESS_QUERY_INFORMATIONPROCESS_VM_READ에 대한 권한이 구체적으로 (모든 프로세스 액세스 권한과 반대되는) SeDebugPrivilege인지 여부에 대한 문서가 명확하지 않은 것 같습니다.

+0

그래, 내가 그것을 돌려 보내기 전에 핸들을 닫고 제외했다. 내가 알고 싶은 또 다른 일은 서비스에 대한 핸들을 열고 그 허가를 거부하는 것을 계속 막는 것입니다. – Lodle

0

MyMiniDumpCallback을 명시 적으로 PMINIDUMP_CALLBACK_INFORMATION 유형으로 캐스팅하는 것으로 나타났습니다. 컴파일러 오류가 발생하여 유형이 일치하지 않아 주변을 돌아 다니는 것처럼 생기게 보입니다. 그것과 PMINIDUMP_CALLBACK_INFORMATION은 함수 포인터가 아니라 구조체입니다.

PMINIDUMP_CALLBACK_INFORMATION에 대한 함수 포인터의 직접 형변환은 해당 구조체의 첫 번째 매개 변수가 콜백 함수이므로 유효 할 수 있습니다. 그러나 다시, 그것은 진짜 물고기 같아 보인다. 아마도 콜백 함수를 잘못 선언 한 것입니다 (예 : CALLBACK/__ stdcall 수정 자 잊음). 공식적인 매개 변수를 먼저 캐스팅하지 않고 코드를 컴파일하면 더 도움이 될 것입니다.

또한 콜백 함수가 호출되는 것을 확인 했습니까?

관련 문제