【问题标题】:How to close existing handle on file in C#如何在 C# 中关闭文件上的现有句柄
【发布时间】:2011-12-30 16:33:53
【问题描述】:

如何在 C# 中关闭文件的现有句柄?可能吗?

假设我使用管理员帐户运行代码?我可以强制关闭文件吗?

在另一篇文章中,答案之一是使用互操作:

[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));
    }
}

此解决方案不起作用。我们需要重启才能删除文件。

另一个例子告诉终止进程:

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 = @"(?<=\s+pid:\s+)\b(\d+)\b(?=\s+)";
foreach(Match match in Regex.Matches(outputTool, matchPattern)) {
    Process.GetProcessById(int.Parse(match.Value)).Kill();
}

问题是我不想杀死进程,因为锁定文件的进程是 IIS 或资源管理器。

我需要刷新一个网站的文件。

这是我正在使用的解决方案,它工作正常:

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(@"(?<pid>pid:\s+[0-9]*)\s*(?<type>type:\s+\w*)\s*(?<handle>[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) && !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);
    }
}

要使用此解决方案,您需要使用来自 sysinternal 的handle.exe

【问题讨论】:

  • 你是怎么搞定的?
  • @parapura rajkumar ,实际上我不知道如何获取句柄。但我想有办法拿到把手并关闭它
  • 为什么会被否决?只需将其标记为 dup。
  • @CédricBoivin google.com/…

标签: c# file .net-4.0 handle


【解决方案1】:
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-25
  • 2011-08-16
  • 2018-12-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多