我想出了包装了原生DirectoryInfo.Delete()方法,并试图“安全删除”指定的文件夹下面的DirectoryInfo扩展方法:
此方法需要以下COM参考:Microsoft Internet控制 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
请注意,这是shell的标准行为。你将从'rmdir/S'得到同样的错误信息。我想删除基本上失败,因为资源管理器仍然有处理子文件夹打开。 – 2010-11-05 00:40:47
@ 0xA3 - 这是不一致的。请参阅我对以下答案的评论。在某些情况下,我可以在Windows资源管理器中查看文件夹时删除文件夹,然后资源管理器仅导航到已删除子文件的父文件夹。 – 2010-11-05 00:44:01
@ToddMain我知道这是旧的,但如果你能为此发布解决方案,我将非常感激。 – 2017-10-04 22:31:16