2010-11-05 239 views
6

假設我有一個文件夾結構,如:DirectoryInfo.Delete(真),不刪除當文件夾結構打開Windows資源管理器

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 該目錄不是空的。 - 單擊「確定」即可解除此操作,然後文件夾結構不會被刪除。

即使在Windows資源管理器中打開文件夾結構時運行此代碼,我如何才能正確執行(即刪除)任何想法?

+4

請注意,這是shell的標準行爲。你將從'rmdir/S'得到同樣的錯誤信息。我想刪除基本上失敗,因爲資源管理器仍然有處理子文件夾打開。 – 2010-11-05 00:40:47

+0

@ 0xA3 - 這是不一致的。請參閱我對以下答案的評論。在某些情況下,我可以在Windows資源管理器中查看文件夾時刪除文件夾,然後資源管理器僅導航到已刪除子文件的父文件夾。 – 2010-11-05 00:44:01

+0

@ToddMain我知道這是舊的,但如果你能爲此發佈解決方案,我將非常感激。 – 2017-10-04 22:31:16

回答

1

看看這個article。 IOException可以從打開的句柄生成到目錄:This open handle can result from enumerating directories and files,這正是在瀏覽器中打開的內容。聽起來像實際的錯誤信息是通用的。

+0

是的,我已經讀過,但它表明它只適用於WinXP和更早版本。其次,假設在* MySubfolder下*我有另一個名爲「Temp」的子文件夾和一個名爲「mypic.jpg」的文件。如果我正在查看Windows資源管理器中的「Temp」文件夾並使用上面的代碼刪除它(和jpg),它會刪除。這是不一致的,我不知道該怎麼辦。 – 2010-11-05 00:42:23

2

您唯一能得到這個「工作」 100%一貫是的摧毀探險家(好主意)或的摧毀手柄(also bad idea

我的建議是隻處理失敗正常而不是試圖這個。

1

你能做的最好的是捕獲錯誤,然後使用handle.exe找出哪些進程正在使用的文件,並要求用戶關閉與選項的應用重試取消

有沒有想過哪個程序打開了某個文件或目錄?現在你可以找到。 Handle是一個實用程序,顯示有關係統中任何進程的打開句柄的信息。您可以使用它來查看打開文件的程序,或查看程序所有句柄的對象類型和名稱。

一些更多的信息在這裏:

How to monitor process' IO activity using C#?

0

我想出了包裝了原生DirectoryInfo.Delete()方法,並試圖「安全刪除」指定的文件夾下面的DirectoryInfo擴展方法:

此方法需要以下COM參考: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 
相關問題