title: How to close existing handle on file in C#
body: <p>How can I close an existing handle on a file in C#? Is it possible? </p>
  
  <p>Suppose I run code with administrator account? Can I just force the file to be closed?</p>
  
  <p>In another post, one of the answer was to use interop:</p>
  
  <pre><code>[Flags]
  enum MoveFileFlags {
      MOVEFILE_REPLACE_EXISTING = 0x00000001,
      MOVEFILE_COPY_ALLOWED = 0x00000002,
      MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004,
      MOVEFILE_WRITE_THROUGH = 0x00000008,
      MOVEFILE_CREATE_HARDLINK = 0x00000010,
      MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x00000020
  }
  [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
  static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, MoveFileFlags dwFlags);
  
  static void delete() {
      string fileName = @"c:\temp\test.xlsx";
      bool success = false;
      foreach(var e in Enum.GetNames(typeof(MoveFileFlags))) {
          success = MoveFileEx(fileName, null, (MoveFileFlags) Enum.Parse(typeof(MoveFileFlags), e));
          MessageBox.Show(string.Format("{0} success : {1}", e, success));
      }
  }
  </code></pre>
  
  <p>This solutions is not working. We need to reboot to delete the file.</p>
  
  <p>Another example tells to kill the process:</p>
  
  <pre><code>string fileName = @"c:\aaa.doc"; //Path to locked file
  
  Process tool = new Process();
  tool.StartInfo.FileName = "handle.exe";
  tool.StartInfo.Arguments = fileName;
  tool.StartInfo.UseShellExecute = false;
  tool.StartInfo.RedirectStandardOutput = true;
  tool.Start();
  tool.WaitForExit();
  string outputTool = tool.StandardOutput.ReadToEnd();
  
  string matchPattern = @"(?&lt;=\s+pid:\s+)\b(\d+)\b(?=\s+)";
  foreach(Match match in Regex.Matches(outputTool, matchPattern)) {
      Process.GetProcessById(int.Parse(match.Value)).Kill();
  }
  </code></pre>
  
  <p>The problem is I don't want to kill the process, since the process that locks the file is IIS or Explorer.</p>
  
  <p>I need to refresh file of a web site.</p>
  
  <p>This is the solutions that I'm using and it is working fine:</p>
  
  <pre><code>static void delete(string fileName) {
      string handleTools = Path.Combine(Application.StartupPath, "handle.exe");
      Process tool = new Process();
      tool.StartInfo.FileName = handleTools;
      tool.StartInfo.Arguments = fileName;
      tool.StartInfo.UseShellExecute = false;
      tool.StartInfo.RedirectStandardOutput = true;
      tool.Start();
      tool.WaitForExit();
  
      string outputTool = tool.StandardOutput.ReadToEnd();
      Regex reg = new Regex(@"(?&lt;pid&gt;pid:\s+[0-9]*)\s*(?&lt;type&gt;type:\s+\w*)\s*(?&lt;handle&gt;[A-F0-9]*:\s+)");
      Match match = reg.Match(outputTool);
      string pid = null;
      string handle = null;
  
      if (match.Groups["pid"].Value != null) {
          pid = match.Groups["pid"].Value;
          if (!string.IsNullOrEmpty(pid)) {
              pid = pid.Replace("pid: ", string.Empty);
          }
      }
      if (match.Groups["handle"].Value != null) {
          handle = match.Groups["handle"].Value;
          if (!string.IsNullOrEmpty(handle)) {
              handle = handle.Replace("handle: ", string.Empty).Replace(":", string.Empty);
          }
      }
      if (!string.IsNullOrEmpty(handle) &amp;&amp; !string.IsNullOrEmpty(pid)) {
          tool = new Process();
          tool.StartInfo.FileName = handleTools;
          tool.StartInfo.Arguments = string.Format("-p {0} -c {1} -y", pid, handle);
          tool.StartInfo.UseShellExecute = false;
          tool.StartInfo.RedirectStandardOutput = true;
          tool.Start();
          tool.WaitForExit();
          File.Delete(fileName);
      }
  }
  </code></pre>
  
  <p>To use this solutions you will need to use <a href="http://technet.microsoft.com/en-us/sysinternals/bb896655.aspx" rel="nofollow">handle.exe</a> from sysinternal</p>