自己是个C#菜鸟,写了些小东西,但是调试起来总是很麻烦。后来发现大牛们都用什么“日志”来记录软件执行的操作(好像叫软件日志还是系统日志,我就暂取软件日志),这样便于调试,还有就是在软件发生问题的时候方便查阅,感觉这是一个很好的方法,所以就尝试着加这项功能。
我采用的是用记事本来记录。
1.首先完成最简单的一步:把操作写入指定的txt文件
public void WriteDiary(string step)
{
StreamWriter sw = File.AppendText(fname);
sw.WriteLine(step);
sw.Close();
}
然后我们来试试看这个简单的函数能否正常执行
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string fname = "C:\\Users\\Zhou\\Desktop\\DiaryFile.txt";
private void Form1_Load(object sender, EventArgs e)
{
FileStream fs = new FileStream(fname, FileMode.Create);//我们以create方式覆盖创建。
fs.Close();
WriteDiary("打开日志成功");
}
public void WriteDiary(string step)
{
step = DateTime.Now + " " + step;
StreamWriter sw = File.AppendText(fname);
sw.WriteLine(step);
sw.Close();
}
}
运行后会发现桌面多了个DiaryFile.txt文件,点击打开后里面的内容为:xxxxxxxx 打开日志成功
这就记录了程序执行的操作
在界面添加一个按钮,在单击事件中:
private void button1_Click(object sender, EventArgs e)
{
string t = "你点击了" + this.button1.Text;
WriteDiary(t);
}
运行程序,点击刚添加的按钮button1.打开日志,发现操作已经成功写入。
这样你就记录在程序中自己关系的操作,有据可查。
在你打开这个日志的时候你再点击按钮,发现日志并没有更新,难道是写入错误?这时关闭当前日志,再重新打开日志,发现我们的操作是正常记录了的,只是没有实时更新
但有时候我们希望的是这个日志能实时的显示出来,不需要我们去打开这个txt文件来查看。此时我首先想到的是添加一个窗口,然后在窗口里添加一个listbox,用listbox来显示操作,我尝试并且成功了,这样虽能达到实时显示的目的,但是用户有可能一不小心就把这个窗口给关闭了,这样会导致程序出错,或者不能记录程序的操作等错误。
我们知道这个日志是txt文本文件,是可编辑的,我想能不能通过软件直接更改显示内容。于是百度了一下,给了我一个惊喜。
用SendMessage这个API可以实现这个功能。查看了这个API的参数有我们要更改内容的窗口句柄,还有消息类型,以及更改的内容。获取窗口句柄可以用FindWindow和FindWindowEX这两个API来实现
IntPtr vHandle = FindWindow("Notepad", "DiaryFile.txt - 记事本");//获取记事本窗口的句柄
IntPtr txtHandle = FindWindowEx(vHandle, IntPtr.Zero, "Edit", null);//获取记事本文本部分句柄
SendMessage(txtHandle, WM_SETTEXT, (IntPtr)0, mesg);//设置文本不问内容
因为我们记录一次操作就希望显示的日志更新一下,所以上面这部分内容可以加到写日志的函数中去
public void WriteDiary(string step)
{
step = DateTime.Now + " " + step;
StreamWriter sw = File.AppendText(fname);
sw.WriteLine(step);
sw.Close();
IntPtr vHandle = FindWindow("Notepad", "DiaryFile.txt - 记事本");//获取记事本句柄
IntPtr txtHandle = FindWindowEx(vHandle, IntPtr.Zero, "Edit", null);//获取记事本文本部分句柄
SendMessage(txtHandle, WM_SETTEXT, (IntPtr)0, step);//设置记事本文本部分内容
}
此时运行程序,打开日志,发现“打开日志成功”,现在点击按钮,发现日志内容是变化了,日志被替换为“你点击了button1”,这并不是我们想要的效果。此时我们关闭日志,再重新打开,发现日志仍然记录了两次操作:“打开日志成功” “你点击了button1”。所以sendMessage这个API只是更改了日志显示的内容,并没有改变日志内存储的数据(相当于你改变了文本,但是没有点击“保存”),那这时我们可以读取日志的内容,然后利用SendMessage来显示。
public void WriteDiary(string step)
{
step = DateTime.Now + " " + step;
StreamWriter sw = File.AppendText(fname);
sw.WriteLine(step);
sw.Close();
//这里为增加部分,SendMessage里的显示内容要相应更改为msg
StreamReader sr = new StreamReader(fname);
string msg = sr.ReadToEnd();//读取日志内容
sr.Close();
IntPtr vHandle = FindWindow("Notepad", "DiaryFile.txt - 记事本");//获取记事本句柄
IntPtr txtHandle = FindWindowEx(vHandle, IntPtr.Zero, "Edit", null);//获取记事本文本部分句柄
SendMessage(txtHandle, WM_SETTEXT, (IntPtr)0, msg);//设置记事本文本部分内容
}
此时运行程序,打开日志,日志同样显示:“打开日志成功”,此时点击按钮,日志增加了一条操作:“你点击了按钮就button1”,再点击按钮继续增加。。。。。这时我们关闭日志,单击几次按钮,再次打开日志,发现日志仍然记录了我们的操作。如果你想程序运行时就自动显示日志而不需要手动打开,在load里加一句:Process.Start(fname);就行了
如果你想最新执行的操作显示在最前面,只需要在日志写入的时候修改就行了。把最后执行的操作插入第一行就行了。整个程序如下:
public partial class Form1 : Form
{
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);
[DllImport("User32.DLL")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(
string lpClassName,
string lpWindowName
);
int WM_SETTEXT = 0x000C;
public Form1()
{
InitializeComponent();
}
string fname = "C:\\Users\\Zhou\\Desktop\\DiaryFile.txt";
private void Form1_Load(object sender, EventArgs e)
{
FileStream fs = new FileStream(fname, FileMode.Create);//我们以create方式覆盖创建。
fs.Close();
Process.Start(fname);
WriteDiary("打开日志成功");
}
public void WriteDiary(string step)
{
StreamReader sr = new StreamReader(fname);
string temp = sr.ReadToEnd();
sr.Close();
step = DateTime.Now + " " + step;
temp = step + "\r\n" + temp;
StreamWriter sw = new StreamWriter(fname);
sw.Write(temp);
sw.Close();
IntPtr vHandle = FindWindow("Notepad", "DiaryFile.txt - 记事本");//获取记事本句柄
IntPtr txtHandle = FindWindowEx(vHandle, IntPtr.Zero, "Edit", null);//获取记事本文本部分句柄
SendMessage(txtHandle, WM_SETTEXT, (IntPtr)0, temp);//设置记事本文本部分内容
}
private void button1_Click(object sender, EventArgs e)
{
string t = "你点击了" + this.button1.Text;
WriteDiary(t);
}
}
有什么不对的,希望大家批评指正,有更简单的方法,求交流。。。。共同学习