DirectoryInfo.Delete (True) не удаляется при открытой структуре папок в проводнике Windows - PullRequest
7 голосов
/ 05 ноября 2010

Предполагая, что у меня есть структура папок, такая как:

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 Каталог не пустой. - нажатие кнопки OK отклоняет это, а затем структура папки не удаляется.

Любые мысли о том, как я могу заставить это работать правильно (т.е.удалить), даже при запуске этого кода, когда папка struture открыта в проводнике Windows?

Ответы [ 4 ]

2 голосов
/ 05 ноября 2010

Единственный способ добиться того, чтобы это работало на 100% последовательно, - это использовать нуклер-эксплорер (плохая идея) или нюхать дескриптор ( также плохая идея )

Я бы порекомендовал просто изящно обработать ошибку, а не пытаться это сделать.

1 голос
/ 05 ноября 2010

Лучшее, что вы можете сделать, это перехватить ошибку и затем использовать handle.exe , чтобы выяснить, какой процесс использует файл, и попросить пользователя закрыть приложение с параметрами retry * 1004. * или отмена .

Вы когда-нибудь задумывались, в какой программе открыт конкретный файл или каталог? Теперь вы можете узнать. Дескриптор - это утилита, которая отображает информацию об открытых дескрипторах для любого процесса в системе. Вы можете использовать его для просмотра программ, у которых открыт файл, или для просмотра типов объектов и имен всех дескрипторов программы.

Дополнительная информация здесь:

Как отслеживать активность ввода-вывода процесса с помощью C #?

1 голос
/ 05 ноября 2010

Ознакомьтесь с этой статьей .IOException может быть сгенерировано из открытого дескриптора в каталог: This open handle can result from enumerating directories and files, что именно то, что делает открытие в проводнике.Похоже, фактическое сообщение об ошибке является общим.

0 голосов
/ 15 ноября 2013

Я предложил следующий метод расширения DirectoryInfo, который оборачивает собственный метод DirectoryInfo.Delete () и пытается «безопасно удалить» указанную папку:

Этот метод требует следующую ссылку COM: Microsoft Internet Controls COM Reference:  Microsoft Internet Controls х


    '''' <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
...