How to skip directory or file when UnauthorizedAccessException

巧了我就是萌 提交于 2021-01-28 16:30:50

问题


I am writing an application which checks the computer for viruses from a specific path(including system paths, such as the Windows directory, Program Files, Application Data, etc)

The user will click a button "Start scan", will begin checking of system files(including Windows/ProgramFiles directories) for viruses, comparing files to MD5 hashes from a text files named "viruslist.txt"

However, I am having some issues with UnauthorizedAccessException errors. The application will stop when it detects a file which cannot be accessed.

I want the application to skip the denied files and move on to the next file in the specific path.

My code is as it follows: Backgroundworker Do Work code:

    Try
        For Each file As String In IO.Directory.EnumerateFiles(FolderBrowserDialog3.SelectedPath, IO.SearchOption.AllDirectories).Union(IO.Directory.EnumerateFiles(FolderBrowserDialog4.SelectedPath, "*", IO.SearchOption.AllDirectories))
            Try
                Dim scanbox As New TextBox
                Dim read As String = My.Computer.FileSystem.ReadAllText(System.AppDomain.CurrentDomain.BaseDirectory & "viruslist.txt")
                scanbox.Text = read.ToString
                Dim md5 As MD5CryptoServiceProvider = New MD5CryptoServiceProvider
                Dim f As FileStream = New FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, 8192)
                f = New FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, 8192)
                md5.ComputeHash(f)
                Dim hash As Byte() = md5.Hash
                Dim buff As StringBuilder = New StringBuilder
                Dim hashByte As Byte
                For Each hashByte In hash
                    buff.Append(String.Format("{0:X2}", hashByte))
                Next

                If scanbox.Text.Contains(buff.ToString) Then

                    AddListItem2(ListBox2, "" & file & "")
                End If
            Catch ex As Exception
            End Try
            '   SetLabelText_ThreadSafe(Me.Label1, "" & file & "")
            If (BackgroundWorker1.CancellationPending = True) Then

                e.Cancel = True
                Exit For
            End If
            SetLabelText_ThreadSafe(Me.Labelscannedfiles, file & "")
            int = int + 1
            SetLabelText_ThreadSafe(Me.Label2, int & " Out Of " & filecount & "")
            Dim pct As Integer = (int / filecount * 100)
            BackgroundWorker1.ReportProgress(pct)
        Next file
  Catch ex as unauthorizedaccessexception

Also, the button code(start scan):

 FolderBrowserDialog3.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.Windows)

        Try
            For Each strDir As String In
                System.IO.Directory.GetDirectories(FolderBrowserDialog3.SelectedPath)

                For Each strFile As String In System.IO.Directory.GetFiles(strDir)



                Next
            Next
        Catch ex As Exception

Listbox2- used to display detected infected objects. I've tried the following:

  • Changing the app's manifest to "requireAdministrator" and "highestavailable" ;
  • Disabling UAC .

Nothing worked so far!

UPDATE Thanks to JQSOFT for providing the solution to my issue. The below solution will surely help a lot of people who have the same issue I had. This question has been solved.


回答1:


Here's some points.

'Set this to True in the Cancel button...
Private cancel As Boolean

Sub New()
    InitializeComponent()
    '...

    BackgroundWorker1.WorkerReportsProgress = True
    BackgroundWorker1.WorkerSupportsCancellation = True
End Sub

Use this iterator function to get the authorized files and folders:

Private Iterator Function IterateFolders(startDir As String, 
                                         includeFiles As Boolean, 
                                         includeSubDir As Boolean) As IEnumerable(Of String)
    Try
        For Each dirName In Directory.EnumerateDirectories(startDir)
            Yield dirName

            Try
                If includeFiles Then
                    For Each fileName In Directory.EnumerateFiles(startDir)
                        Yield fileName
                    Next
                End If

                If includeSubDir Then
                    For Each subDir In IterateFolders(dirName, includeFiles, includeSubDir)
                        Yield subDir
                    Next
                End If
            Catch ex As UnauthorizedAccessException
            Catch ex As Exception
            End Try
        Next
    Catch ex As UnauthorizedAccessException
    Catch ex As Exception
    End Try
End Function

The start scan button

Private Sub Scan_Click(sender As Object, e As EventArgs) Handles Scan.Click
    If BackgroundWorker1.IsBusy Then Return
    Using fbd As New FolderBrowserDialog
        If fbd.ShowDialog = DialogResult.OK Then
            cancel = False
            '...
            BackgroundWorker1.RunWorkerAsync(fbd.SelectedPath)
        End If
    End Using
End Sub

The BackgroundWorker events:

Private Sub BackgroundWorker1_DoWork(sender As Object,
                                     e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    Dim dir = e.Argument.ToString

    For Each file In IterateFolders(dir, True, True).
            Where(Function(f) IO.File.Exists(f)) '<- To get the files only.
        If cancel Then
            e.Cancel = True
            Return
        End If

        Try

            Dim b As Boolean = False

            Using md5 As New MD5CryptoServiceProvider,
                f As FileStream = New FileStream(file, 
                                             FileMode.Open, 
                                             FileAccess.Read, 
                                             FileShare.Read, 8192)

                md5.ComputeHash(f)

                Dim hash As Byte() = md5.Hash
                Dim buff As New StringBuilder
                Dim hashByte As Byte

                For Each hashByte In hash
                    buff.Append(String.Format("{0:X2}", hashByte))
                Next

                b = IO.File.ReadLines("...FullPathOf\viruslist.txt").
                Any(Function(x) x = buff.ToString)
            End Using

            'The main thread...
            Invoke(New Action(Sub()
                                    If b Then ListBox2.Items.Add(file)
                                    Labelscannedfiles.Text = ....
                                    Label2.Text = $"{int} Out of {filecount}"
                              End Sub))

            'Code to update the progress here...
        Catch ex As IOException
        Catch ex As Exception
        End Try
    Next
End Sub

Private Sub BackgroundWorker1_ProgressChanged(sender As Object,
                                              e As ProgressChangedEventArgs) _
                                              Handles BackgroundWorker1.ProgressChanged
    'Update the progress...
End Sub

Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object,
                                                 e As RunWorkerCompletedEventArgs) _
                                                 Handles BackgroundWorker1.RunWorkerCompleted
    If e.Error IsNot Nothing Then
        'An error occurred
    ElseIf e.Cancelled Then
        'Operation canceled...
    Else
        'On success ....
    End If
End Sub


来源:https://stackoverflow.com/questions/61794996/how-to-skip-directory-or-file-when-unauthorizedaccessexception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!