问题
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