First, declare that the call is not performed according to the AOP method, and the call is still displayed.
Using system;
Using system. IO;
Using system. collections;
Using system. runtime. interopservices;
Using icsharpcode. sharpziplib. Zip;
Using icsharpcode. sharpziplib. Zip. compression;
Using icsharpcode. sharpziplib. Zip. Compression. streams;
Using icsharpcode. sharpziplib. Bzip2;
Using icsharpcode. sharpziplib. checksums;
Namespace genersoft. Focus
{
[Structlayoutattribute (layoutkind. Sequential, charset = charset. Auto)]
Public struct logfileheader
{
[Financialas (unmanagedtype. byvaltstr, sizeconst = 19)] Public String headersignature; // focustools. logfile, with the front 0x12
Public int entrylistnumber;
}
[structlayoutattribute (layoutkind. sequential, charset = charset. auto)]
public struct logfileentrylist
{< br> [financialas (unmanagedtype. byvaltstr, sizeconst = 9)] Public String createdate; // 8-bit, 20031201 format
[financialas (unmanagedtype. byvaltstr, sizeconst = 10)] Public String createtime; // 9-bit, 140324111 format
[financialas (unmanagedtype. byvaltstr, sizeconst = 1024)] Public String additionalinformation; // call the transferred log information
Public int additionalinformationtype; //
Public int entrynumber; // number of entries
}
[Structlayoutattribute (layoutkind. Sequential, charset = charset. Auto)]
Public struct logfileentry
{
[Financialas (unmanagedtype. byvaltstr, sizeconst = 1024)] Public String filename; // calling file name
[Financialas (unmanagedtype. byvaltstr, sizeconst = 1024)] Public String methodname; // calling method name
Public int filelinenumber; // location of the row number of calling
}
Public Enum logtype
{
Info, warning, error, exception, database
}
Public class log
{
Private Static logfileheader lfh;
Private Static logfileentrylist lfel;
Private Static logfileentry [] LFE;
Private Static system. Text. stringbuilder sb = NULL;
Private Static log instance = NULL;
Private const string logfilename = @ "C: \ focus. log ";
Private log ()
{
Lfh = new logfileheader ();
Lfh. headersignature = "focustools. logfile ";
SB = new system. Text. stringbuilder ();
Lfel = new logfileentrylist ();
}
Public static log instance
{
Get {If (null = instance) instance = new log (); Return instance ;}
}
Public void write (string S, logtype T)
{
System. datetime dt = system. datetime. now;
Lfel = new logfileentrylist ();
Lfel. additionalinformation = s;
Lfel. createdate = string. Format ("{0: D4} {1: D2} {2: D2}", DT. Year, DT. Month, DT. Day );
Lfel. createtime = string. format ("{0: D2} {1: D2} {2: D2} {3: D3}", DT. hour, DT. minute, DT. second, DT. millisecond );
// Query the call stack information of all threads in the current process. How can this problem be solved?
System. Diagnostics. stacktrace ST = new system. Diagnostics. stacktrace (true );
Lfel. entrynumber = ST. FrameCount-1;
Lfel. additionalinformationtype = convert. toint32 (t );
LFE = new logfileentry [st. FrameCount-1];
For (INT I = ST. FrameCount-1; I> 0; I --) // The last one is the write method itself, so it is not written.
{
LFE [st. FrameCount-1-i] = new logfileentry ();
LFE [st. FrameCount-1-i]. filename = ST. getframe (I). getfilename ();
LFE [st. FrameCount-1-i]. methodname = ST. getframe (I). getmethod (). Name;
LFE [st. FrameCount-1-i]. filelinenumber = ST. getframe (I). getfilelinenumber ();
}
Flush ();
}
Private void flush ()
{
Int entrylistnum = 0;
Filestream FS = new filestream (logfilename, filemode. openorcreate, fileaccess. readwrite );
Binarywriter BW = new binarywriter (FS );
Binaryreader BR = new binaryreader (FS );
Int size, size2;
Try
{
Bw. Write (lfh. headersignature );
BR. basestream. Seek (19, seekorigin. Begin );
Try
{
Entrylistnum = Br. readint32 () + 1;
}
Catch
{
Entrylistnum = 1;
}
Bw. basestream. Seek (19, seekorigin. Begin );
Bw. Write (entrylistnum );
Bw. basestream. Seek (0, seekorigin. End );
Size = marshal. sizeof (lfel );
Size2 = marshal. sizeof (LFE [0]);
Byte [] input = new byte [size + size2 * lfel. entrynumber];
intptr P = marshal. allochglobal (size);
marshal. structuretoptr (lfel, P, true);
byte [] bentrylist = new byte [size];
marshal. copy (p, bentrylist, 0, size);
// BW. write (bentrylist);
marshal. freehglobal (p);
bentrylist. copyto (input, 0);
for (INT I = 0; I {< br> intptr P2 = marshal. allochglobal (size2);
marshal. structuretoptr (LFE [I], P2, true);
byte [] bentry = new byte [size2];
marshal. copy (P2, bentry, 0, size2);
// BW. write (bentry);
marshal. freehglobal (P2);
bentry. copyto (input, bentrylist. length + I * size2);
}
// system. diagnostics. trace. writeline (system. text. encoding. default. getstring (input);
Deflater def = new Deflater (Deflater. best_compression);
If (def. isneedinginput) def. setinput (input);
def. finish ();
// system. diagnostics. trace. writeline (system. text. encoding. default. getstring (input);
byte [] dbuf = new byte [input. length];
int dsize = 0;
dsize = def. deflate (dbuf);
Bw. Write (dsize); // The size after compression
Bw. Write (input. Length); // The size before compression.
Bw. Write (dbuf, 0, dsize );
}
Catch (exception ex)
{
Throw ex;
}
Finally
{
If (null! = Br) Br. Close ();
If (null! = BW) BW. Close ();
If (null! = FS) fs. Close ();
}
}
}
Public class logfileeventargs
{
Public logfileeventargs (INT curvalue, int maxvalue)
{
This. curvalue = curvalue;
This. maxvalue = maxvalue;
}
Private int curvalue = 0;
Private int maxvalue = 0;
Public int curvalue {get {return curvalue;} set {curvalue = value ;}}
Public int maxvalue {get {return maxvalue;} set {maxvalue = value ;}}
}
Public Delegate void logfileeventhandler (Object sender, logfileeventargs E );
}
Note the following two points:
1. Stack information is read from stacktrace. When releasing the Assembly, copy the PDB file of the same version number. Otherwise, the line and column information cannot be read.
2. The structure processing adopts the intptr method.