当文件操作遇上进程占用时

  近日做文件操作时,老是抛异常说文件正在被另一个进程占用着,很无奈,给我知道是哪个进程占用的话,就把它给Kill掉,当然这样做在一定程度上是有危险的,万一占用文件的进程是那么那么地重要,就不该Kill了,因此这样的做法只能在确保安全的情况下去做,或者是Kill了进程之后带来的不良后果也无关痛痒。上网找了一下,在别的进程占用文件下读写文件的文章很多,但获取占用文章的进程就比较少,在百度上就有人说过用unlocker这种工具,这工具我没去看,感觉也不太适合在这里用吧,如果有dll,提供API那还不错。后来就在谷歌里找到了只那么一篇文章而已,看了之后还终究要用到别的exe,还得另外开进程啊。

       这个工具叫handler,从微软里面下载的。只是一个控制台程序而已,双击它运行就可以查看当前系统中正在运行的进程,进程ID,占用的文件等信息。如果给他输入文件名的参数,那就可以知道到时是那些进程在占用着这个文件了,列举的信息中有进程ID,这个很关键,有了pid,那Process就有希望了。

 1             //要检查被那个进程占用的文件
 2             string fileName = @"C:\Users\Administrator\Desktop\temp\..\temp\WF英文文档(MSDN).doc";
 3             //先格式化一下路径,免得有上面那种路径的话,程序识别不出来
 4             fileName = new FileInfo(fileName).FullName;
 5             Process tool = new Process();
 6             //下面这段就配置一下启动进程的相关了
 7             tool.StartInfo.FileName = @"C:\Users\Administrator\Desktop\temp\handle.exe";
 8             tool.StartInfo.Arguments = fileName + " /accepteula";
 9             tool.StartInfo.UseShellExecute = false;
10             //这里为了在运行的时候不会给那个程序冒出来
11             //Win7下不用也行,但XP就需要了
12             tool.StartInfo.RedirectStandardOutput = true;
13             tool.Start();
14             tool.WaitForExit();
15             string outputTool = tool.StandardOutput.ReadToEnd();
16 
17             //正则提取出进程的pid
18             string matchPattern = @"(?<=\s+pid:\s+)\b(\d+)\b(?=\s+)";
19             MatchCollection mc = Regex.Matches(outputTool, matchPattern);
20             foreach (Match match in mc)
21             {
22                 //有了pid,想把进程怎么弄就怎么弄。
23                 
24 
25             }

  这里还插一个题外话吧,就是在关进程的时候,用Process类的话有两种方式,一种比较温柔的CloseMainWindow()方法,另一种则是比较野蛮的,Kill()方法,除非WinForm程序的,只能比较野蛮了,之前听同事说是即使用了Kill(),进程还是会杀不干净的,对Kill()和CloseMainWindow()的内部实现机制还不了解,看那个同事是说用进程通讯去关的,要知道那个窗体标题,其实这样感觉挺像用CloseMainWindow()了,但单纯地用进程通讯去关也是有缺陷的,原本那窗体的标题叫Form1的,经过一系列操作之后窗体名改了,或者加上“(未响应)”,单纯写死一个标题太不科学了。用Process实例的MainWindowTitle属性就可以获取到主窗体的标题,可万一碰到的是子窗体用ShowDialog的形式启动时,想关闭子窗体时,CloseMainWindow()、Kill()、进程通讯都做不到了。用Process实例的MainWindowHandle属性可以获取进程的IntPtr对象,这个相当于在进程通信前调用系统API的FindWindow方法,这样用来发送一个WM_CLOSE消息也跟使用MainWindowTitle属性调用FindWindow的差不多,使用IntPtr对象的适用范围更广,其实用Kill()还是用WM_CLOSE消息,哪个强力一点,干净一点,我真知道,如果Kill()万一跟WM_CLOSE效果差不多的话,那也是Kill方便,免了声明系统API方法,IntPtr或标题那几个操作。求高人点。

posted @ 2013-05-13 08:10  猴健居士  阅读(3069)  评论(3编辑  收藏  举报