C#程序关于文件占用无法访问问题求解。。。
这个代码是一个鼠标键盘录制回放器的一部分代码,我简单说下。。。点record开始记录,record按钮文字变成stop. 点stop以后再点play可以正常播放,但在点了record没点stop时候点play会出错,OperationLog.txt被其它进程占用,不能访问。 不知道在哪关闭流,也不想用抛出错误的方法。。。求解.太穷 没多少分。。
- C# code
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Threading;using System.IO;namespace UltroMouse{ public partial class FrmMain : Form { #region 私有常量 private readonly int m_ScreenWidth = 1024; private readonly int m_ScreenHeight = 768; #endregion 私有常量 #region 私有变量 /// <summary> /// 屏幕捕获点X坐标 /// </summary> private int m_CaptureX = 0; /// <summary> /// 屏幕捕获点Y坐标 /// </summary> private int m_CaptureY = 0; /// <summary> /// 锁定对象,用于加锁 /// </summary> private object m_LockObj = new object(); /// <summary> /// 开始记录坐标 /// </summary> private bool m_StartRecordPos = false; /// <summary> /// 时间cnt /// </summary> private UInt32 m_dwTimeCnt = 0;//100ms every Cnt. //add some variable here. private FileInfo f = new FileInfo("OperationLog.txt"); private StreamWriter sw=null; private StreamReader sr=null; private bool m_Recording = false; private bool m_RequestShowForm = false; private bool m_StopExcuteRecord = false; /// <summary> /// 钩子管理实例 /// </summary> private SKHook m_HookMain = new SKHook(); #endregion 私有变量 #region 私有方法 /// <summary> /// /// </summary> /// <param name="mousex"></param> /// <param name="mousey"></param> private void RecordCaptureXY(int code,int mousex, int mousey) { //label1.Text = "X=" + mousex.ToString(); //label2.Text = "Y=" + mousey.ToString(); //if record now, save the records to the log file. if(m_Recording&&Check_RecordMouse.Checked) sw.WriteLine("M,{0},{1},{2},{3}", m_dwTimeCnt * 100,code, mousex, mousey); } /// <summary> /// /// </summary> /// <param name="mousex"></param> /// <param name="mousey"></param> private void RecordKeyCode(KeyEventArgs e,WM_KEYBOARD keystatus) { //if record now, save the records to the log file. if (m_Recording && Check_RecordKeyboard.Checked) { sw.WriteLine("K,{0},{1},{2}", m_dwTimeCnt * 100, (int)keystatus,(int)e.KeyCode); } } #endregion 私有方法 #region 构造函数 /// <summary> /// 主窗口 /// </summary> public FrmMain() { InitializeComponent(); this.m_ScreenWidth = Screen.PrimaryScreen.Bounds.Width; this.m_ScreenHeight = Screen.PrimaryScreen.Bounds.Height; this.m_HookMain.OnKeyDown += new KeyEventHandler(HookMain_OnKeyDown); this.m_HookMain.OnKeyUp += new KeyEventHandler(HookMain_OnKeyUp); this.m_HookMain.OnMouseUpdate += new MouseUpdateEventHandler(HookMain_OnMouseUpdate); } #endregion 构造函数 #region 控件事件 /// <summary> /// 窗体加载 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void FrmMain_Load(object sender, EventArgs e) { POINT mousePoint = new POINT(); Win32API.GetCursorPos(ref mousePoint); this.m_HookMain.InstallHook(); } /// <summary> /// 窗体已经关闭 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void FrmMain_FormClosed(object sender, FormClosedEventArgs e) { this.m_HookMain.UnInstallHook(); } /// <summary> /// 窗体正在关闭 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void FrmMain_FormClosing(object sender, FormClosingEventArgs e) { //Thread.Sleep(300); } /// <summary> /// 鼠标钩子更新事件 /// </summary> /// <param name="x"></param> /// <param name="y"></param> private void HookMain_OnMouseUpdate(int code,int x, int y) { this.RecordCaptureXY(code,x, y); } /// <summary> /// 键盘钩子KeyDown事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void HookMain_OnKeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Escape && Control.ModifierKeys == Keys.Shift) { m_StopExcuteRecord = true; } if (e.KeyCode == Keys.R && Control.ModifierKeys == Keys.Control) { if (m_Recording == false) { this.Hide(); timer1.Enabled=true; m_dwTimeCnt=0; m_Recording = true; button4.Text = "Stop"; notifyIcon1.Visible = true; //托盘图标可见 //open the log file. sw = f.CreateText(); } else { this.Show(); timer1.Enabled=false; m_Recording = false; button4.Text = "Record"; notifyIcon1.Visible = false; //托盘图标可见 //close the file. sw.Close(); } } if (e.KeyCode == Keys.H && Control.ModifierKeys == Keys.Control) { if (this.Visible) { this.ShowInTaskbar = false; //不显示在系统任务栏 notifyIcon1.Visible = true; //托盘图标可见 this.Hide(); } else { this.ShowInTaskbar = true; //显示在系统任务栏 notifyIcon1.Visible = false; //托盘图标隐藏 this.Show(); } } //record the key code. RecordKeyCode(e,WM_KEYBOARD.WM_KEYDOWN); } /// <summary> /// 键盘钩子KeyUp事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void HookMain_OnKeyUp(object sender, KeyEventArgs e) { //record the key code. RecordKeyCode(e, WM_KEYBOARD.WM_KEYUP); } #endregion 控件事件 private void timer1_Tick(object sender, EventArgs e) { m_dwTimeCnt ++; } private void ExcutRecord() { //Hide the current form. string Str = null; string[] Tokens; int dwTimeMSOld = 0; int iTimes = int.Parse(textBox1.Text); //Do it many times. while (iTimes-- > 0) { //open file sr = File.OpenText("OperationLog.txt"); dwTimeMSOld = 0; //一直读到空为止 while ((Str = sr.ReadLine()) != null) { //We can stop it whenever we want. if(m_StopExcuteRecord) { m_StopExcuteRecord = false; sr.Close(); goto ENDFUN; } Tokens = Str.Split(','); string s = Tokens[0]; int dwTimeMS = int.Parse(Tokens[1]); Thread.Sleep(dwTimeMS - dwTimeMSOld); dwTimeMSOld = dwTimeMS; if(s=="M") { int dwMouseCode = int.Parse(Tokens[2]); int x = int.Parse(Tokens[3]); int y = int.Parse(Tokens[4]); dwMouseCode+=(int)(MouseEventFlag.MOUSEEVENTF_ABSOLUTE); Win32API.mouse_event((MouseEventFlag)dwMouseCode, x*65535/m_ScreenWidth, y*65535/m_ScreenHeight, 0, (UIntPtr)0); } else if(s=="K") { int iStatus = int.Parse(Tokens[2]); int iKeyCode = int.Parse(Tokens[3]); //send the keyboard event code. if((WM_KEYBOARD)iStatus == WM_KEYBOARD.WM_KEYDOWN) { Win32API.keybd_event((byte)iKeyCode, 0, 0, 0); } else { Win32API.keybd_event((byte)iKeyCode, 0, 0x02, 0); } } } //Because the last record will record a redundant CTRL, maybe left or right. //So release them here. I know this is not good, but .... Win32API.keybd_event((byte)Keys.LControlKey, 0, 0x02, 0); Win32API.keybd_event((byte)Keys.RControlKey, 0, 0x02, 0); //Close file sr.Close(); }
[解决办法]
开始没注意看你的代码,你这个StreamWriter定义是函数外面的就好办啊。
直接在play里面卸载钩子关闭流就可以了啊,都不需要判断了。
this.m_HookMain.UnInstallHook();
this.sw.Close();
。。。。
[解决办法]
写入文件用 File.AppendAllText(); 这个函数
读取文件用 fs1 = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 这个方式打开文件流
这样就可以一边读一边写 而不需要关闭读取流 也就是说这个读取文件的流可以一直打开