https://github.com/thejinchao/AxTrace
大神写的一个调试工具,可以在运行时监视“日志”和“变量”。
原来AxTrace 3的时候,自带C#、C例子,更新到AxTrace 4后,没有C#例子。所以修改了原有的C#例子,让它能和AxTrace 4一起工作。
封装的实用类AxTrace.cs
using System;
using System.Runtime.InteropServices;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Diagnostics;
namespace com.thecodeway
{
public class AxTrace
{
/*---------------------------------------------------------------------------------------------*/
public enum LogType
{
TRACE = 0,
DEBUG = 1,
INFO = 2,
WARN = 3,
ERROR = 4,
FATAL = 5,
USERDEF = 10,
}
//private static readonly ushort AX_CODEPAGE_ACP = 0;
private static readonly ushort AX_CODEPAGE_UTF8 = 1;
//private static readonly ushort AX_CODEPAGE_UTF16 = 2;
public static readonly uint AXV_INT8 = 0;
public static readonly uint AXV_UINT8 = 1;
public static readonly uint AXV_INT16 = 2;
public static readonly uint AXV_UINT16 = 3;
public static readonly uint AXV_INT32 = 4;
public static readonly uint AXV_UINT32 = 5;
public static readonly uint AXV_INT64 = 6;
public static readonly uint AXV_UINT64 = 7;
public static readonly uint AXV_FLOAT32 = 8;
public static readonly uint AXV_FLOAT64 = 9;
public static readonly uint AXV_STR_ACP = 10;
public static readonly uint AXV_STR_UTF8 = 11;
public static readonly uint AXV_STR_UTF16 = 12;
public static readonly uint AXV_USER_DEF = 100;
private static readonly string DEFAULT_AXTRACE_SERVER_IP = "127.0.0.1";
private static Int32 DEFAULT_AXTRACE_SERVER_PORT = 1978;
private static Int32 AXTRACE_MAX_PROCESSNAME_LENGTH = 512;
private static readonly int AXTRACE_MAX_LOG_STRING_LENGTH = 0x8000;
private static readonly int AXTRACE_MAX_VALUENAME_LENGTH = 128;
private static readonly int AXTRACE_MAX_VALUE_LENGTH = 1024;
//private static readonly int AXTRACE_MAX_SCENE_NAME_LENGTH = 128;
//private static readonly int AXTRACE_MAX_SCENE_DEFINE_LENGTH = 2048;
//private static readonly int AXTRACE_MAX_ACTOR_INFO_LENGTH = 2048;
//private static readonly int AXTRACE_MAX_ACTOR_LOG_LENGTH = 2048;
private static readonly int AXTRACE_PROTO_VERSION = 4;
private static readonly int AXTRACE_CMD_TYPE_SHAKEHAND = 0;
private static readonly byte AXTRACE_CMD_TYPE_LOG = 1;
private static readonly byte AXTRACE_CMD_TYPE_VALUE = 2;
//private static readonly int AXTRACE_CMD_TYPE_2D_BEGIN_SCENE = 3;
//private static readonly int AXTRACE_CMD_TYPE_2D_ACTOR = 4;
//private static readonly int AXTRACE_CMD_TYPE_2D_END_SCENE = 5;
//private static readonly int AXTRACE_CMD_TYPE_2D_ACTOR_LOG = 6;
[ThreadStatic]
private static axtrace_contex_s g_context = null;
/*---------------------------------------------------------------------------------------------*/
/* AxTrace Global data */
private class axtrace_contex_s
{
public bool is_init_succ; /* 0 means not, 1 means yes*/
public Socket socket; /* socket file desc*/
public axtrace_contex_s()
{
is_init_succ = false;
}
};
/*---------------------------------------------------------------------------------------------*/
/* axtrace communication data struct*/
[Serializable]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct axtrace_head_s
{
public ushort length; /* length */
public byte flag; /* magic flag, always ‘A‘ */
public byte type; /* command type AXTRACE_CMD_TYPE_* */
};
[Serializable]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct axtrace_shakehand_s
{
public axtrace_head_s head; /* common head */
public ushort ver; /* proto ver */
public short sname_len; /* length of session name */
public uint pid; /* process id*/
public uint tid; /* thread id*/
/* [session name buf with ‘\0‘ ended]*/
};
[Serializable]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct axtrace_log_s
{
public axtrace_head_s head; /* common head */
public uint log_type; /* trace style AXT_* */
public ushort code_page; /* code page */
public ushort length; /* trace string length */
/* [trace string data with ‘\0‘ ended] */
};
[Serializable]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct axtrace_value_s
{
public axtrace_head_s head; /* common head */
public uint value_type; /* value type AXV_* */
public ushort name_len; /* length of value name */
public ushort value_len; /* length of value */
/* [name buf with ‘\0‘ ended]*/
/* [value buf] */
};
[Serializable]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct axtrace_2d_begin_scene_s
{
axtrace_head_s head; /* common head */
double left; /* left of scene*/
double top; /* top of scene*/
double right; /* right of scene*/
double bottom; /* bottom of scene*/
ushort name_len; /* length of scene name */
ushort define_len; /* length of scene define */
/* [scene name buf with ‘\0‘ ended]*/
/* [scene define buf with ‘\0‘ ended]*/
};
[Serializable]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct axtrace_2d_actor_s
{
axtrace_head_s head; /* common head */
Int64 actor_id; /* id of actor */
double x; /* position (x)*/
double y; /* position (y)*/
double dir; /* direction */
uint style; /* user define style */
ushort name_len; /* length of actor name */
ushort info_len; /* length of actor information */
/* [actor name buf with ‘\0‘ ended]*/
/* [actor information buf with ‘\0‘ ended]*/
};
[Serializable]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct axtrace_2d_end_scene_s
{
axtrace_head_s head; /* common head */
ushort name_len; /* length of scene name */
/* [scene name buf with ‘\0‘ ended]*/
};
[Serializable]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct axtrace_2d_actor_log_s
{
axtrace_head_s head; /* common head */
Int64 actor_id; /* id of actor */
ushort name_len; /* length of scene name */
ushort log_len; /* length of actor log */
/* [scene name buf with ‘\0‘ ended]*/
/* [actor log(utf8) buf with ‘\0‘ ended]*/
};
static private void _send_handshake_message(axtrace_contex_s ctx)
{
/* buf for send , call send() once*/
int headSize = Marshal.SizeOf(typeof(axtrace_shakehand_s));
byte[] buf = new byte[headSize + AXTRACE_MAX_PROCESSNAME_LENGTH];
string process_module_name = Process.GetCurrentProcess().MainModule.FileName;
int name_length = System.Text.Encoding.UTF8.GetByteCount(process_module_name);
/* add ‘\0‘ ended */
name_length += 1;
/*calc final length*/
int final_length = Marshal.SizeOf(typeof(axtrace_shakehand_s)) + name_length;
var head = new axtrace_shakehand_s();
head.head.length = (ushort)(final_length);
head.head.flag = (byte)‘A‘;
head.head.type = (byte)AXTRACE_CMD_TYPE_SHAKEHAND;
head.ver = (ushort)AXTRACE_PROTO_VERSION;
head.sname_len = (short)name_length;
head.pid = (uint)Process.GetCurrentProcess().Id;
head.tid = (uint)Thread.CurrentThread.ManagedThreadId;
IntPtr headPtr = Marshal.AllocHGlobal(headSize);
Marshal.StructureToPtr(head, headPtr, false);
Marshal.Copy(headPtr, buf, 0, headSize);
System.Text.Encoding.UTF8.GetBytes(process_module_name).CopyTo(buf, headSize);
buf[final_length - 1] = 0; //add ‘\0‘
Marshal.FreeHGlobal(headPtr);
/* send to axtrace server*/
ctx.socket.Send(buf, 0, final_length, SocketFlags.DontRoute);
}
static private axtrace_contex_s _axtrace_try_init(string server_ip, ushort server_port)
{
try
{
g_context = new axtrace_contex_s();
//try connect to server
g_context.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
/* set SO_LINGER off, make sure all data in send buf can be sended */
g_context.socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, 0);
/* connect to server */
IPEndPoint iep = new IPEndPoint(IPAddress.Parse(server_ip), server_port);
g_context.socket.Connect(iep);
/* send hand shake message */
_send_handshake_message(g_context);
/* init success */
g_context.is_init_succ = true;
}
catch (Exception)
{
g_context.is_init_succ = false;
}
return g_context;
}
static axtrace_contex_s _axtrace_get_thread_contex()
{
if (g_context != null)
{
/* already try init in this thread */
return (g_context.is_init_succ) ? g_context : null;
}
/* try init */
g_context = _axtrace_try_init(DEFAULT_AXTRACE_SERVER_IP, (ushort)DEFAULT_AXTRACE_SERVER_PORT);
return g_context.is_init_succ ? g_context : null;
}
static public void Log(LogType log_type, string format, params object[] args)
{
/* buf for send , call send() once*/
int headSize = Marshal.SizeOf(typeof(axtrace_log_s));
byte[] buf = new byte[headSize + AXTRACE_MAX_LOG_STRING_LENGTH];
/* is init ok? */
var ctx = _axtrace_get_thread_contex();
if (ctx == null || !ctx.is_init_succ) return;
/* Create String Contents*/
string trace_string = System.String.Format(format, args);
/** get string length*/
// use byte count not the length of string
//int content_length = content.Length + 1;
int contents_byte_size = System.Text.Encoding.UTF8.GetByteCount(trace_string);
/* add ‘\0‘ ended */
contents_byte_size += 1;
/* fill the trace head data */
int final_length = Marshal.SizeOf(typeof(axtrace_log_s)) + contents_byte_size;
var head = new axtrace_log_s();
head.head.length = (ushort)(final_length);
head.head.flag = (byte)‘A‘;
head.head.type = AXTRACE_CMD_TYPE_LOG;
head.log_type = (uint)log_type;
head.code_page = AX_CODEPAGE_UTF8;
head.length = (ushort)contents_byte_size;
IntPtr headPtr = Marshal.AllocHGlobal(headSize);
Marshal.StructureToPtr(head, headPtr, false);
/* copy the head data */
Marshal.Copy(headPtr, buf, 0, headSize);
/* copy the trace string */
System.Text.Encoding.UTF8.GetBytes(trace_string).CopyTo(buf, headSize);
buf[final_length - 1] = 0; //add ‘\0‘
Marshal.FreeHGlobal(headPtr);
/* send to axtrace server*/
ctx.socket.Send(buf, 0, final_length, SocketFlags.DontRoute);
}
static private void _value(axtrace_contex_s ctx, /*uint style, */string name, uint value_type, byte[] valueBytes)
{
byte[] nameBytes = System.Text.Encoding.UTF8.GetBytes(name);
int name_length = nameBytes.Length + 1; // add ‘\0‘
int value_length = valueBytes.Length;
int headSize = Marshal.SizeOf(typeof(axtrace_value_s));
byte[] buf = new byte[headSize + AXTRACE_MAX_VALUENAME_LENGTH + AXTRACE_MAX_VALUE_LENGTH];
int final_length = Marshal.SizeOf(typeof(axtrace_value_s)) + name_length + value_length;
axtrace_value_s head = new axtrace_value_s();
head.head.length = (ushort)(final_length);
head.head.flag = (byte)‘A‘;
head.head.type = AXTRACE_CMD_TYPE_VALUE;
head.value_type = value_type;
head.name_len = (ushort)(name_length);
head.value_len = (ushort)(value_length);
IntPtr headPtr = Marshal.AllocHGlobal(headSize);
Marshal.StructureToPtr(head, headPtr, false);
Marshal.Copy(headPtr, buf, 0, headSize);
nameBytes.CopyTo(buf, headSize);
buf[headSize + nameBytes.Length] = 0; //add ‘\0‘
valueBytes.CopyTo(buf, headSize + head.name_len);
Marshal.FreeHGlobal(headPtr);
ctx.socket.Send(buf, 0, final_length, SocketFlags.DontRoute);
}
static public void Value(/*uint style, */string name, sbyte value)
{
var ctx = _axtrace_get_thread_contex();
if (!ctx.is_init_succ) return;
_value(ctx, /*style, */name,
AXV_UINT8,
BitConverter.GetBytes(value));
}
static public void Value(/*uint style, */string name, byte value)
{
var ctx = _axtrace_get_thread_contex();
if (!ctx.is_init_succ) return;
_value(ctx, /*style, */name,
AXV_INT8,
BitConverter.GetBytes(value));
}
static public void Value(/*uint style, */string name, short value)
{
var ctx = _axtrace_get_thread_contex();
if (!ctx.is_init_succ) return;
_value(ctx, /*style, */name,
AXV_INT16,
BitConverter.GetBytes(value));
}
static public void Value(/*uint style, */string name, ushort value)
{
var ctx = _axtrace_get_thread_contex();
if (!ctx.is_init_succ) return;
_value(ctx, /*style, */name,
AXV_UINT16,
BitConverter.GetBytes(value));
}
static public void Value(/*uint style, */string name, int value)
{
var ctx = _axtrace_get_thread_contex();
if (!ctx.is_init_succ) return;
_value(ctx, /*style, */name,
AXV_INT32,
BitConverter.GetBytes(value));
}
static public void Value(/*uint style, */string name, uint value)
{
var ctx = _axtrace_get_thread_contex();
if (!ctx.is_init_succ) return;
_value(ctx, /*style, */name,
AXV_UINT32,
BitConverter.GetBytes(value));
}
static public void Value(/*uint style, */string name, long value)
{
var ctx = _axtrace_get_thread_contex();
if (!ctx.is_init_succ) return;
_value(ctx, /*style, */name,
AXV_INT64,
BitConverter.GetBytes(value));
}
static public void Value(/*uint style, */string name, ulong value)
{
var ctx = _axtrace_get_thread_contex();
if (!ctx.is_init_succ) return;
_value(ctx, /*style, */name,
AXV_UINT64,
BitConverter.GetBytes(value));
}
static public void Value(/*uint style, */string name, float value)
{
var ctx = _axtrace_get_thread_contex();
if (!ctx.is_init_succ) return;
_value(ctx, /*style, */name,
AXV_FLOAT32,
BitConverter.GetBytes(value));
}
static public void Value(/*uint style, */string name, double value)
{
var ctx = _axtrace_get_thread_contex();
if (!ctx.is_init_succ) return;
_value(ctx, /*style, */name,
AXV_FLOAT64,
BitConverter.GetBytes(value));
}
static public void Value(/*uint style, */string name, string value)
{
var ctx = _axtrace_get_thread_contex();
if (!ctx.is_init_succ) return;
byte[] stringBytes = System.Text.Encoding.UTF8.GetBytes(value);
byte[] withNull = new byte[stringBytes.Length + 1];
stringBytes.CopyTo(withNull, 0);
withNull[stringBytes.Length] = 0;
_value(ctx, /*style, */name,
AXV_STR_UTF8,
withNull);
}
}
}
调用的代码Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using com.thecodeway;
using System.Runtime.InteropServices;
namespace test.win32.cs
{
class Program
{
public static void AxTraceThread(object obj)
{
AxTrace.Log(AxTrace.AXT_TRACE, (string)obj);
}
private class AxValueParam
{
public string value_name;
public string value;
}
public static void AxValueThread(object obj)
{
AxTrace.Value(AxTrace.AXT_TRACE,
((AxValueParam)obj).value_name, ((AxValueParam)obj).value);
}
[DllImport(@"AxTraceDll.dll", EntryPoint = "mixed_mode_multiply", CallingConvention = CallingConvention.StdCall)]
public static extern int Multiply(int x, int y);
[DllImport(@"AxTraceDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void axlog(uint log_type, string message, __arglist);
static void Main(string[] args)
{
System.Console.WriteLine("============= AxTrace4 Test(C#) ================");
//--------------------------
{
Console.WriteLine("AxTrace Test\n请按任意键继续. . .");
Console.ReadKey(true);
//test AxTrace
AxTrace.Log(AxTrace.AXT_TRACE, "-=-=-=-=-=-= Hello,World -=-=-=-=-=-=-=-=-=-");
AxTrace.Log(AxTrace.AXT_TRACE, "中文字符+Ascii");
AxTrace.Log(AxTrace.AXT_TRACE, "MultiLineTest\nLine{0}:第一行\nLine2:{1}\nLine3:第三行pi={2}", 1, "第二行", 3.14f);
AxTrace.Log(AxTrace.AXT_DEBUG, "DEBUG: This is a debug message");
AxTrace.Log(AxTrace.AXT_INFO, "INFO: This is a info message");
AxTrace.Log(AxTrace.AXT_WARN, "WARN: This is a warning message");
AxTrace.Log(AxTrace.AXT_ERROR, "ERROR: This is a error message");
AxTrace.Log(AxTrace.AXT_FATAL, "FATAL: This is a fatal message");
}
{
Console.WriteLine("AxTrace Pressure Test\nPress any key to continue...");
Console.ReadKey();
int blank_Count = 0;
int step = 1;
int MAX_BLANK_COUNT = 50;
AxTrace.Log(AxTrace.AXT_TRACE, "<BEGIN>");
for (int i = 0; i < 500; i++)
{
byte[] szTemp = new byte[blank_Count + 1];
int j = 0;
for (j = 0; j < blank_Count; j++) szTemp[j] = (byte)‘ ‘;
blank_Count += step;
if (blank_Count >= MAX_BLANK_COUNT) step = -1;
if (blank_Count <= 0) step = 1;
szTemp[j++] = (byte)‘*‘;
string l = System.Text.Encoding.ASCII.GetString(szTemp);
AxTrace.Log(AxTrace.AXT_TRACE, l);
}
AxTrace.Log(AxTrace.AXT_TRACE, "<END>");
}
{
Console.WriteLine("AxTrace Multithread Pressure Test\nPress any key to continue...");
Console.ReadKey();
WaitCallback waitCallback = new WaitCallback(AxTraceThread);
int blank_Count = 0;
int step = 1;
int MAX_BLANK_COUNT = 50;
AxTrace.Log(AxTrace.AXT_TRACE, "<BEGIN>");
for (int i = 0; i < 500; i++)
{
byte[] szTemp = new byte[blank_Count + 1];
int j = 0;
for (j = 0; j < blank_Count; j++) szTemp[j] = (byte)‘ ‘;
blank_Count += step;
if (blank_Count >= MAX_BLANK_COUNT) step = -1;
if (blank_Count <= 0) step = 1;
szTemp[j++] = (byte)‘*‘;
ThreadPool.QueueUserWorkItem(waitCallback,
System.Text.Encoding.ASCII.GetString(szTemp));
}
}
{
Console.WriteLine("AxValue Test\nPress any key to continue...");
Console.ReadKey();
//test value
AxTrace.Value(AxTrace.AXT_TRACE, "Int_Test", (int)-12345);
AxTrace.Value(AxTrace.AXT_TRACE, "BYTE_MAX_VALUE", (byte)byte.MaxValue);
AxTrace.Value(AxTrace.AXT_TRACE, "BYTE_MIN_VALUE", (byte)byte.MinValue);
AxTrace.Value(AxTrace.AXT_TRACE, "SHORT_MAX_VALUE", (short)short.MaxValue);
AxTrace.Value(AxTrace.AXT_TRACE, "SHORT_MIN_VALUE", (short)short.MinValue);
AxTrace.Value(AxTrace.AXT_TRACE, "INT_MAX_VALUE", (int)int.MaxValue);
AxTrace.Value(AxTrace.AXT_TRACE, "INT_MIN_VALUE", (int)int.MinValue);
AxTrace.Value(AxTrace.AXT_TRACE, "LONG_MAX_VALUE", (long)long.MaxValue);
AxTrace.Value(AxTrace.AXT_TRACE, "LONG_MIN_VALUE", (long)long.MinValue);
AxTrace.Value(AxTrace.AXT_TRACE, "Float_Test", (float)-3.1415926f);
AxTrace.Value(AxTrace.AXT_TRACE, "Double_Test", (double)-3.141592653589793238462643383279);
AxTrace.Value(AxTrace.AXT_TRACE, "FLOAT_MAX_VALUE", (float)float.MaxValue);
AxTrace.Value(AxTrace.AXT_TRACE, "FLOAT_MIN_VALUE", (float)float.MinValue);
AxTrace.Value(AxTrace.AXT_TRACE, "DOUBLE_MAX_VALUE", (double)double.MaxValue);
AxTrace.Value(AxTrace.AXT_TRACE, "DOUBLE_MIN_VALUE", (double)double.MinValue);
AxTrace.Value(AxTrace.AXT_TRACE, "String_Test", "String 汉字 123");
}
{
Console.WriteLine("AxValue Pressure Test\nPress any key to continue...");
Console.ReadKey();
int start_blank = 0;
int start_step = 1;
int MAX_BLANK_COUNT = 50;
for (int i = 0; i < 100; i++)
{
AxTrace.Value(AxTrace.AXT_TRACE, "start_blank", start_blank);
int blank_Count = start_blank;
int step = start_step;
for (int j = 0; j < 50; j++)
{
byte[] szTemp = new byte[blank_Count + 1];
int k = 0;
for (k = 0; k < blank_Count; k++) szTemp[k] = (byte)‘ ‘;
blank_Count += step;
if (blank_Count >= MAX_BLANK_COUNT) step = -1;
if (blank_Count <= 0) step = 1;
szTemp[k++] = (byte)‘*‘;
string value_name = "Value_" + j;
AxTrace.Value(AxTrace.AXT_TRACE, value_name,
System.Text.Encoding.ASCII.GetString(szTemp));
}
start_blank += start_step;
if (start_blank >= MAX_BLANK_COUNT) start_step = -1;
if (start_blank <= 0) start_step = 1;
Thread.Sleep(10);
}
}
{
Console.WriteLine("AxValue Multithread Pressure Test\nPress any key to continue...");
Console.ReadKey();
int start_blank = 0;
int start_step = 1;
int MAX_BLANK_COUNT = 50;
WaitCallback waitCallback = new WaitCallback(AxValueThread);
for (int i = 0; i < 500; i++)
{
AxTrace.Value(AxTrace.AXT_TRACE, "start_blank_multiThread", start_blank);
int blank_Count = start_blank;
int step = start_step;
for (int j = 0; j < 50; j++)
{
byte[] szTemp = new byte[blank_Count + 1];
int k = 0;
for (k = 0; k < blank_Count; k++) szTemp[k] = (byte)‘ ‘;
blank_Count += step;
if (blank_Count >= MAX_BLANK_COUNT) step = -1;
if (blank_Count <= 0) step = 1;
szTemp[k++] = (byte)‘*‘;
string value_name = "Value_" + j;
AxValueParam axvp = new AxValueParam();
axvp.value_name = "Value_" + j; ;
axvp.value = System.Text.Encoding.ASCII.GetString(szTemp);
ThreadPool.QueueUserWorkItem(waitCallback, axvp);
}
start_blank += start_step;
if (start_blank >= MAX_BLANK_COUNT) start_step = -1;
if (start_blank <= 0) start_step = 1;
Thread.Sleep(10);
}
}
}
}
}
原文:https://www.cnblogs.com/octoberkey/p/14778145.html