Как закрыть существующий дескриптор файла в C # - PullRequest
2 голосов
/ 16 ноября 2011

Как я могу закрыть существующий дескриптор файла в 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 или Explorer.

Мне нужно обновить файл веб-сайта.

Это решения, которые я использую, и работает нормально:

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

Чтобы использовать это решение, вам нужно использовать handle.exe от sysinternal

1 Ответ

2 голосов
/ 16 ноября 2011
...