【问题标题】:How to close a file that is already opened in a directory如何关闭已在目录中打开的文件
【发布时间】:2012-10-04 14:37:42
【问题描述】:

我正在尝试解析一个文件夹并删除其中的所有文件。

DirectoryInfo dir = new DirectoryInfo("C\\Temp");
if (dir.GetDirectories().Any(p => p.Name == "\\NewTemp"))
{
    foreach (string file in Directory.GetFiles(dir + "\\NewTemp"))
    {
        File.SetAttributes(file, FileAttributes.Normal);
        File.Delete(file);
    }
}

此代码运行良好,并删除了我的 \NewTemp 文件夹中的所有文件。但是,如果打开任何文件,这些文件将不会被删除。我想强制关闭打开的文件并删除它们。我什至尝试过

foreach (string file in Directory.GetFiles(dir + "\\NewTemp"))
{
    TextReader tr = new StreamReader(dir+"\\NewTemp\\"+file);
    tr.Close();
    File.SetAttributes(file, FileAttributes.Normal);
    File.Delete(file);
}

但是没有用。请让我知道我在哪里失踪。

【问题讨论】:

  • 我很确定有这个命令行实用程序,您可以使用它来获取所有打开特定文件的进程,我也很确定您可以从 c# 中杀死这些进程跨度>
  • tr 正在尝试关闭文件 TextReader tr = new StreamReader(file)。我打错字了
  • stackoverflow.com/questions/177146/… 托管代码并不太简单。在这个答案中,有一个指向 Codeproject 上的 proget 的链接可以帮助你。

标签: c# file directory delete-file


【解决方案1】:

请让我知道我在哪里失踪。

好吧,您正在关闭文件上的您的句柄-但这不会影响任何其他文件句柄,无论它们是否属于您的进程。基本上你不能删除在别处使用的文件,除非它是用允许删除的文件共享标志显式打开的。据我所知,这正是 Windows 文件系统的工作方式。 (编辑:我最初建议使用记事本作为保持文件句柄打开的一种方式,但显然它在将句柄加载到内存后会关闭句柄。嗯,尝试其他应用程序 :)

【讨论】:

  • 嗯,实际上您可以从资源管理器中删除您在记事本中打开的文件。这完全取决于您打开文件的文件共享...所以,有时您可以删除其他地方正在使用的文件。这完全取决于打开文件所需的应用程序的 FileShare 级别。
  • 我相信你可以强制关闭文件句柄(任何文件句柄),我用过可以做到这一点的程序。我不认为有任何 .Net 函数可以做到这一点,因此您可能需要深入研究 Windows API 以获得答案。
  • 这实际上是一个不好的例子。记事本读取文件,然后将其关闭。您可以删除使用记事本打开的文件,而无需先关闭记事本。
  • 记事本示例不正确。记事本不会保持手柄打开。它将所有文本加载到内存中并释放句柄。即使记事本打开,您也可以删除文件。
  • @Kratz:这是一项非常重要的任务。您需要以某种方式获取持有文件句柄的进程并让这些进程关闭该句柄。没有单独的 WinAPI 函数。
【解决方案2】:

如果句柄已被另一个进程打开,则无法删除文件。您必须先终止该进程,然后才能删除文件。

你可以看看这个example to see how to find all open handles.

【讨论】:

    【解决方案3】:

    这是一个方便的工具,用于查找哪个进程具有文件句柄:

    http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx

    【讨论】:

      【解决方案4】:

      如果你知道是哪个程序打开了你的文件,你可以直接just taskkill那个程序,然后删除你的文件。

      如果您不知道打开文件的进程是什么,则可以使用a utility like this,然后处理输出。我自己会重定向输出,然后使用正则表达式来查找我想要获得的过程,但可能有更好的方法。

      请记住,这种方法并不完全安全,并且可能会杀死您不想杀死的进程。

      【讨论】:

        【解决方案5】:

        这些是您的选择,按照您应该尝试的顺序(从侵入性最小到侵入性强)。

        1. 做你目前正在做的事情(删除只读属性并尝试删除文件)。
        2. 您可以尝试重命名文件,然后将其删除。
        3. 如果这不起作用,那么您应该打开带有FILE_FLAG_DELETE_ON_CLOSE 标志的文件(pinvoke 到CreateFile)。当文件的所有其他句柄都关闭时,系统将为您删除文件。
        4. 如果上面对 CreateFile 的调用失败,因为文件不是用FILE_SHARE_DELETE 打开的,那么你应该调用MoveFileEx 并带有MOVEFILE_DELAY_UNTIL_REBOOT 标志(并且lpNewFileName 参数设置为NULL / IntPtr.Zero)。这将导致该文件在系统下次重新启动/重启时被删除。
        5. 如果步骤 4 不可行(即您不能等待重新启动),那么只有这样才能继续执行杀死可能已锁定文件的随机进程的路径。请记住,这可能会导致系统不稳定,特别是如果它是您试图杀死的系统进程。

        【讨论】:

          【解决方案6】:
          foreach (System.Diagnostics.Process myProc in System.Diagnostics.Process.GetProcesses())
          {
              if (myProc.ProcessName == "EXCEL")
              {
                  myProc.Kill();
                  break;
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2013-03-18
            • 2014-08-20
            • 1970-01-01
            • 2020-05-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多