在Windows资源管理器中打开文件夹结构时,DirectoryInfo.Delete(True)不会删除

假设我有一个文件夹结构,如:

  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资源管理器中打开文件夹结构时运行此代码也是如此?

只有这样你才能让这个100%一致地“工作”是通过nuking explorer(坏主意)或nuking手柄( 也是坏主意 )

我的建议是优雅地处理失败而不是尝试这个。

看看这篇文章 。 IOException可以从目录的打开句柄生成: This open handle can result from enumerating directories and files ,这正是资源管理器中的开放。 听起来像实际的错误消息是通用的。

您可以做的最好的方法是捕获错误,然后使用handle.exe找出正在使用该文件的进程,并要求用户使用重试取消选项关闭应用程序。

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

这里有更多信息:

如何使用C#监控进程的IO活动?

我想出了以下DirectoryInfo扩展方法,该方法包装本机DirectoryInfo.Delete()方法并尝试“安全删除”指定的文件夹:

此方法需要以下COM引用:Microsoft Internet Controls COM参考:Microsoft Internet Controls X

 ''''  '''' 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). ''''  '''' The DirectoryInfo object being extended '''' Optional: true to delete this directory, its subdirectories, and all files; otherwise false '''' A Boolean indicating whether the DirectoryInfo.Delete(recursive) operation completed without an Exception '''' Authored by CMC 2013-05-06 12:04:25 PM  _ 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