2010-11-05 240 views
6

假设我有一个文件夹结构,如:DirectoryInfo.Delete(真),不删除当文件夹结构打开Windows资源管理器

C:\MyTemp 
    - MySubFolder

如果我尝试删除使用:

Dim path As String = "C:\MyTemp" 
Dim di As System.IO.DirectoryInfo 
di = System.IO.Directory.CreateDirectory(path) 
di.CreateSubdirectory("MySubFolder") 
di.Delete(True) 

这工作正常,除非我有Windows资源管理器打开,我正在看'MySubFolder'目录。然后我得到一个IOException 该目录不是空的。 - 单击“确定”即可解除此操作,然后文件夹结构不会被删除。

即使在Windows资源管理器中打开文件夹结构时运行此代码,我如何才能正确执行(即删除)任何想法?

+4

请注意,这是shell的标准行为。你将从'rmdir/S'得到同样的错误信息。我想删除基本上失败,因为资源管理器仍然有处理子文件夹打开。 – 2010-11-05 00:40:47

+0

@ 0xA3 - 这是不一致的。请参阅我对以下答案的评论。在某些情况下,我可以在Windows资源管理器中查看文件夹时删除文件夹,然后资源管理器仅导航到已删除子文件的父文件夹。 – 2010-11-05 00:44:01

+0

@ToddMain我知道这是旧的,但如果你能为此发布解决方案,我将非常感激。 – 2017-10-04 22:31:16

回答

1

看看这个article。 IOException可以从打开的句柄生成到目录:This open handle can result from enumerating directories and files,这正是在浏览器中打开的内容。听起来像实际的错误信息是通用的。

+0

是的,我已经读过,但它表明它只适用于WinXP和更早版本。其次,假设在* MySubfolder下*我有另一个名为“Temp”的子文件夹和一个名为“mypic.jpg”的文件。如果我正在查看Windows资源管理器中的“Temp”文件夹并使用上面的代码删除它(和jpg),它会删除。这是不一致的,我不知道该怎么办。 – 2010-11-05 00:42:23

2

您唯一能得到这个“工作” 100%一贯是的摧毁探险家(好主意)或的摧毁手柄(also bad idea

我的建议是只处理失败正常而不是试图这个。

1

你能做的最好的是捕获错误,然后使用handle.exe找出哪些进程正在使用的文件,并要求用户关闭与选项的应用重试取消

有没有想过哪个程序打开了某个文件或目录?现在你可以找到。 Handle是一个实用程序,显示有关系统中任何进程的打开句柄的信息。您可以使用它来查看打开文件的程序,或查看程序所有句柄的对象类型和名称。

一些更多的信息在这里:

How to monitor process' IO activity using C#?

0

我想出了包装了原生DirectoryInfo.Delete()方法,并试图“安全删除”指定的文件夹下面的DirectoryInfo扩展方法:

此方法需要以下COM参考:Microsoft Internet控制 COM Reference: Microsoft Internet Controls X


    '''' <summary> 
    '''' Attempts to perform a "Safe delete" by searching for any Windows File Explorer instances attached to the extended DirectoryInfo Object 
    '''' and navigate those instances off the current DirectoryInfo path in an attempt to prevent a "Directory is not empty" IOException when 
    '''' calling DirectoryInfo.Delete(recursive). 
    '''' </summary> 
    '''' <param name="DirectoryInfo">The DirectoryInfo object being extended</param> 
    '''' <param name="recursive">Optional: true to delete this directory, its subdirectories, and all files; otherwise false</param> 
    '''' <returns>A Boolean indicating whether the DirectoryInfo.Delete(recursive) operation completed without an Exception</returns> 
    '''' <remarks>Authored by CMC 2013-05-06 12:04:25 PM</remarks> 
    <System.Runtime.CompilerServices.Extension()> _ 
    Public Function TrySafeDelete(ByVal [DirectoryInfo] As DirectoryInfo, Optional ByVal recursive As Boolean = False, Optional ByVal retryCount As Integer = 0) As Boolean 
     Const maxRetryCount As Integer = 10 
     retryCount = If(retryCount < 0, 0, retryCount) 
     Dim success As Boolean = True 
     If ([DirectoryInfo] IsNot Nothing) Then 
      [DirectoryInfo].Refresh() 
      Dim msWinShellIExplorerWindowsLockingCurrentDirectory As Dictionary(Of SHDocVw.InternetExplorer, DirectoryInfo) = New Dictionary(Of SHDocVw.InternetExplorer, DirectoryInfo) 
      If ([DirectoryInfo].Exists()) Then 
       Try 
        Dim msWinShellIExplorerWindows As SHDocVw.ShellWindows = New SHDocVw.ShellWindows() 
        For Each msWinShellIExplorerWindow As SHDocVw.InternetExplorer In msWinShellIExplorerWindows 
         If (msWinShellIExplorerWindow.Name.Equals("windows explorer", StringComparison.OrdinalIgnoreCase)) Then 
          Dim locationValue As String = msWinShellIExplorerWindow.LocationURL() 
          If (locationValue.Length() > 0) Then 
           Dim locationURI As Uri = Nothing 
           If (Uri.TryCreate(locationValue, UriKind.RelativeOrAbsolute, locationURI)) Then 
            Dim msWinShellDirectoryInfo As DirectoryInfo = New DirectoryInfo(locationURI.LocalPath()) 
            Dim isLockingCurrentDirectory As Boolean = msWinShellDirectoryInfo.FullName.ToLower().Contains([DirectoryInfo].FullName.ToLower()) 
            If (isLockingCurrentDirectory AndAlso Not msWinShellIExplorerWindowsLockingCurrentDirectory.ContainsKey(msWinShellIExplorerWindow)) Then msWinShellIExplorerWindowsLockingCurrentDirectory.Add(msWinShellIExplorerWindow, msWinShellDirectoryInfo) 
           End If 
          End If 
         End If 
        Next 

        Dim navigateCompleteCount As Integer = 0 
        If (msWinShellIExplorerWindowsLockingCurrentDirectory.Any()) Then 
         For Each msWinShellDirectoryEntry As KeyValuePair(Of SHDocVw.InternetExplorer, DirectoryInfo) In msWinShellIExplorerWindowsLockingCurrentDirectory 
          Dim msWinShellIExplorerWindow As SHDocVw.InternetExplorer = msWinShellDirectoryEntry.Key() 
          Dim msWinShellDirectoryInfo As DirectoryInfo = msWinShellDirectoryEntry.Value() 
          AddHandler msWinShellIExplorerWindow.NavigateComplete2, New SHDocVw.DWebBrowserEvents2_NavigateComplete2EventHandler(Sub(pDisp As Object, ByRef URL As Object) 
                                        navigateCompleteCount += 1 
                                        If (navigateCompleteCount.Equals(msWinShellIExplorerWindowsLockingCurrentDirectory.Count())) Then 
                                         With [DirectoryInfo] 
                                          .Delete(recursive) 
                                          .Refresh() 
                                         End With 
                                        End If 
                                       End Sub) 
          msWinShellIExplorerWindow.Navigate2(New Uri(msWinShellDirectoryInfo.Root.FullName()).AbsoluteUri()) 
         Next 
        Else 
         With [DirectoryInfo] 
          .Delete(recursive) 
          .Refresh() 
         End With 
        End If 
       Catch ex As Exception 
       End Try 

       [DirectoryInfo].Refresh() 
       If ([DirectoryInfo].Exists() AndAlso (retryCount <= maxRetryCount)) Then 
        [DirectoryInfo].TrySafeDelete(recursive, retryCount + 1) 
       End If 
       success = Not DirectoryInfo.Exists() 
      End If 
     End If 
     Return success 
    End Function 
相关问题