C# 判斷文件是否被占用的三種方法
using System.IO; using System.Runtime.InteropServices; [DllImport("kernel32.dll")] public static extern IntPtr _lopen(string lpPathName, int iReadWrite); [DllImport("kernel32.dll")] public static extern bool CloseHandle(IntPtr hObject); public const int OF_READWRITE = 2; public const int OF_SHARE_DENY_NONE = 0x40; public readonly IntPtr HFILE_ERROR = new IntPtr(-1); private void button1_Click(object sender, EventArgs e) { string vFileName = @"c:\temp\temp.bmp"; if (!File.Exists(vFileName)) { MessageBox.Show("文件都不存在!"); return; } IntPtr vHandle = _lopen(vFileName, OF_READWRITE | OF_SHARE_DENY_NONE); if (vHandle == HFILE_ERROR) { MessageBox.Show("文件被占用!"); return; } CloseHandle(vHandle); MessageBox.Show("沒有被占用!"); }
上述方法容易導致未占用文件被過程占用了,不可取的檢查方案
public static bool IsFileInUse(string fileName) { bool inUse = true; FileStream fs = null; try { fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None); inUse = false; } catch { } finally { if (fs != null) fs.Close(); } return inUse;//true表示正在使用,false沒有使用 }
第三種方案
/// <summary> /// 返回指示文件是否已被其它程序使用的布爾值 /// </summary> /// <param name="fileFullName">文件的完全限定名,例如:“C:\MyFile.txt”。</param> /// <returns>如果文件已被其它程序使用,則為 true;否則為 false。</returns> public static Boolean FileIsUsed(String fileFullName) { Boolean result = false; //判斷文件是否存在,如果不存在,直接返回 false if (!System.IO.File.Exists(fileFullName)) { result = false; }//end: 如果文件不存在的處理邏輯 else {//如果文件存在,則繼續判斷文件是否已被其它程序使用 //邏輯:嘗試執行打開文件的操作,如果文件已經被其它程序使用,則打開失敗,拋出異常,根據此類異常可以判斷文件是否已被其它程序使用。 System.IO.FileStream fileStream = null; try { fileStream = System.IO.File.Open(fileFullName, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite, System.IO.FileShare.None); result = false; } catch (System.IO.IOException ioEx) { result = true; } catch (System.Exception ex) { result = true; } finally { if (fileStream != null) { fileStream.Close(); } } }//end: 如果文件存在的處理邏輯 //返回指示文件是否已被其它程序使用的值 return result; }//end method FileIsUsed
要檢測文件被那個進程占用,需要使用微軟提供的工具Handle.exe,這里有微軟提供的下載
我們可以在c#中調用Handle.exe 來檢測到底哪個進程占用了文件
string fileName = @"c:\aaa.doc";//要檢查被那個進程占用的文件 Process tool = new Process(); tool.StartInfo.FileName = "handle.exe"; tool.StartInfo.Arguments = fileName+" /accepteula"; tool.StartInfo.UseShellExecute = false; tool.StartInfo.RedirectStandardOutput = true; tool.Start(); tool.WaitForExit(); string outputTool = tool.StandardOutput.ReadToEnd(); string matchPattern = @"(?<=\s+pid:\s+)\b(\d+)\b(?=\s+)"; foreach(Match match in Regex.Matches(outputTool, matchPattern)) { Process.GetProcessById(int.Parse(match.Value)).Kill(); }