8

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

C:\MyTemp
   - 我的子文件夹

如果我尝试使用以下方法删除它:

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

4 回答 4

2

唯一能让这个“工作”100% 始终如一的方法是对 explorer 进行核对(坏主意)或对句柄进行核对(也是个坏主意

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

于 2010-11-05T00:54:31.690 回答
1

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

于 2010-11-05T00:35:48.150 回答
1

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

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

这里有更多信息:

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

于 2010-11-05T01:13:39.070 回答
0

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

此方法需要以下 COM 参考:Microsoft Internet Controls 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
于 2013-11-14T21:15:05.480 回答