NO MFC - use .log debugger

zhaozj2021-02-16  40

I have always thought of using .log to debug programs, I have made one a few days ago, which can be used in VC and BCB. The following is the effect of the program run, when I debug a service program, generate a .log log file, record some information related to the startup and closing service procedure ...

[Source path & filename:] E: / Microsoft / Desktop / Simple_Service_02/##simple_service.log[9844796] Record Start At Date: 2003.08.06 & Time: 16:19:25.

[9844796] _SIMPLE_SERVICE_07 Winmain Start [9844796] Winnt system is available! [9844796] CommandLine by Following. [9844796] E: / Microsoft / Desktop / Simple_Service_02/#simple_Service.exe

[9844796] CurrentDirectory by Following. [9844796] D: / Winnt / System32

[9844796] Current Module FileName by Following. [9844796] E: / Microsoft / Desktop / Simple_Service_02/##simple_service.exe

[9844796] Re-set the current directory position [9844796] CurrentDirectory by Following. [9844796] E: / Microsoft / Desktop / Simple_Service_02

[9844796] Numargscount = 0x1 (1) [9844796] Command line parameter 0x0 (0) [9844796] E: / Microsoft / Desktop / Simple_Service_02/#simple_Service.exe

[9844796] Success To RegisterServiceCtrlhandler [9844796] Created synchronization object

[9845000] Waiting for the synchronization signal timeout [9845000] SetServiceStatus successfully!

[9845500] Progress = 0x1 (1)

[9846000] Progress = 0x15 (21)

[9846500] Progress = 0x29 (41)

[9847000] Progress = 0x3d (61)

[9847500] Progress = 0x51 (81)

[9848000] Progress = 0x65 (101)

[9848500] Progress = 0x79 (121) [9848500] SetServiceStatus to service_running!

[9849500] Doing Something ...

[9849609] Doing Something ...

[9849703] doing Something ...

[9849812] Doing Something ...

[9849906] Doing Something ...

[9850015] Doing Something ...

[9850062] Go INTO Service_ctrl function.

[9850062] Recive Service_Control_Stop

[9850109] Doing Something ...

[9850218] Doing Something ...

[9850265] The service status has been set to service_stop_pending, and the synchronization object is set to an excitation state. [9850312] Synchronous object is triggered

[9850312] Service_Maincleanup!

[9850312] setServiceStatus to service_stopped success!

[9850765] The service is now stoped [9850765] StartServiceCtrlDispatcher Complete.

[9850765] Record end at date: 2003.08.06 & Time: 16:19:31.

· Basic process introduction:

The first is in the constructor, first obtain the source path and name of the execution file in the command line, generate a corresponding .log file name according to the name (if there is existence to the recycle station). Apply for memory, create a file name (if repeated, append .log retry), set the available tag (Active = true).

Then, in the process of use, use the method of :: Write (), write the information you want to write to the buffer (please less than 512 bytes, otherwise open up a larger buffer, the buffer is full, writing Go to the .log file). After using :: Last () method at the end of the .log file (also forced buffering write hard drive) to add time dates.

Finally in the destructor. Natural is three songs, activiVe = false; closehandle (); and release buffer

To use this class, please include the class file, definition except all functions. as follows:

#include "runtimelog.cpp" runtimelog log;

The following is an example used in the window:

LResult Callback WinProc (HWND HWND, UINT UMSG, WPARAM WPARAM, LPARAM LPARAM) {char string [128] = ""; WSPrintf (String, "WinProc with Umst = 0x% x", UMSG); log.write (string);

····

Finally, please remember to call :: Last () method. Otherwise, if you use EXITPROCESS (); to exit the program, the destructor I defined doesn't work.

The use of this class is roughly the same in the BLAND C Builder, and it is basically available by my test ... and Win98 and Win2K are basically available (unknown in WinXP).

(Disclaimer: This file can be modified, used or reprinted, but I don't have any consequences that use this class):

Not much, the following is the source file of the class: (Full text - March 16, 2003 _am: 11:16)

// ******************************************************** **************************** // ******* FileName: runtimelog.h ******** ****************************** * ****************** *********************************************************** **********

#ifndef __runtimeloginclude # define __runtimeloginclude // include Something Here

// ************************************************* *** # include typedef class runtimelog {

PUBLIC:

Runtimelog (); ~ runtimelog (); // Destructor Void Last (Bool Show); void Last (); int showResult (dword delay);

Bool Group, Nobuff, Lastshow; // Used to group information

Private: / / About the Type of Function Pointer Declaration TypeDef Winshellapi Int (WinApi ShellFile);

Bool Active, DOLOG, NOSYSTIME; DWORD OFFSET; // Indicates the memory use offset DWORD BUFFSIZE; DWORD NUMTOWRITE; LPSTR SYSTICK; Handle FileHandle; Char * LPBUFF; // Used to apply for memory char logfile [512];

LPSTR DWNUM2STR (DWORD VAL);

PUBLIC:

DWORD hlstrcpy (LPSTR Str1, LPSTR Str2, DWORD Len); DWORD hlstrcat (LPSTR Str, LPSTR Plus, DWORD StrLen, DWORD PlusLen); LPSTR GetDate (); LPSTR GetTime (); LPSTR GetSysTick (DWORD * len); int write ( LPSTR LPSTR); int NumberWrite (LPSTR LPSTR, DWORD VAL); int WriteLog (Void); Void MSG (LPSTR STR);

} Runtimelog, * pruntimelog; // end of class runtimelog

// at include Last # endif // # iFNDef __runtimeloginclude /// ******************* * **************** *************** ///

// ******************************************************** **************************** // ******* FileName: runtimelog.cpp ******** ****************************** * ****************** * Version: 1.12 ************************************************* / / ********** *********************************************************** ********************* // Disclaimer: the file can be easily modified, used or reproduced, but I do not use any kind of consequences caused by the responsible // author: `海 海 ************ E-mail: free77@163.net********************************** / / * *********************************************************** ************************* / / You can define your classes inside the function, as follows the definition method of using the New. ********************* // runtimelog * RTLOG = new runtimelog; then in the last delete rtlog; ******** // can also be used The following method is defined: Runtimelog log; and it is best to explicitly call destructor ********* // ********************** *********************************************************** *** // The external interface is mainly :: Write (""); used to write information to buffer memory, //, :: Last (); used for the final end portion, write to the .log file. The buffer content / / can also be called directly: WriteLog (); to write buffer content (if any if any) is written to .log file. // Ver 1.02 new information Packet function, use group to control whether the packet // has been corrected automatic write buffer to disk error ..., buffering to 2048

#include #include "runtimelog.h"

// Constructor :: runtimelog () // without parameter constructor {nobuff = false; lastshow = false; active = false; nosystime = false; group = true;

OFFSET = NULL; NUMTOWRITE = NULL; SYSTICK = NULL; FileHandle = NULL; LPBUFF = NULL; BUFFSIZE = 2048; // Setupize size

Bool delold = false; // Set whether you want to throw away the old log dword overwrite = true; // Set whether you want to overwrite the old log, if it is not lost above words, Word Torecyclebin = false; // Set whether the old log is put Recycle bin

OverWrite = OverWrite CREATE_ALWAYS: CREATE_NEW; // a macro definition ToRecyclebin = ToRecyclebin FOF_ALLOWUNDO | FOF_SILENT | FOF_NOCONFIRMATION: FOF_SILENT | FOF_NOCONFIRMATION; // · Application available memory as a buffer space, point lpBuff, size BuffSize??

// lpbuff = (char *) Heapalloc (getProcessHeap (), Heap_zero_memory, buffsize; lpbuff = new char [buffsize]; // lpbuff = buffer;

If (lpbuff! = null) {// · Get ​​the process file name, change into the .log file name, find if it is repeated, is sent to getModuleFileName (null, lpbuff, buffsize); HLSTRCPY (logfile, lpbuff, null ); Getlongpathname (logfile, logfile, 512); // If you call this function in Win98, you may give a short file name format uint len ​​= strlen (logfile); uint i = 0; // then remove the extension from behind FOR (I = LEN; I> 0; I -) {IF (logfile [i] == '.') {HLSTRCAT (Logfile, "Log", I, 4); LEN = LEN 3; BREAK }}

// First determine whether the file is loop: // if you cannot create a file once successfully. IF ((GetFileAttributes (Logfile) == -1) || (GetLastError () == Error_File_not_Found); // MSG ("File does not exist");

Else if (DELOLD) / / The site is set to TRUE to delete the original file

{// Discovery file already exists, you need to thrown into the recycleopstructa fileop; lpshfileopstruct lpfileop = & fileop; Memset (LPFileop, Null, Sizeof (fileop));

Fileop.fflags = Torecyclebin; fileop.wfunc = fo_delete; fileop.pfrom = logfile; lpfileop-> hwnd = null;

// * / / Regarding the file operation of the runtime, define the function of the function's pointer shellfile * lpshfileOperation = null; // Function pointer defines hmodule hlib = loadingLibrary; if (hlib) {lpshfileOperation = Shellfile *) getProcaddress (HLIB, "ShfileOperation"); if (lpshfileOperation) {/ * if (* / lpshfileOperation (lpfileop); // msg ("SHFileOperation is issued during execution");} Else MSG ("shell32. There is no such function in DLL "); if (! freelibrary (hlib)) msg ​​(" release DLL failed ");} else msg (" no shell32.dll "); // * /} // throw garbage completion

/ / · Create a new file, write time FileHandle = Createfile (logfile, generic_write, file_share_read, null, overwrite, file_attribute_normal, null); if (filehandle == invalid_handle_value) {// When you can't create a new file Try to increase the file suffix if (HLSTRCAT (Logfile, ", NULL, 4) <125) goto loop; else {msg (" The problem in the CreateFile execution process, give up the retry. "); / * EXITPROCESS (0 ); * /}} Else {// handle is valid to perform setFilePointer (FileHandle, getFileSize (NULL), NULL, FILE_BEGIN); // Set the original size

Writefile (FileHandle, "[Source Path & FileName:], Strlen (" [Source Path & FileName:]), & NumTowrite, Null; Writefile (FileHandle, Logfile, Strlen (Logfile), & NumTowrite, NULL; / * Used in branch * / writefile (FileHandle, "/ X0D / X0A", Strlen ("/ X0D / X0A"), & NumTowrite, NULL;

WSPrintf (LPBUFF, "Record Start At Date:% S & Time:% s.", getdate (), gettime ());

Systick = getSystick (& ​​NumTowrite); // Get System Time Writefile (FileHandle, Systick, NUMTOWRITE, & NUMTOWRITE, NULL);

Writefile (FileHandle, LPBuff, Strlen (LPBuff), & NumTowrite, NULL

/ * Used in branch * / writefile (FileHandle, "/ X0D / X0A", Strlen ("/ x0d / x0a"), & numTowrite, null; if (! Setndoffile (filehandle)) MessageBox (null, "setting is unsuccessful "," ?? ", MB_ok | MB_TOPMOST); // Write data tail

// CloseHandle; FileHandle = INVALID_HANDLE_VALUE; // Close the handle LPBUFF [0] = null;} // Estimate the execution of the handle is valid; DOLOG = true;} else active = false; Nosystime = false; Write ("");

Return;}

// ******************************************************** ***************** VOID RUNTIMELOG :: Last () {last (0);} void runtimelog :: Last (Bool show) {group = false;

// Write the time IF (Active) {WRITELOG (); if (lpbuff! = Null) {if (filehandle == invalid_handle_value) {msg ("There is a problem in the final WriteLog process"); EXITPROCESS (0) } Else {// handle is active

/ * Used in branch * / writefile (FileHandle, "/ X0D / X0A", Strlen ("/ x0d / x0a"), & numTowrite, null; system = getsystick (& ​​number); // Get system time Writefile (FileHandle, Systick) Numtowrite, & NumTowrite, NULL;

WSPrintf (LPBUFF, "Record End at Date:% s.", getdate (), gettime ()); Writefile (FileHandle, LpBuff, Strlen (LPBuff), & NumTowrite, NULL

/ * Used in branch * / writefile (FileHandle, "/ X0D / X0A", Strlen ("/ X0D / X0A"), & NumTowrite, NULL;

If (! setndoffile (filehandle (filehandle)) MSG ("Set the end is not successful"); // Write the data tail

CloseHandle (FileHandle); FileHandle = Invalid_Handle_Value; // Close Handle LPBUFF [0] = NULL; if (show) showResult (0);} // Perform handle is valid} // end of if (lpbuff! = Null Active = false; // DOLOG = false;} // end of if (active) return;} // ************************************* ************************************************* Runtimelog :: ~ runtimelog () // Destructor {// msg ("Destructure ..."); Last (Lastshow); // MSG ("Prepare Release Memory"); // HeapFree (GetProcessHeap (), NULL, LPBUFF); lpbuff = null DOLOG = FALSE; SLEEP (100); delete lpbuff; lpbuff = null; DOLOG = FALSE;

Return;} // end of ~ runtimelog () // end of constructor and destructor

// ******************************************************** ****************

// Number to the output of the string, the return value is a string pointer // does not have unsuccessful case, nor does it deal with negative weight // The first parameter is the number you want to convert, the second parameter is specified conversion The minimum length // The third parameter is a string, and the first character is used as a placeholder, which can be null, then use the default

LPSTR RUNTIMELOG :: DWNum2Str (dWord Val) {static char Numstr [18] = ""; // _ULTOA (VAL, NUMSTR, 10); WSPRINTF (NUMSTR, "% Lu", VAL); Return Numstr;} / * / LPSTR DWNUM2STR (DWORD VAL, DWORD WIDTH, LPSTR LPSTR) {// The following is a number to ASCII comparison table Static Char Num [11] = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48}; static dword base [11] = // The following is to build a base table {0, 1, 10, 1000000, 10000000, 100000000, 1000000000}; static char array [16]; / / Used // array [0] = 0; // truncated strings DWORD INDEX, I, St; Index = 0; ST = 0;

IF (width> 10) width = 10; // width can't be greater than 10

/ / According to the third parameter, change the value of the value of the occupancy (LPSTR & LSTRLEN (LPSTR)) NUM [10] = LPSTR [0]; Else Num [10] = NUM ​​[0];

/ / In order to prevent zero as the divided number IF (VAL == 0) {for (i = width; I> 1; I - /) {Array [index] = NUM ​​[10]; Index ;} array [ Index] = NUM ​​[0]; array [index 1] = 0; return array;} // end of if (val == 0) // Start for normal operation for (i = 10; i> 0; I- -) // This is a loop {IF (! = Base [i]) {st = 1; i ; continue;} else if (! (! (}) / / Ready to fill in placeholders {Array [index] = NUM ​​[10]; index ;}} else {// {array [index] = NUM ​​[VAL / base [i]]; val = val% base [i]; Index ; msg (array);} _ASM {MOV EAX, VAL // This is the divisor MOV EDX, I // Note, the array subscript must be a register Sal EDX, 2 // right shift two or more equal to i * 4 MOV EBX, Base [edx] xor edx, edx // Do you want to empty EDX DIV EBX // before doing the method: Now there is a rest of DX, and the AX is the merchant MOV VAL, EDX / / save the remainder Add Eax, 30H // Adjust to ASCII code MOV ECX, INDEX MOV BYTE PTR Array [ECX], AL // Save the last character result to array add index, 1 // Equivalent to index } // end of _ASM {} } // end of for (dword i = ... array [index] = 0; // final truncation string Return Array;} // * // ************* *********************************************************** **

// ***** Custom function ******************************************* DWORD RUNTIMELOG :: HLSTRCPY (LPSTR STR1, LPSTR STR2, DWORD LEN) {DWORD II = 0; if (len == 0) // If no length is given, the length is automatically calculated (! (Str2 [len] == 0)) LEN } = F (! == STR2) RETURN LEN; IF (STR1 0; II-) {str1 [ii] = STR2 [II];} str1 [0] = str2 [0] ; // make up a loop} str1 [len] = 0; // Set the new string end Return Len;} // ******************** **************************************************** DWORD RUNTIMELOG :: HLSTRCAT ( LPSTR STR, LPSTR PLUS, DWORD STRLEN, DWORD PLUSLEN) {if (Strlen == 0) // If the length is not given, the length {while (! (Str [strlease == 0)) Strlen ;} IF (Pluslen == 0) // If no length is given, the length {while (! (Plus [pluslen] == 0)) Pluslen ;} DWORD II = 0; // Define Copy Plus Index is 0 for (II; II

// ******************************************************** ****************** LPSTR RUNTIMELOG :: getdate () {static char Date [15]; date [0] = null; systemtime systemtime; getlocaltime; wsprintf (DATE, "% D.% D.% D", systemtime.wyear, systemtime.wmonth, systemtime.wday; Return Date;} // **************** *********************************************************** LPSTR RunTimeLog :: GetTime () {static char Time [15]; Time [0] = NULL; SYSTEMTIME SystemTime; GetLocalTime (& SystemTime); wsprintf (Time, "% d:% d:% d", SystemTime.wHour, SystemTime . Return Time;} // *********************************************** ******************************* LPSTR RUNTIMELOG :: GetSystick (DWORD * LEN) {// "Royal Breeze" Static char Tick [20] = ""; static dword dwpase = gettickcount (), dwcurtick = gettickcount (); dwpase = dwcurs; dwcurtick = gettickcount (); tick [0] = null; // Clear the original string IF (DWPASTICK! = dwcurtick "&& group) LSTRCAT (Tick," / x0d / x0a "); // If the front and rear time is inconsistent, insert the branch LSTRCAT (Tick," ["); // Pred into the first /// LSTRCAT (Tick, Dwnum2Str (DWCURTICK, NULL, NULL); LSTRCAT (Tick, Dwnum2Str (dwcurtick)); * len = HLSTRCAT (Tick, "]", NULL, 2); // Reputable Return Tick;} / / ************************************************** ******************

INT Runtimelog :: Write (LPSTR LPSTR) // Reserved as a parameter function {DWORD LEN, LENTH, Ticklen; LPSTR TEMP = NULL; LEN = Strlen (LPSTR); if (Len && (! Nosystime) {TEMP = GetSystick (& Number); ticklen = Numtowrite;} else {ticklen = 0;} LENTH = LEN Ticklen 2; if (LENTH> BUFFSIZE) {// msg ("The length is too large, unwinding buffer"); if (FileHandle = Invalid_Handle_Value) {Writefile (FileHandle, NULL); // Write System Time Writefile (FileHandle, LPSTR, LEN, & NUMTOWRITE, NULL); // Write String content / * Used for branch * / Writefile (FileHandle, "/ X0D / X0A", Strlen ("/ X0D / X0A"), & NumTowrite, NULL; setndoffile (FileHandle); Return 1;} return 0; // Len is greater than buffsize and file handle is not available} // end of if (len> buffsize)

IF (Offset LENTH)> buffsize) WRITELOG ();

If (active) // If it is active, it provides writing {while (! "; DOLOG = FALSE;

IF (Ticklen) Offset = HLSTRCAT (LPBUFF, TEMP, OFFSET, TIKLEN); // Write System Time

IF (len) Offset = HLSTRCAT (LPBUFF, LPSTR, OFFSET, LEN); // Writing String Offset = HLSTRCAT (LPBUFF, "/ X0D / X0A", Offset, NULL); // Add Branch DOLOG = true; if WRITELOG (); RETURN 1;}

RETURN 0;} // ************************************************************ ********************** INT runtimelog :: WriteLog (void) {if (active && offset) {while (! DOLOG); DOLOG = FALSE;

IF (FileHandle == INVALID_HANDLE_VALUE) {msg ("Problems in the last written logfile process"); return 0;} Else {// The handle is valid to execute Writefile (FileHandle, LPBuff, Offset, & NumTowrite, NULL); offset = 0; // Remember to set 0 LPBUFF [0] = null; // lpbuff [1] = null; if (! ")) MSG (" Setting the end is not successful ") Data tail

} // Perform the handle to perform DOLOG = true; return 1;} else return 0;} // ******************************************** ********************************************************************* VOID RUNTIMELOG :: MSG (LPSTR STR) { MessageBox (NULL, STR, "??", MB_ok | MB_TOPMOST | MB_SETFOREGROUND; RETURN;}

// ******************************************************** ***************** INTUNTIMELOG :: NumberWrite (LPSTR LPSTR, DWORD VAL) {char Temp [30]; WSPrintf (Temp, "0x% x (% lu)" , VAL, VAL); Write (LPSTR); if (offset) OFFSET = Offset -2; Else {setndoffile (FileHandle); setFilePointer (FileHandle, GetFileSize (FileHandle, Null);} nosystime = true Write (TEMP); Nosystime = false; return 1L;} // **************************************************** **************************************** INT Runtimelog :: ShowResult (DWORD DELAY) {if (active) {Writelog () WHILE (! DOLOG); DOLOG = FALSE;

GetWindowsDirectory (lpBuff, BuffSize); DWORD ExecLen = hlstrcat (lpBuff, "//notepad.exe /" ", NULL, NULL); ExecLen = hlstrcat (lpBuff, logfile, ExecLen, NULL); ExecLen = hlstrcat (lpBuff," / "", NULL, NULL);

PROCESS_INFORMATION pi; STARTUPINFO si; memset (& si, 0, sizeof (si)); si.cb = sizeof (si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_MAXIMIZE; // SW_SHOW; CreateProcess (NULL, lpBuff, NULL Null, False, 0, NULL, NULL, & SI, & PI);

LPBUFF [0] = NULL; if (delay> 100000) DELAY = 150; if (delay); DOLOG = true; return;} else return;}

// ************************************************** ***********

转载请注明原文地址:https://www.9cbs.com/read-24601.html

New Post(0)