2010-11-05 17 views
6

En supposant que j'ai une structure de dossiers comme:DirectoryInfo.Delete (Vrai) ne supprime pas lorsque la structure du dossier est ouvert dans l'Explorateur Windows

C:\MyTemp 
    - MySubFolder

Si je tente de supprimer cela en utilisant:

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

Cela fonctionne très bien, sauf si j'ai Windows Explorer ouvert et je regarde le répertoire 'MySubFolder'. Ensuite, je reçois une IOException Le répertoire n'est pas vide. - le fait de cliquer sur OK le supprime et la structure du dossier n'est pas supprimée.

Y a-t-il des réflexions sur la façon dont je peux obtenir ce résultat correctement (c'est-à-dire supprimer), même lors de l'exécution de ce code alors que la structure du dossier est ouverte dans Windows Explorer?

+4

Notez qu'il s'agit d'un comportement standard du shell. Vous obtiendrez le même message d'erreur de 'rmdir/S'. Je suppose que la suppression échoue fondamentalement car Explorer a toujours un handle pour le sous-dossier ouvert. –

+0

@ 0xA3 - Ce n'est pas cohérent. Voir mon commentaire sur la réponse ci-dessous. Il y a des cas où je peux supprimer un dossier tout en le regardant dans l'Explorateur de Windows et qu'Explorer juste navs au dossier parent de l'enfant qui a été supprimé. –

+0

@ToddMain Je sais que c'est vieux mais j'apprécierai vraiment si vous pouvez poster la solution pour ceci. –

Répondre

1

Consultez ce article. IOException peut être généré à partir d'un handle ouvert vers le répertoire: This open handle can result from enumerating directories and files, ce qui est exactement ce que l'ouverture dans l'explorateur fait. On dirait que le message d'erreur réel est générique.

+0

ouais, j'avais lu cela, mais il indique qu'il ne s'applique qu'à WinXP et plus tôt.deuxièmement, supposons sous un * MySubfolder * j'ai un autre sous-dossier appelé "Temp" et un fichier appelé "mypic.jpg". Si je regarde le dossier "Temp" dans Windows Explorer et le supprime (et le jpg) en utilisant le code ci-dessus, il supprime. Cela a été irrégulier et je ne suis pas sûr de savoir quoi faire à ce sujet. –

2

La seule façon que vous pouvez obtenir ce « travail » 100% est toujours par l'explorateur nuking (mauvaise idée) ou nuking la poignée (also bad idea)

Ma recommandation serait de gérer simplement l'échec grâce plutôt que d'essayer ce.

1

Le mieux que vous pouvez faire est attraper l'erreur puis utilisez handle.exe pour savoir quel processus utilise le fichier et demander à l'utilisateur de fermer l'application avec des options pour nouvelle tentative ou cancel.

Vous êtes-vous déjà demandé quel programme avait ouvert un fichier ou un répertoire particulier? Maintenant, vous pouvez le découvrir. Handle est un utilitaire qui affiche des informations sur les handles ouverts pour tout processus du système. Vous pouvez l'utiliser pour voir les programmes qui ont un fichier ouvert, ou pour voir les types d'objets et les noms de toutes les poignées d'un programme.

Un peu plus d'info ici:

How to monitor process' IO activity using C#?

0

je suis venu avec la méthode d'extension DirectoryInfo suivante qui enveloppe la méthode DirectoryInfo.Delete native() et tente de "supprimer en toute sécurité" dans le dossier spécifié:

Cette méthode nécessite la référence COM suivantes: Microsoft Internet Controls COM Reference: Microsoft Internet Controls x 01


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