转载:https://www.easyicon.net/(免费icon)

转载:https://www.codeproject.com/Articles/5260/XCrashReport-Exception-Handling-and-Crash-Report-4(codeproject示例demo)

转载:https://blog.csdn.net/agan4014/article/details/2614770

转载:http://blog.sina.com.cn/s/blog_5513eb7b0100nu80.html

转载:https://blog.csdn.net/sunflover454/article/details/51200663

实现原理:在程序运行过程中异常,通过捕获异常,并在回调函数启动BugReport程序

实现效果

第一步:导入上面的源码文件到自己的工程中

CrashFileNames.h

#ifndef CRASHFILENAMES_H
#define CRASHFILENAMES_H #define XCRASHREPORT_MINI_DUMP_FILE _T("CRASH.DMP")//Crash文件
#define XCRASHREPORT_ERROR_LOG_FILE _T("ERRORLOG.TXT")//日志文件
#define XCRASHREPORT_CRASH_REPORT_APP _T("xxxBugReport.exe")//你自己BugReport程序名字 #endif //CRASHFILENAMES_H

ExceptionHandler.h

#ifndef    EXCEPTIONHANDLER_H
#define EXCEPTIONHANDLER_H typedef struct _EXCEPTION_POINTERS EXCEPTION_POINTERS, *PEXCEPTION_POINTERS; int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS data, const TCHAR *Message); #endif

ExceptionHandler.cpp

#pragma warning(disable : 4514)
#pragma warning(disable : 4201) #define _WIN32_WINDOWS 0x0500 // for IsDebuggerPresent // comment out this line if you don't want minidumps
#define XCRASHREPORT_WRITE_MINIDUMP
//#define XCRASHREPORT_WRITE_ERROR_LOG // does not require MFC; use 'Not using precompiled headers' #include "windows.h"
#include <tchar.h>
#include "GetWinVer.h"
#include "miniversion.h"
#include <DbgHelp.h>
#include "CrashFileNames.h" #pragma comment(lib, "Dbghelp.lib") #ifndef _countof
#define _countof(array) (sizeof(array)/sizeof(array[0]))
#endif const int NumCodeBytes = ; // Number of code bytes to record.
const int MaxStackDump = ; // Maximum number of DWORDS in stack dumps.
const int StackColumns = ; // Number of columns in stack dump. #define ONEK 1024
#define SIXTYFOURK (64*ONEK)
#define ONEM (ONEK*ONEK)
#define ONEG (ONEK*ONEK*ONEK) ///////////////////////////////////////////////////////////////////////////////
// lstrrchr (avoid the C Runtime )
static TCHAR * lstrrchr(LPCTSTR string, int ch)
{
TCHAR *start = (TCHAR *)string; while (*string++) /* find end of string */
;
/* search towards front */
while (--string != start && *string != (TCHAR) ch)
; if (*string == (TCHAR) ch) /* char found ? */
return (TCHAR *)string; return NULL;
} #define HPRINTF_BUFFER_SIZE (8*1024) // must be at least 2048
static TCHAR hprintf_buffer[HPRINTF_BUFFER_SIZE]; // wvsprintf never prints more than one K.
static int hprintf_index = ; ///////////////////////////////////////////////////////////////////////////////
// hflush
static void hflush(HANDLE LogFile)
{
if (hprintf_index > )
{
DWORD NumBytes;
WriteFile(LogFile, hprintf_buffer, lstrlen(hprintf_buffer), &NumBytes, );
hprintf_index = ;
}
} ///////////////////////////////////////////////////////////////////////////////
// hprintf
static void hprintf(HANDLE LogFile, LPCTSTR Format, ...)
{
if (hprintf_index > (HPRINTF_BUFFER_SIZE-))
{
DWORD NumBytes;
WriteFile(LogFile, hprintf_buffer, lstrlen(hprintf_buffer), &NumBytes, );
hprintf_index = ;
} va_list arglist;
va_start( arglist, Format);
hprintf_index += wvsprintf(&hprintf_buffer[hprintf_index], Format, arglist);
va_end( arglist);
} #ifdef XCRASHREPORT_WRITE_MINIDUMP ///////////////////////////////////////////////////////////////////////////////
// DumpMiniDump
static void DumpMiniDump(HANDLE hFile, PEXCEPTION_POINTERS excpInfo)
{
if (excpInfo == NULL)
{
// Generate exception to get proper context in dump
__try
{
OutputDebugString(_T("raising exception\r\n"));
RaiseException(EXCEPTION_BREAKPOINT, , , NULL);
}
__except(DumpMiniDump(hFile, GetExceptionInformation()),
EXCEPTION_CONTINUE_EXECUTION)
{
}
}
else
{
OutputDebugString(_T("writing minidump\r\n"));
MINIDUMP_EXCEPTION_INFORMATION eInfo;
eInfo.ThreadId = GetCurrentThreadId();
eInfo.ExceptionPointers = excpInfo;
eInfo.ClientPointers = FALSE; // note: MiniDumpWithIndirectlyReferencedMemory does not work on Win98
MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MiniDumpNormal,
excpInfo ? &eInfo : NULL,
NULL,
NULL);
}
} #endif // XCRASHREPORT_WRITE_MINIDUMP ///////////////////////////////////////////////////////////////////////////////
// FormatTime
//
// Format the specified FILETIME to output in a human readable format,
// without using the C run time.
static void FormatTime(LPTSTR output, FILETIME TimeToPrint)
{
output[] = _T('\0');
WORD Date, Time;
if (FileTimeToLocalFileTime(&TimeToPrint, &TimeToPrint) &&
FileTimeToDosDateTime(&TimeToPrint, &Date, &Time))
{
wsprintf(output, _T("%d/%d/%d %02d:%02d:%02d"),
(Date / ) & , Date & , (Date / ) + ,
(Time >> ), (Time >> ) & 0x3F, (Time & 0x1F) * );
}
} ///////////////////////////////////////////////////////////////////////////////
// DumpModuleInfo
//
// Print information about a code module (DLL or EXE) such as its size,
// location, time stamp, etc.
static bool DumpModuleInfo(HANDLE LogFile, HINSTANCE ModuleHandle, int nModuleNo)
{
bool rc = false;
TCHAR szModName[MAX_PATH*];
ZeroMemory(szModName, sizeof(szModName)); __try
{
if (GetModuleFileName(ModuleHandle, szModName, sizeof(szModName)-) > )
{
// If GetModuleFileName returns greater than zero then this must
// be a valid code module address. Therefore we can try to walk
// our way through its structures to find the link time stamp.
IMAGE_DOS_HEADER *DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle;
if (IMAGE_DOS_SIGNATURE != DosHeader->e_magic)
return false; IMAGE_NT_HEADERS *NTHeader = (IMAGE_NT_HEADERS*)((TCHAR *)DosHeader
+ DosHeader->e_lfanew);
if (IMAGE_NT_SIGNATURE != NTHeader->Signature)
return false; // open the code module file so that we can get its file date and size
HANDLE ModuleFile = CreateFile(szModName, GENERIC_READ,
FILE_SHARE_READ, , OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, ); TCHAR TimeBuffer[];
TimeBuffer[] = _T('\0'); DWORD FileSize = ;
if (ModuleFile != INVALID_HANDLE_VALUE)
{
FileSize = GetFileSize(ModuleFile, );
FILETIME LastWriteTime;
if (GetFileTime(ModuleFile, , , &LastWriteTime))
{
FormatTime(TimeBuffer, LastWriteTime);
}
CloseHandle(ModuleFile);
}
hprintf(LogFile, _T("Module %d\r\n"), nModuleNo);
hprintf(LogFile, _T("%s\r\n"), szModName);
hprintf(LogFile, _T("Image Base: 0x%08x Image Size: 0x%08x\r\n"),
NTHeader->OptionalHeader.ImageBase,
NTHeader->OptionalHeader.SizeOfImage), hprintf(LogFile, _T("Checksum: 0x%08x Time Stamp: 0x%08x\r\n"),
NTHeader->OptionalHeader.CheckSum,
NTHeader->FileHeader.TimeDateStamp); hprintf(LogFile, _T("File Size: %-10d File Time: %s\r\n"),
FileSize, TimeBuffer); hprintf(LogFile, _T("Version Information:\r\n")); CMiniVersion ver(szModName);
TCHAR szBuf[];
WORD dwBuf[]; ver.GetCompanyName(szBuf, sizeof(szBuf)-);
hprintf(LogFile, _T(" Company: %s\r\n"), szBuf); ver.GetProductName(szBuf, sizeof(szBuf)-);
hprintf(LogFile, _T(" Product: %s\r\n"), szBuf); ver.GetFileDescription(szBuf, sizeof(szBuf)-);
hprintf(LogFile, _T(" FileDesc: %s\r\n"), szBuf); ver.GetFileVersion(dwBuf);
hprintf(LogFile, _T(" FileVer: %d.%d.%d.%d\r\n"),
dwBuf[], dwBuf[], dwBuf[], dwBuf[]); ver.GetProductVersion(dwBuf);
hprintf(LogFile, _T(" ProdVer: %d.%d.%d.%d\r\n"),
dwBuf[], dwBuf[], dwBuf[], dwBuf[]); ver.Release(); hprintf(LogFile, _T("\r\n")); rc = true;
}
}
// Handle any exceptions by continuing from this point.
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return rc;
} ///////////////////////////////////////////////////////////////////////////////
// DumpModuleList
//
// Scan memory looking for code modules (DLLs or EXEs). VirtualQuery is used
// to find all the blocks of address space that were reserved or committed,
// and ShowModuleInfo will display module information if they are code
// modules.
static void DumpModuleList(HANDLE LogFile)
{
SYSTEM_INFO SystemInfo;
GetSystemInfo(&SystemInfo); const size_t PageSize = SystemInfo.dwPageSize; // Set NumPages to the number of pages in the 4GByte address space,
// while being careful to avoid overflowing ints
const size_t NumPages = * size_t(ONEG / PageSize);
size_t pageNum = ;
void *LastAllocationBase = ; int nModuleNo = ; while (pageNum < NumPages)
{
MEMORY_BASIC_INFORMATION MemInfo;
if (VirtualQuery((void *)(pageNum * PageSize), &MemInfo,
sizeof(MemInfo)))
{
if (MemInfo.RegionSize > )
{
// Adjust the page number to skip over this block of memory
pageNum += MemInfo.RegionSize / PageSize;
if (MemInfo.State == MEM_COMMIT && MemInfo.AllocationBase >
LastAllocationBase)
{
// Look for new blocks of committed memory, and try
// recording their module names - this will fail
// gracefully if they aren't code modules
LastAllocationBase = MemInfo.AllocationBase;
if (DumpModuleInfo(LogFile,
(HINSTANCE)LastAllocationBase,
nModuleNo))
{
nModuleNo++;
}
}
}
else
pageNum += SIXTYFOURK / PageSize;
}
else
pageNum += SIXTYFOURK / PageSize; // If VirtualQuery fails we advance by 64K because that is the
// granularity of address space doled out by VirtualAlloc()
}
} ///////////////////////////////////////////////////////////////////////////////
// DumpSystemInformation
//
// Record information about the user's system, such as processor type, amount
// of memory, etc.
static void DumpSystemInformation(HANDLE LogFile)
{
FILETIME CurrentTime;
GetSystemTimeAsFileTime(&CurrentTime);
TCHAR szTimeBuffer[];
FormatTime(szTimeBuffer, CurrentTime); hprintf(LogFile, _T("Error occurred at %s.\r\n"), szTimeBuffer); TCHAR szModuleName[MAX_PATH*];
ZeroMemory(szModuleName, sizeof(szModuleName));
if (GetModuleFileName(, szModuleName, _countof(szModuleName)-) <= )
lstrcpy(szModuleName, _T("Unknown")); TCHAR szUserName[];
ZeroMemory(szUserName, sizeof(szUserName));
DWORD UserNameSize = _countof(szUserName)-;
if (!GetUserName(szUserName, &UserNameSize))
lstrcpy(szUserName, _T("Unknown")); hprintf(LogFile, _T("%s, run by %s.\r\n"), szModuleName, szUserName); // print out operating system
TCHAR szWinVer[], szMajorMinorBuild[];
int nWinVer;
GetWinVer(szWinVer, &nWinVer, szMajorMinorBuild);
hprintf(LogFile, _T("Operating system: %s (%s).\r\n"),
szWinVer, szMajorMinorBuild); SYSTEM_INFO SystemInfo;
GetSystemInfo(&SystemInfo);
hprintf(LogFile, _T("%d processor(s), type %d.\r\n"),
SystemInfo.dwNumberOfProcessors, SystemInfo.dwProcessorType); MEMORYSTATUS MemInfo;
MemInfo.dwLength = sizeof(MemInfo);
GlobalMemoryStatus(&MemInfo); // Print out info on memory, rounded up.
hprintf(LogFile, _T("%d%% memory in use.\r\n"), MemInfo.dwMemoryLoad);
hprintf(LogFile, _T("%d MBytes physical memory.\r\n"), (MemInfo.dwTotalPhys +
ONEM - ) / ONEM);
hprintf(LogFile, _T("%d MBytes physical memory free.\r\n"),
(MemInfo.dwAvailPhys + ONEM - ) / ONEM);
hprintf(LogFile, _T("%d MBytes paging file.\r\n"), (MemInfo.dwTotalPageFile +
ONEM - ) / ONEM);
hprintf(LogFile, _T("%d MBytes paging file free.\r\n"),
(MemInfo.dwAvailPageFile + ONEM - ) / ONEM);
hprintf(LogFile, _T("%d MBytes user address space.\r\n"),
(MemInfo.dwTotalVirtual + ONEM - ) / ONEM);
hprintf(LogFile, _T("%d MBytes user address space free.\r\n"),
(MemInfo.dwAvailVirtual + ONEM - ) / ONEM);
} ///////////////////////////////////////////////////////////////////////////////
// GetExceptionDescription
//
// Translate the exception code into something human readable
static const TCHAR *GetExceptionDescription(DWORD ExceptionCode)
{
struct ExceptionNames
{
DWORD ExceptionCode;
TCHAR * ExceptionName;
}; #if 0 // from winnt.h
#define STATUS_WAIT_0 ((DWORD )0x00000000L)
#define STATUS_ABANDONED_WAIT_0 ((DWORD )0x00000080L)
#define STATUS_USER_APC ((DWORD )0x000000C0L)
#define STATUS_TIMEOUT ((DWORD )0x00000102L)
#define STATUS_PENDING ((DWORD )0x00000103L)
#define STATUS_SEGMENT_NOTIFICATION ((DWORD )0x40000005L)
#define STATUS_GUARD_PAGE_VIOLATION ((DWORD )0x80000001L)
#define STATUS_DATATYPE_MISALIGNMENT ((DWORD )0x80000002L)
#define STATUS_BREAKPOINT ((DWORD )0x80000003L)
#define STATUS_SINGLE_STEP ((DWORD )0x80000004L)
#define STATUS_ACCESS_VIOLATION ((DWORD )0xC0000005L)
#define STATUS_IN_PAGE_ERROR ((DWORD )0xC0000006L)
#define STATUS_INVALID_HANDLE ((DWORD )0xC0000008L)
#define STATUS_NO_MEMORY ((DWORD )0xC0000017L)
#define STATUS_ILLEGAL_INSTRUCTION ((DWORD )0xC000001DL)
#define STATUS_NONCONTINUABLE_EXCEPTION ((DWORD )0xC0000025L)
#define STATUS_INVALID_DISPOSITION ((DWORD )0xC0000026L)
#define STATUS_ARRAY_BOUNDS_EXCEEDED ((DWORD )0xC000008CL)
#define STATUS_FLOAT_DENORMAL_OPERAND ((DWORD )0xC000008DL)
#define STATUS_FLOAT_DIVIDE_BY_ZERO ((DWORD )0xC000008EL)
#define STATUS_FLOAT_INEXACT_RESULT ((DWORD )0xC000008FL)
#define STATUS_FLOAT_INVALID_OPERATION ((DWORD )0xC0000090L)
#define STATUS_FLOAT_OVERFLOW ((DWORD )0xC0000091L)
#define STATUS_FLOAT_STACK_CHECK ((DWORD )0xC0000092L)
#define STATUS_FLOAT_UNDERFLOW ((DWORD )0xC0000093L)
#define STATUS_INTEGER_DIVIDE_BY_ZERO ((DWORD )0xC0000094L)
#define STATUS_INTEGER_OVERFLOW ((DWORD )0xC0000095L)
#define STATUS_PRIVILEGED_INSTRUCTION ((DWORD )0xC0000096L)
#define STATUS_STACK_OVERFLOW ((DWORD )0xC00000FDL)
#define STATUS_CONTROL_C_EXIT ((DWORD )0xC000013AL)
#define STATUS_FLOAT_MULTIPLE_FAULTS ((DWORD )0xC00002B4L)
#define STATUS_FLOAT_MULTIPLE_TRAPS ((DWORD )0xC00002B5L)
#define STATUS_ILLEGAL_VLM_REFERENCE ((DWORD )0xC00002C0L)
#endif ExceptionNames ExceptionMap[] =
{
{0x40010005, _T("a Control-C")},
{0x40010008, _T("a Control-Break")},
{0x80000002, _T("a Datatype Misalignment")},
{0x80000003, _T("a Breakpoint")},
{0xc0000005, _T("an Access Violation")},
{0xc0000006, _T("an In Page Error")},
{0xc0000017, _T("a No Memory")},
{0xc000001d, _T("an Illegal Instruction")},
{0xc0000025, _T("a Noncontinuable Exception")},
{0xc0000026, _T("an Invalid Disposition")},
{0xc000008c, _T("a Array Bounds Exceeded")},
{0xc000008d, _T("a Float Denormal Operand")},
{0xc000008e, _T("a Float Divide by Zero")},
{0xc000008f, _T("a Float Inexact Result")},
{0xc0000090, _T("a Float Invalid Operation")},
{0xc0000091, _T("a Float Overflow")},
{0xc0000092, _T("a Float Stack Check")},
{0xc0000093, _T("a Float Underflow")},
{0xc0000094, _T("an Integer Divide by Zero")},
{0xc0000095, _T("an Integer Overflow")},
{0xc0000096, _T("a Privileged Instruction")},
{0xc00000fD, _T("a Stack Overflow")},
{0xc0000142, _T("a DLL Initialization Failed")},
{0xe06d7363, _T("a Microsoft C++ Exception")},
}; for (int i = ; i < sizeof(ExceptionMap) / sizeof(ExceptionMap[]); i++)
if (ExceptionCode == ExceptionMap[i].ExceptionCode)
return ExceptionMap[i].ExceptionName; return _T("an Unknown exception type");
} ///////////////////////////////////////////////////////////////////////////////
// GetFilePart
static TCHAR * GetFilePart(LPCTSTR source)
{
TCHAR *result = lstrrchr(source, _T('\\'));
if (result)
result++;
else
result = (TCHAR *)source;
return result;
} ///////////////////////////////////////////////////////////////////////////////
// DumpStack
static void DumpStack(HANDLE LogFile, DWORD *pStack)
{
hprintf(LogFile, _T("\r\n\r\nStack:\r\n")); __try
{
// Esp contains the bottom of the stack, or at least the bottom of
// the currently used area.
DWORD* pStackTop; __asm
{
// Load the top (highest address) of the stack from the
// thread information block. It will be found there in
// Win9x and Windows NT.
mov eax, fs:[]
mov pStackTop, eax
} if (pStackTop > pStack + MaxStackDump)
pStackTop = pStack + MaxStackDump; int Count = ; DWORD* pStackStart = pStack; int nDwordsPrinted = ; while (pStack + <= pStackTop)
{
if ((Count % StackColumns) == )
{
pStackStart = pStack;
nDwordsPrinted = ;
hprintf(LogFile, _T("0x%08x: "), pStack);
} if ((++Count % StackColumns) == || pStack + > pStackTop)
{
hprintf(LogFile, _T("%08x "), *pStack);
nDwordsPrinted++; int n = nDwordsPrinted;
while (n < )
{
hprintf(LogFile, _T(" "));
n++;
} for (int i = ; i < nDwordsPrinted; i++)
{
DWORD dwStack = *pStackStart;
for (int j = ; j < ; j++)
{
char c = (char)(dwStack & 0xFF);
if (c < 0x20 || c > 0x7E)
c = '.';
#ifdef _UNICODE
WCHAR w = (WCHAR)c;
hprintf(LogFile, _T("%c"), w);
#else
hprintf(LogFile, _T("%c"), c);
#endif
dwStack = dwStack >> ;
}
pStackStart++;
} hprintf(LogFile, _T("\r\n"));
}
else
{
hprintf(LogFile, _T("%08x "), *pStack);
nDwordsPrinted++;
}
pStack++;
}
hprintf(LogFile, _T("\r\n"));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
hprintf(LogFile, _T("Exception encountered during stack dump.\r\n"));
}
} ///////////////////////////////////////////////////////////////////////////////
// DumpRegisters
static void DumpRegisters(HANDLE LogFile, PCONTEXT Context)
{
// Print out the register values in an XP error window compatible format.
hprintf(LogFile, _T("\r\n"));
hprintf(LogFile, _T("Context:\r\n"));
hprintf(LogFile, _T("EDI: 0x%08x ESI: 0x%08x EAX: 0x%08x\r\n"),
Context->Edi, Context->Esi, Context->Eax);
hprintf(LogFile, _T("EBX: 0x%08x ECX: 0x%08x EDX: 0x%08x\r\n"),
Context->Ebx, Context->Ecx, Context->Edx);
hprintf(LogFile, _T("EIP: 0x%08x EBP: 0x%08x SegCs: 0x%08x\r\n"),
Context->Eip, Context->Ebp, Context->SegCs);
hprintf(LogFile, _T("EFlags: 0x%08x ESP: 0x%08x SegSs: 0x%08x\r\n"),
Context->EFlags, Context->Esp, Context->SegSs);
} ///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// RecordExceptionInfo
//
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS pExceptPtrs,
LPCTSTR lpszMessage)
{
static bool bFirstTime = true;
if (!bFirstTime) // Going recursive! That must mean this routine crashed!
return EXCEPTION_CONTINUE_SEARCH;
bFirstTime = false; // Create a filename to record the error information to.
// Storing it in the executable directory works well. TCHAR szModuleName[MAX_PATH*];
ZeroMemory(szModuleName, sizeof(szModuleName));
if (GetModuleFileName(, szModuleName, _countof(szModuleName)-) <= )
lstrcpy(szModuleName, _T("Unknown")); TCHAR *pszFilePart = GetFilePart(szModuleName); // Extract the file name portion and remove it's file extension
TCHAR szFileName[MAX_PATH*];
lstrcpy(szFileName, pszFilePart);
TCHAR *lastperiod = lstrrchr(szFileName, _T('.'));
if (lastperiod)
lastperiod[] = ; #ifdef XCRASHREPORT_WRITE_ERROR_LOG
// Replace the executable filename with our error log file name
lstrcpy(pszFilePart, XCRASHREPORT_ERROR_LOG_FILE); HANDLE hLogFile = CreateFile(szModuleName, GENERIC_WRITE, , ,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, ); if (hLogFile == INVALID_HANDLE_VALUE)
{
OutputDebugString(_T("Error creating exception report\r\n"));
return EXCEPTION_CONTINUE_SEARCH;
} // Append to the error log
SetFilePointer(hLogFile, , , FILE_END); // Print out a blank line to separate this error log from any previous ones
//hprintf(hLogFile, _T("\r\n")); PEXCEPTION_RECORD Exception = pExceptPtrs->ExceptionRecord;
PCONTEXT Context = pExceptPtrs->ContextRecord; TCHAR szCrashModulePathName[MAX_PATH*];
ZeroMemory(szCrashModulePathName, sizeof(szCrashModulePathName)); TCHAR *pszCrashModuleFileName = _T("Unknown"); MEMORY_BASIC_INFORMATION MemInfo; // VirtualQuery can be used to get the allocation base associated with a
// code address, which is the same as the ModuleHandle. This can be used
// to get the filename of the module that the crash happened in.
if (VirtualQuery((void*)Context->Eip, &MemInfo, sizeof(MemInfo)) &&
(GetModuleFileName((HINSTANCE)MemInfo.AllocationBase,
szCrashModulePathName,
sizeof(szCrashModulePathName)-) > ))
{
pszCrashModuleFileName = GetFilePart(szCrashModulePathName);
} // Print out the beginning of the error log in a Win95 error window
// compatible format.
hprintf(hLogFile, _T("%s caused %s (0x%08x) \r\nin module %s at %04x:%08x.\r\n\r\n"),
szFileName, GetExceptionDescription(Exception->ExceptionCode),
Exception->ExceptionCode,
pszCrashModuleFileName, Context->SegCs, Context->Eip); hprintf(hLogFile, _T("Exception handler called in %s.\r\n"), lpszMessage); DumpSystemInformation(hLogFile); // If the exception was an access violation, print out some additional
// information, to the error log and the debugger.
if (Exception->ExceptionCode == STATUS_ACCESS_VIOLATION &&
Exception->NumberParameters >= )
{
TCHAR szDebugMessage[];
const TCHAR* readwrite = _T("Read from");
if (Exception->ExceptionInformation[])
readwrite = _T("Write to");
wsprintf(szDebugMessage, _T("%s location %08x caused an access violation.\r\n"),
readwrite, Exception->ExceptionInformation[]); #ifdef _DEBUG
// The Visual C++ debugger doesn't actually tell you whether a read
// or a write caused the access violation, nor does it tell what
// address was being read or written. So I fixed that.
OutputDebugString(_T("Exception handler: "));
OutputDebugString(szDebugMessage);
#endif hprintf(hLogFile, _T("%s"), szDebugMessage);
} DumpRegisters(hLogFile, Context); // Print out the bytes of code at the instruction pointer. Since the
// crash may have been caused by an instruction pointer that was bad,
// this code needs to be wrapped in an exception handler, in case there
// is no memory to read. If the dereferencing of code[] fails, the
// exception handler will print '??'.
hprintf(hLogFile, _T("\r\nBytes at CS:EIP:\r\n"));
BYTE * code = (BYTE *)Context->Eip;
for (int codebyte = ; codebyte < NumCodeBytes; codebyte++)
{
__try
{
hprintf(hLogFile, _T("%02x "), code[codebyte]); }
__except(EXCEPTION_EXECUTE_HANDLER)
{
hprintf(hLogFile, _T("?? "));
}
} // Time to print part or all of the stack to the error log. This allows
// us to figure out the call stack, parameters, local variables, etc. // Esp contains the bottom of the stack, or at least the bottom of
// the currently used area
DWORD* pStack = (DWORD *)Context->Esp; DumpStack(hLogFile, pStack); DumpModuleList(hLogFile); hprintf(hLogFile, _T("\r\n===== [end of %s] =====\r\n"),
XCRASHREPORT_ERROR_LOG_FILE);
hflush(hLogFile);
CloseHandle(hLogFile);
#endif //XCRASHREPORT_WRITE_ERROR_LOG ///////////////////////////////////////////////////////////////////////////
//
// write minidump
//
/////////////////////////////////////////////////////////////////////////// #ifdef XCRASHREPORT_WRITE_MINIDUMP // Replace the filename with our minidump file name
lstrcpy(pszFilePart, XCRASHREPORT_MINI_DUMP_FILE); // Create the file
HANDLE hMiniDumpFile = CreateFile(
szModuleName,
GENERIC_WRITE,
,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
NULL); // Write the minidump to the file
if (hMiniDumpFile != INVALID_HANDLE_VALUE)
{
DumpMiniDump(hMiniDumpFile, pExceptPtrs); // Close file
CloseHandle(hMiniDumpFile);
} #endif // XCRASHREPORT_WRITE_MINIDUMP if (IsDebuggerPresent())
{
// let the debugger catch this -
// return the magic value which tells Win32 that this handler didn't
// actually handle the exception - so that things will proceed as per
// normal.
return EXCEPTION_CONTINUE_SEARCH;
}
else
{
///////////////////////////////////////////////////////////////////////
//
// pop up our crash report app
//
/////////////////////////////////////////////////////////////////////// // Replace the filename with our crash report exe file name
lstrcpy(pszFilePart, XCRASHREPORT_CRASH_REPORT_APP); TCHAR szCommandLine[MAX_PATH];
lstrcpy(szCommandLine, szModuleName); lstrcat(szCommandLine, _T(" \"")); // surround app name with quotes
ZeroMemory(szModuleName, sizeof(szModuleName));
GetModuleFileName(, szModuleName, _countof(szModuleName)-);
lstrcat(szCommandLine, GetFilePart(szModuleName));
lstrcat(szCommandLine, _T("\""));
//MessageBox(NULL,szCommandLine,L"",MB_OK); STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW; PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi)); if (CreateProcess(
NULL, // name of executable module
szCommandLine, // command line string
NULL, // process attributes
NULL, // thread attributes
FALSE, // handle inheritance option
, // creation flags
NULL, // new environment block
NULL, // current directory name
&si, // startup information
&pi)) // process information
{
// XCrashReport.exe was successfully started, so
// suppress the standard crash dialog
return EXCEPTION_EXECUTE_HANDLER;
}
else
{
// XCrashReport.exe was not started - let
// the standard crash dialog appear
return EXCEPTION_CONTINUE_SEARCH;
}
}
}

GetWinVer.h

#ifndef GETWINVER_H
#define GETWINVER_H #define WUNKNOWNSTR _T("unknown Windows version") #define W95STR _T("Windows 95")
#define W95SP1STR _T("Windows 95 SP1")
#define W95OSR2STR _T("Windows 95 OSR2")
#define W98STR _T("Windows 98")
#define W98SP1STR _T("Windows 98 SP1")
#define W98SESTR _T("Windows 98 SE")
#define WMESTR _T("Windows ME") #define WNT351STR _T("Windows NT 3.51")
#define WNT4STR _T("Windows NT 4")
#define W2KSTR _T("Windows 2000")
#define WXPSTR _T("Windows XP")
#define W2003SERVERSTR _T("Windows 2003 Server") #define WCESTR _T("Windows CE") #define WUNKNOWN 0 #define W9XFIRST 1
#define W95 1
#define W95SP1 2
#define W95OSR2 3
#define W98 4
#define W98SP1 5
#define W98SE 6
#define WME 7
#define W9XLAST 99 #define WNTFIRST 101
#define WNT351 101
#define WNT4 102
#define W2K 103
#define WXP 104
#define W2003SERVER 105
#define WNTLAST 199 #define WCEFIRST 201
#define WCE 201
#define WCELAST 299 BOOL GetWinVer(LPTSTR pszVersion, int *nVersion, LPTSTR pszMajorMinorBuild); #endif //GETWINVER_H

GetWinVer.cpp

#include "stdafx.h"
#include "tchar.h"
#include "GetWinVer.h" #pragma warning(disable : 4996)
// from winbase.h
#ifndef VER_PLATFORM_WIN32s
#define VER_PLATFORM_WIN32s 0
#endif
#ifndef VER_PLATFORM_WIN32_WINDOWS
#define VER_PLATFORM_WIN32_WINDOWS 1
#endif
#ifndef VER_PLATFORM_WIN32_NT
#define VER_PLATFORM_WIN32_NT 2
#endif
#ifndef VER_PLATFORM_WIN32_CE
#define VER_PLATFORM_WIN32_CE 3
#endif // GetWinVer
BOOL GetWinVer(LPTSTR pszVersion, int *nVersion, LPTSTR pszMajorMinorBuild)
{
if (!pszVersion || !nVersion || !pszMajorMinorBuild)
return FALSE;
lstrcpy(pszVersion, WUNKNOWNSTR);
*nVersion = WUNKNOWN; OSVERSIONINFO osinfo;
osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (!GetVersionEx(&osinfo))
return FALSE; DWORD dwPlatformId = osinfo.dwPlatformId;
DWORD dwMinorVersion = osinfo.dwMinorVersion;
DWORD dwMajorVersion = osinfo.dwMajorVersion;
DWORD dwBuildNumber = osinfo.dwBuildNumber & 0xFFFF; // Win 95 needs this wsprintf(pszMajorMinorBuild, _T("%u.%u.%u"), dwMajorVersion, dwMinorVersion, dwBuildNumber); if ((dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) && (dwMajorVersion == ))
{
if ((dwMinorVersion < ) && (dwBuildNumber == ))
{
lstrcpy(pszVersion, W95STR);
*nVersion = W95;
}
else if ((dwMinorVersion < ) &&
((dwBuildNumber > ) && (dwBuildNumber <= )))
{
lstrcpy(pszVersion, W95SP1STR);
*nVersion = W95SP1;
}
else if ((dwMinorVersion < ) && (dwBuildNumber > ))
{
lstrcpy(pszVersion, W95OSR2STR);
*nVersion = W95OSR2;
}
else if ((dwMinorVersion == ) && (dwBuildNumber == ))
{
lstrcpy(pszVersion, W98STR);
*nVersion = W98;
}
else if ((dwMinorVersion == ) &&
((dwBuildNumber > ) && (dwBuildNumber < )))
{
lstrcpy(pszVersion, W98SP1STR);
*nVersion = W98SP1;
}
else if ((dwMinorVersion == ) && (dwBuildNumber >= ))
{
lstrcpy(pszVersion, W98SESTR);
*nVersion = W98SE;
}
else if (dwMinorVersion == )
{
lstrcpy(pszVersion, WMESTR);
*nVersion = WME;
}
}
else if (dwPlatformId == VER_PLATFORM_WIN32_NT)
{
if ((dwMajorVersion == ) && (dwMinorVersion == ))
{
lstrcpy(pszVersion, WNT351STR);
*nVersion = WNT351;
}
else if ((dwMajorVersion == ) && (dwMinorVersion == ))
{
lstrcpy(pszVersion, WNT4STR);
*nVersion = WNT4;
}
else if ((dwMajorVersion == ) && (dwMinorVersion == ))
{
lstrcpy(pszVersion, W2KSTR);
*nVersion = W2K;
}
else if ((dwMajorVersion == ) && (dwMinorVersion == ))
{
lstrcpy(pszVersion, WXPSTR);
*nVersion = WXP;
}
else if ((dwMajorVersion == ) && (dwMinorVersion == ))
{
lstrcpy(pszVersion, W2003SERVERSTR);
*nVersion = W2003SERVER;
}
}
else if (dwPlatformId == VER_PLATFORM_WIN32_CE)
{
lstrcpy(pszVersion, WCESTR);
*nVersion = WCE;
}
return TRUE;
}

MiniVersion.h

#ifndef MINIVERSION_H
#define MINIVERSION_H class CMiniVersion
{
// constructors
public:
CMiniVersion(LPCTSTR lpszPath = NULL);
BOOL Init();
void Release(); // operations
public: // attributes
public:
// fixed info
BOOL GetFileVersion(WORD *pwVersion);
BOOL GetProductVersion(WORD* pwVersion);
BOOL GetFileFlags(DWORD& rdwFlags);
BOOL GetFileOS(DWORD& rdwOS);
BOOL GetFileType(DWORD& rdwType);
BOOL GetFileSubtype(DWORD& rdwType); // string info
BOOL GetCompanyName(LPTSTR lpszCompanyName, int nSize);
BOOL GetFileDescription(LPTSTR lpszFileDescription, int nSize);
BOOL GetProductName(LPTSTR lpszProductName, int nSize); // implementation
protected:
BOOL GetFixedInfo(VS_FIXEDFILEINFO& rFixedInfo);
BOOL GetStringInfo(LPCTSTR lpszKey, LPTSTR lpszValue); BYTE* m_pData;
DWORD m_dwHandle;
WORD m_wFileVersion[];
WORD m_wProductVersion[];
DWORD m_dwFileFlags;
DWORD m_dwFileOS;
DWORD m_dwFileType;
DWORD m_dwFileSubtype; TCHAR m_szPath[MAX_PATH*];
TCHAR m_szCompanyName[MAX_PATH*];
TCHAR m_szProductName[MAX_PATH*];
TCHAR m_szFileDescription[MAX_PATH*];
}; #endif

MiniVersion.cpp

#include "stdafx.h"
#include "MiniVersion.h" #pragma message("automatic link to VERSION.LIB")
#pragma comment(lib, "version.lib") ///////////////////////////////////////////////////////////////////////////////
// ctor
CMiniVersion::CMiniVersion(LPCTSTR lpszPath)
{
ZeroMemory(m_szPath, sizeof(m_szPath)); if (lpszPath && lpszPath[] != )
{
lstrcpyn(m_szPath, lpszPath, sizeof(m_szPath)-);
}
else
{
} m_pData = NULL;
m_dwHandle = ; for (int i = ; i < ; i++)
{
m_wFileVersion[i] = ;
m_wProductVersion[i] = ;
} m_dwFileFlags = ;
m_dwFileOS = ;
m_dwFileType = ;
m_dwFileSubtype = ; ZeroMemory(m_szCompanyName, sizeof(m_szCompanyName));
ZeroMemory(m_szProductName, sizeof(m_szProductName));
ZeroMemory(m_szFileDescription, sizeof(m_szFileDescription)); Init();
} ///////////////////////////////////////////////////////////////////////////////
// Init
BOOL CMiniVersion::Init()
{
DWORD dwHandle;
DWORD dwSize;
BOOL rc; dwSize = ::GetFileVersionInfoSize(m_szPath, &dwHandle);
if (dwSize == )
return FALSE; m_pData = new BYTE [dwSize + ];
ZeroMemory(m_pData, dwSize+); rc = ::GetFileVersionInfo(m_szPath, dwHandle, dwSize, m_pData);
if (!rc)
return FALSE; // get fixed info VS_FIXEDFILEINFO FixedInfo; if (GetFixedInfo(FixedInfo))
{
m_wFileVersion[] = HIWORD(FixedInfo.dwFileVersionMS);
m_wFileVersion[] = LOWORD(FixedInfo.dwFileVersionMS);
m_wFileVersion[] = HIWORD(FixedInfo.dwFileVersionLS);
m_wFileVersion[] = LOWORD(FixedInfo.dwFileVersionLS); m_wProductVersion[] = HIWORD(FixedInfo.dwProductVersionMS);
m_wProductVersion[] = LOWORD(FixedInfo.dwProductVersionMS);
m_wProductVersion[] = HIWORD(FixedInfo.dwProductVersionLS);
m_wProductVersion[] = LOWORD(FixedInfo.dwProductVersionLS); m_dwFileFlags = FixedInfo.dwFileFlags;
m_dwFileOS = FixedInfo.dwFileOS;
m_dwFileType = FixedInfo.dwFileType;
m_dwFileSubtype = FixedInfo.dwFileSubtype;
}
else
return FALSE; // get string info GetStringInfo(_T("CompanyName"), m_szCompanyName);
GetStringInfo(_T("FileDescription"), m_szFileDescription);
GetStringInfo(_T("ProductName"), m_szProductName); return TRUE;
} ///////////////////////////////////////////////////////////////////////////////
// Release
void CMiniVersion::Release()
{
// do this manually, because we can't use objects requiring
// a dtor within an exception handler
if (m_pData)
delete [] m_pData;
m_pData = NULL;
} ///////////////////////////////////////////////////////////////////////////////
// GetFileVersion
BOOL CMiniVersion::GetFileVersion(WORD * pwVersion)
{
for (int i = ; i < ; i++)
*pwVersion++ = m_wFileVersion[i];
return TRUE;
} ///////////////////////////////////////////////////////////////////////////////
// GetProductVersion
BOOL CMiniVersion::GetProductVersion(WORD * pwVersion)
{
for (int i = ; i < ; i++)
*pwVersion++ = m_wProductVersion[i];
return TRUE;
} ///////////////////////////////////////////////////////////////////////////////
// GetFileFlags
BOOL CMiniVersion::GetFileFlags(DWORD& rdwFlags)
{
rdwFlags = m_dwFileFlags;
return TRUE;
} ///////////////////////////////////////////////////////////////////////////////
// GetFileOS
BOOL CMiniVersion::GetFileOS(DWORD& rdwOS)
{
rdwOS = m_dwFileOS;
return TRUE;
} ///////////////////////////////////////////////////////////////////////////////
// GetFileType
BOOL CMiniVersion::GetFileType(DWORD& rdwType)
{
rdwType = m_dwFileType;
return TRUE;
} ///////////////////////////////////////////////////////////////////////////////
// GetFileSubtype
BOOL CMiniVersion::GetFileSubtype(DWORD& rdwType)
{
rdwType = m_dwFileSubtype;
return TRUE;
} ///////////////////////////////////////////////////////////////////////////////
// GetCompanyName
BOOL CMiniVersion::GetCompanyName(LPTSTR lpszCompanyName, int nSize)
{
if (!lpszCompanyName)
return FALSE;
ZeroMemory(lpszCompanyName, nSize);
lstrcpyn(lpszCompanyName, m_szCompanyName, nSize-);
return TRUE;
} ///////////////////////////////////////////////////////////////////////////////
// GetFileDescription
BOOL CMiniVersion::GetFileDescription(LPTSTR lpszFileDescription, int nSize)
{
if (!lpszFileDescription)
return FALSE;
ZeroMemory(lpszFileDescription, nSize);
lstrcpyn(lpszFileDescription, m_szFileDescription, nSize-);
return TRUE;
} ///////////////////////////////////////////////////////////////////////////////
// GetProductName
BOOL CMiniVersion::GetProductName(LPTSTR lpszProductName, int nSize)
{
if (!lpszProductName)
return FALSE;
ZeroMemory(lpszProductName, nSize);
lstrcpyn(lpszProductName, m_szProductName, nSize-);
return TRUE;
} ///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// protected methods
//
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// GetFixedInfo
BOOL CMiniVersion::GetFixedInfo(VS_FIXEDFILEINFO& rFixedInfo)
{
BOOL rc;
UINT nLength;
VS_FIXEDFILEINFO *pFixedInfo = NULL; if (!m_pData)
return FALSE; if (m_pData)
rc = ::VerQueryValue(m_pData, _T("\\"), (void **) &pFixedInfo, &nLength);
else
rc = FALSE; if (rc)
memcpy (&rFixedInfo, pFixedInfo, sizeof (VS_FIXEDFILEINFO)); return rc;
} ///////////////////////////////////////////////////////////////////////////////
// GetStringInfo
BOOL CMiniVersion::GetStringInfo(LPCTSTR lpszKey, LPTSTR lpszReturnValue)
{
BOOL rc;
DWORD *pdwTranslation;
UINT nLength;
LPTSTR lpszValue; if (m_pData == NULL)
return FALSE; if (!lpszReturnValue)
return FALSE; if (!lpszKey)
return FALSE; *lpszReturnValue = ; rc = ::VerQueryValue(m_pData, _T("\\VarFileInfo\\Translation"),
(void**) &pdwTranslation, &nLength);
if (!rc)
return FALSE; TCHAR szKey[];
wsprintf(szKey, _T("\\StringFileInfo\\%04x%04x\\%s"),
LOWORD (*pdwTranslation), HIWORD (*pdwTranslation),
lpszKey); rc = ::VerQueryValue(m_pData, szKey, (void**) &lpszValue, &nLength); if (!rc)
return FALSE; lstrcpy(lpszReturnValue, lpszValue); return TRUE;
}

第二步:在main函数处加入try catch 捕获异常

// Duilib_Login.cpp : 定义应用程序的入口点。
//
#include "CefBrowserApp.h"
#include "MainFrameWnd.h"
#include "ExceptionHandler.h" //#define CEF_USE_SANDBOX 560 int Mymain(HINSTANCE hInstance)
{
CPaintManagerUI::SetInstance(hInstance);
CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath()); HRESULT Hr = ::CoInitialize(NULL);
if (FAILED(Hr)) return ; /***************************************begin初始化cef*******************************************/ void* sandbox_info = NULL;
#if defined(CEF_USE_SANDBOX)
CefScopedSandboxInfo scoped_sandbox;
sandbox_info = scoped_sandbox.sandbox_info();
#endif CefMainArgs main_args(hInstance);
CefRefPtr<CCefBrowserApp> spApp(new CCefBrowserApp); // Execute the secondary process, if any.
int exit_code = CefExecuteProcess(main_args, spApp.get(), sandbox_info);
if (exit_code >= )
return exit_code;
CefRefPtr<CefCommandLine> command_line;
command_line = CefCommandLine::CreateCommandLine();
command_line->AppendSwitch("no-proxy-server");//加载慢,关闭代理试试 //command_line->AppendSwitch("--disable-web-security");//关闭同源策略
//command_line->AppendSwitchWithValue("ppapi-flash-version", "28.0.0.137");//PepperFlash\manifest.json中的version
//command_line->AppendSwitchWithValue("ppapi-flash-path", "PepperFlash\\pepflashplayer.dll"); CefSettings cSettings;
const char* loc = "zh-CN"; cSettings.no_sandbox = true;
cSettings.multi_threaded_message_loop = true;
//cSettings.single_process = false;
cSettings.log_severity = LOGSEVERITY_DISABLE;//设置日志级别,解决安装启动佰卓数安后桌面出现一个debug.log文件(调试阶段可以去掉)
CefString(&cSettings.locale).FromASCII(loc);
cef_string_from_ascii(loc, strlen(loc), &cSettings.locale); // Execute the secondary process, if any.
CefInitialize(main_args, cSettings, spApp.get(), sandbox_info);
/***************************************结束初始化cef*******************************************/ CMainFrameWnd Main;
Main.Create(NULL, _T("MainFrameWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE | WS_EX_ACCEPTFILES);
Main.CenterWindow();
Main.ShowModal(); //if (!cSettings.multi_threaded_message_loop) {
// // Run the CEF message loop. This function will block until the application
// // recieves a WM_QUIT message.
// CefRunMessageLoop();
//}
//else {
// DuiLib::CPaintManagerUI::MessageLoop();
//} //CefShutdown(); ::CoUninitialize(); return ;
} int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow)
{
__try
{
Mymain(hInstance);
}
__except (RecordExceptionInfo(GetExceptionInformation(),
_T("DuilibDemo.cpp - _tWinMain")))
{
// Do nothing here - RecordExceptionInfo() has already done
// everything that is needed. Actually this code won't even
// get called unless you return EXCEPTION_EXECUTE_HANDLER from
// the __except clause.
} return ;
}

手动让程序崩溃:

*(int*) = ;

BugReport源码:点击下载

给自己的程序添加BugReport的更多相关文章

  1. 在Windows系统下用命令把应用程序添加到系统服务

    在Windows系统下用命令把应用程序添加到系统服务,使用SC命令. 加入服务格式如下:sc create ServiceName binPath= 程序路径 start= auto(等号后面的空格是 ...

  2. 图像处理控件ImageGear for .NET教程如何为应用程序 添加DICOM功能(2)

    在前面的一些关于图像处理控件ImageGear for .NET文章<图像处理控件ImageGear for .NET教程: 添加DICOM功能(1)>中讲解了如何对应用程序添加DICOM ...

  3. C# 为网络程序添加用户代理

    如何为网络程序添加用户代理,本人推荐使用UrlMkSetSessionOption函数, 不过该函数有一个弱点不可以X64编译,X86编译软件才可以调用该函数 否则会一直返回!S_OK意义错误.第二呢 ...

  4. 将一个应用程序添加做成windows服务

    需求来源: 在服务器端运行的一个应用程序,为完成客户端路径分析等功能: 此应用程序只需要运行着就可以,没有界面等要求: 因此,考虑把此应用程序添加到服务器端电脑管理的服务中,可以启动和停止. 这里添加 ...

  5. IOS编程教程(八):在你的应用程序添加启动画面

    IOS编程教程(八):在你的应用程序添加启动画面   虽然你可能认为你需要编写闪屏的代码,苹果已经可以非常轻松地把它做在Xcode中.不需要任何编码.你只需要做的是设置一些配置. 什么是闪屏 对于那些 ...

  6. 在Unicode版Inno Setup中使用ISSkin给安装程序添加皮肤

    原文 http://www.cnblogs.com/2356/archive/2009/10/27/1590565.html 在Unicode版Inno Setup中使用ISSkin给安装程序添加皮肤 ...

  7. 安装程序添加iis的方法经验分享

    原文:安装程序添加iis的方法经验分享 网上有一些这样的方法,但我这里主要做一些对比和扩充 网上这方面的文章的岁数比较大,server 08R2和win7出来后,整理这方面的资料的文章没找到,所以这里 ...

  8. 将程序添加到右键菜单和图标(以记事本、UltraEdit为例)

    原文:将程序添加到右键菜单(以记事本.UltraEdit为例) 如何将程序加入右键菜单,这里分别以记事本.UltraEdit为例! 以记事本程序为例: 1. 在运行中输入regedit,打开注册表,找 ...

  9. 011.Adding Search to an ASP.NET Core MVC app --【给程序添加搜索功能】

    Adding Search to an ASP.NET Core MVC app 给程序添加搜索功能 2017-3-7 7 分钟阅读时长 作者 本文内容 1.Adding Search by genr ...

随机推荐

  1. Linux基础(三)Shell test 命令

    Shell test 命令 Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值.字符和文件三个方面的测试. 数值测试 参数 说明 -eq 等于则为真 -ne 不等于则为真 -gt ...

  2. unity3d 第一人称脚本解释MouseLook

    using UnityEngine; using System.Collections; /// MouseLook rotates the transform based on the mouse ...

  3. 总结docker常用命令

    docker 1docker pull 镜像 2docker ps -a 查看所有容器docker image 查看镜像 3docker rm 容器id 删除容器 docker rm 一次可以指定多个 ...

  4. 提高Linux运维效率的30个命令行常用快捷键

    提高Linux运维效率的30个命令行常用快捷键 表4-1  30个常用快捷键 快捷键 功能说明 最有用快捷键 tab 命令或路径等的补全键,Linux最有用快捷键* 移动光标快捷键 Ctrl+a 光标 ...

  5. <3>lua字符串

    1.字符串 <1>字符串相连/加法   .. local str = "abc" str = str .. 7 --字符串与数字相连 print(str) --abc7 ...

  6. html5-新元素新布局模板-完善中

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  7. Java基础(basis)-----关键字break、continue、return的区别

       1.break      break只能用于switch语句和循环语句中,跳出当前循环:但是如果是嵌套循环, 则只能跳出当前的这一层循环,只有逐层break才能跳出所有循环 for (int i ...

  8. codeforces 980E The Number Games

    题意: 给出一棵树,要求去掉k个点,使得剩下的还是一棵树,并且要求Σ(2^i)最大,i是剩下的节点的编号. 思路: 要使得剩下的点的2的幂的和最大,那么肯定要保住大的点,这是贪心. 考虑去掉哪些点的话 ...

  9. zookeeper开发

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 zookeeper-3.4.11 ZK客户端操作命令: #登 ...

  10. 【安装虚拟机三】设置Linux IP地址

    环境 VMware 10 CentOS-6.5-x86_64 第一步:查看IP信息linux:ifconfig (windows:ipconfig) 第二步:编辑网卡信息 vi /etc/syscon ...