簡體   English   中英

在Windows資源管理器中打開文件夾結構時,DirectoryInfo.Delete(True)不會刪除

[英]DirectoryInfo.Delete(True) Doesn't Delete When Folder Structure is Open in Windows Explorer

假設我有一個文件夾結構,如:

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資源管理器中打開文件夾結構時運行此代碼也是如此?

只有這樣你才能讓這個100%一致地“工作”是通過nuking explorer(壞主意)或nuking手柄( 也是壞主意

我的建議是優雅地處理失敗而不是嘗試這個。

看看這篇文章 IOException可以從目錄的打開句柄生成: This open handle can result from enumerating directories and files ,這正是資源管理器中的開放。 聽起來像實際的錯誤消息是通用的。

您可以做的最好的方法是捕獲錯誤,然后使用handle.exe找出正在使用該文件的進程,並要求用戶使用重試取消選項關閉應用程序。

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

這里有更多信息:

如何使用C#監控進程的IO活動?

我想出了以下DirectoryInfo擴展方法,它包裝了本機DirectoryInfo.Delete()方法並嘗試“安全地刪除”指定的文件夾:

此方法需要以下COM引用:Microsoft Internet Controls COM參考: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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM