2010-11-05 10 views
6

Zakładając Mam struktury folderów, takich jak:DirectoryInfo.Delete (prawda) nie usuwa Kiedy Struktura folder jest otwarty w Eksploratorze Windows

C:\MyTemp 
    - MySubFolder

Gdy próbuję usunąć to za pomocą:

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

Działa to dobrze, , chyba że mam Eksploratora Windows otwarty i patrzę na katalogu "MySubFolder". Następnie otrzymuję IOException Katalog nie jest pusty. - kliknięcie przycisku OK powoduje odrzucenie tej opcji, a następnie struktura folderów nie jest usuwana.

Jakieś przemyślenia na temat tego, w jaki sposób mogę uzyskać to, aby wykonać poprawnie (tj. Usunąć), nawet podczas uruchamiania tego kodu, mając otwartą listę folderów w Eksploratorze Windows?

+4

Należy pamiętać, że jest to standardowe zachowanie powłoki. Otrzymasz ten sam komunikat o błędzie z 'rmdir/S'. Domyślam się, że usunięcie w zasadzie nie powiedzie się, ponieważ Explorer nadal ma uchwyt do podfolderu otwartego. –

+0

@ 0xA3 - Nie jest spójny. Zobacz mój komentarz do odpowiedzi poniżej. Są przypadki, w których mogę usunąć folder podczas przeglądania go w Eksploratorze Windows, a następnie Explorer po prostu przechodzi do folderu nadrzędnego dziecka, które zostało usunięte. –

+0

@ToddMain Wiem, że to jest stare, ale naprawdę będę wdzięczny, jeśli umieścisz rozwiązanie tego problemu. –

Odpowiedz

1

Sprawdź to article. Wyjątek IOException może być generowany z otwartego uchwytu do katalogu: This open handle can result from enumerating directories and files, który jest dokładnie tym, co otwiera eksplorator. Wygląda na to, że aktualny komunikat o błędzie ma charakter ogólny.

+0

tak, przeczytałem, ale stwierdza, że ​​dotyczy tylko WinXP i wcześniejszych.po drugie, załóżmy pod * MySubfolder * mam inny podfolder o nazwie "Temp" i plik w nim o nazwie "mypic.jpg". Jeśli patrzę na folder "Temp" w Eksploratorze Windows i usuwam go (oraz plik jpg) za pomocą powyższego kodu, to usuwam. To było niespójne i nie jestem pewien, co z tym zrobić. –

2

Jedyny sposób można uzyskać to do „pracy” 100% konsekwentnie jest przez nuking Explorer (zły pomysł) lub nuking uchwyt (also bad idea)

Moja rekomendacja byłoby po prostu obsłużyć awarii wdzięcznie w przeciwieństwie do prób to.

1

Najlepiej można zrobić, to złapać błąd, a następnie użyć handle.exe aby dowiedzieć się, które proces jest za pomocą pliku i poprosić użytkownika, aby zamknąć aplikację z opcji ponownego lub anulować.

Czy kiedykolwiek zastanawiałeś się, który program ma otwarty konkretny plik lub katalog? Teraz możesz się dowiedzieć. Handle to narzędzie wyświetlające informacje o otwartych uchwytach dla dowolnego procesu w systemie. Możesz go użyć, aby zobaczyć programy, które mają otwarty plik lub zobaczyć typy obiektów i nazwy wszystkich uchwytów programu.

Niektóre więcej informacji tutaj:

How to monitor process' IO activity using C#?

0

wymyśliłem następujący DirectoryInfo metodę rozszerzenia, które owija sposób natywny DirectoryInfo.Delete() i stara się „bezpiecznie usuwać” określonego folderu:

metoda ta wymaga następującego odwołanie COM: Kontroluje 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 
Powiązane problemy