UnauthorizedAccessException 时如何跳过目录或文件
How to skip directory or file when UnauthorizedAccessException
我正在编写一个应用程序,用于从特定路径(包括系统路径,例如 Windows 目录、Program Files、Application Data 等)检查计算机是否有病毒
用户将单击按钮 "Start scan",将开始检查系统文件(包括 Windows/ProgramFiles 目录)是否有病毒,将文件与名为 "viruslist.txt" 的文本文件的 MD5 哈希进行比较
但是,我遇到了一些 UnauthorizedAccessException 错误问题。当检测到无法访问的文件时,应用程序将停止。
我希望应用程序跳过被拒绝的文件并转到特定路径中的下一个文件。
我的代码如下:
后台工作代码:
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
另外,按钮代码(开始扫描):
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- 用于显示检测到的感染对象。
我尝试了以下方法:
- 将应用的清单更改为 "requireAdministrator" 和 "highestavailable" ;
- 正在禁用 UAC。
到目前为止没有任何效果!
更新
感谢 JQSOFT 为我的问题提供解决方案。下面的解决方案肯定会帮助很多遇到同样问题的人。这个问题已经解决了。
这里有几点。
'Set this to True in the Cancel button...
Private cancel As Boolean
Sub New()
InitializeComponent()
'...
BackgroundWorker1.WorkerReportsProgress = True
BackgroundWorker1.WorkerSupportsCancellation = True
End Sub
使用此迭代器函数获取授权的文件和文件夹:
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
开始扫描按钮
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
BackgroundWorker
事件:
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
我正在编写一个应用程序,用于从特定路径(包括系统路径,例如 Windows 目录、Program Files、Application Data 等)检查计算机是否有病毒
用户将单击按钮 "Start scan",将开始检查系统文件(包括 Windows/ProgramFiles 目录)是否有病毒,将文件与名为 "viruslist.txt" 的文本文件的 MD5 哈希进行比较
但是,我遇到了一些 UnauthorizedAccessException 错误问题。当检测到无法访问的文件时,应用程序将停止。
我希望应用程序跳过被拒绝的文件并转到特定路径中的下一个文件。
我的代码如下: 后台工作代码:
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
另外,按钮代码(开始扫描):
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- 用于显示检测到的感染对象。 我尝试了以下方法:
- 将应用的清单更改为 "requireAdministrator" 和 "highestavailable" ;
- 正在禁用 UAC。
到目前为止没有任何效果!
更新 感谢 JQSOFT 为我的问题提供解决方案。下面的解决方案肯定会帮助很多遇到同样问题的人。这个问题已经解决了。
这里有几点。
'Set this to True in the Cancel button...
Private cancel As Boolean
Sub New()
InitializeComponent()
'...
BackgroundWorker1.WorkerReportsProgress = True
BackgroundWorker1.WorkerSupportsCancellation = True
End Sub
使用此迭代器函数获取授权的文件和文件夹:
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
开始扫描按钮
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
BackgroundWorker
事件:
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