Incorrect progressbar value reported by the backgroundworker - vb.net

I build an app, which searches for different files through the computer, including Windows, ProgramFiles, etc folders.
I've already done with the 'recursive' file search and it works now, this means all files/folders which are inaccessible will be skipped and the software will move on with the other available folders/files. But now, I have other issues...
The problem is that, for some odd reason, the application does not correctly report the progressbar value accordingly to the progress made in searching the files. This means that, the file search continues, BUT the progressbar is already 100%. The progressbar value SHOULD be 100% when the file search has been successfully completed.
====other code is already here ====
Dim int As Integer = 0
Dim filecount As Integer = 0
Private Function GetFilesRecursive(ByVal path As String) As List(Of String)
Dim lstResult As New List(Of String)
Dim stkStack As New Stack(Of String)
stkStack.Push(path)
Do While (stkStack.Count > 0)
Dim strDirectory As String = stkStack.Pop
Try
lstResult.AddRange(Directory.GetFiles(strDirectory, "*.*"))
Dim strDirectoryName As String
For Each strDirectoryName In Directory.GetDirectories(strDirectory)
stkStack.Push(strDirectoryName)
Next
Catch ex As Exception
End Try
Loop
Return lstResult
End Function
Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles Quickscan.DoWork
Try
Dim i As Integer
Dim files As List(Of String) = GetFilesRecursive(FolderBrowserDialog1.SelectedPath)
For Each file As String In files
Try
Dim scanbox As New TextBox
Dim read As String = My.Computer.FileSystem.ReadAllText(System.AppDomain.CurrentDomain.BaseDirectory & "db1.db")
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
AddListItem(Listbox2, "" & file)
AddListItem2(Listbox2, "" & file & "")
End If
Catch ex As Exception
End Try
If (Backgroundworker1.CancellationPending = True) Then
e.Cancel = True
Exit For
End If
SetLabelText_ThreadSafe(Me.Labelscannedfiles, file & "")
i = i + 1
SetLabelText_ThreadSafe(Me.Label2, i)
Dim pct As Integer = CInt(CDbl(i) / CDbl(files.Count) * 100)
Backgroundworker1.ReportProgress(pct)
Next file
Catch ex As UnauthorizedAccessException
End Try
Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles Backgroundworker1.ProgressChanged
Label28.Text = "Computer scan is in progress... Please wait"
ProgressBar1.Value = e.ProgressPercentage / 100
Any solution or help would be highly appreciated!

In your DoWork() method...
Change:
For Each file As String In GetFilesRecursive(FolderBrowserDialog1.SelectedPath)
To:
Dim i As Integer ' <- you didn't actually declare a counter before
Dim files As List(Of String) = GetFilesRecursive(FolderBrowserDialog1.SelectedPath)
For Each file As String In files
Now you can get the count from "files" and use that in your percentage calculation:
i = i + 1 ' <-- increment our "i" counter
SetLabelText_ThreadSafe(Me.Label2, i)
Dim pct As Integer = CInt(CDbl(i) / CDbl(files.Count) * 100)
backgroundworker1.ReportProgress(pct)

Related

Whats wrong with my filesystem watcher code VB.NET?

when my file system watcher detects a virus a dialog shows but when i click the delete file option it says its open in my program but in the filesystem watcher when i add the openfiledialog.Dispose function it doesnt show my dialog so heres the code can somone provide a fix? code below.
Private Sub FileSystemWatcher1_Changed(ByVal sender As System.Object, ByVal e As System.IO.FileSystemEventArgs) Handles FileSystemWatcher1.Changed
Try
Detect.Labellastreal.Text = e.FullPath
ListBox3.Items.Add(Detect.Labellastreal.Text)
Me.OpenFileDialog3.FileName = ""
Dim scanbox As New TextBox
scanbox.Text = My.Computer.FileSystem.ReadAllText(Application.StartupPath & "\VirusList.dat").ToString
Dim md5 As New MD5CryptoServiceProvider
Dim f As New FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read, &H2000)
f = New FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read, &H2000)
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
f.Close()
If scanbox.Text.Contains(buff.ToString) Then
Me.OpenFileDialog3.FileName = e.FullPath
Detect.ShowDialog()
WriteToLog("Virus detected")
End If
Catch exception1 As Exception
ProjectData.SetProjectError(exception1)
Dim ex As Exception = exception1
ProjectData.ClearProjectError()
End Try
End Sub
Firstly, don't even bother using that code. FileSystemWatcher is unreliable, and fails lots of the time.
Secondly, remove f = New FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read, &H2000), as you're calling it twice.
Lastly, for a Visual Basic anti-virus with real-time protection, I recommend you use this code:
Private Function GetMD5String(ByVal strFilename As String) As String
Dim MD5 As String = GetMD5String(strFilename)
Dim cMD5 = Security.Cryptography.MD5.Create
Dim bytHash As Byte()
Dim sb As New System.Text.StringBuilder
Dim scanbox As New TextBox
scanbox.Text = My.Computer.FileSystem.ReadAllText("viruslist.txt").ToString
Me.OpenFileDialog1.FileName = strFilename
Using cStream As New IO.FileStream(strFilename, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
bytHash = cMD5.ComputeHash(cStream)
End Using
For Each c In bytHash
sb.Append(c.ToString("X2"))
Next
If scanbox.Text.Contains(sb.ToString) Then
Detect.ShowDialog()
WriteToLog("Malicious exploit detected.")
Quarantinevb.ListBox1.Items.Add(strFilename)
End If
Return sb.ToString
End Function
Works well and is reliable.

Read each number from array and making sum

I am kinda new at coding.
I am reading some numbers from a txt files and i have them into a array,i managed to make them descending,now i want to make a sum with this numbers,for example:
I will have an input number 1000,on the list i will have numbers from 100 to 1000 and i want to make a sum with them to reach 1000 with minimum rest.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim fStream As New System.IO.FileStream("C:\Users\Alex\Desktop\test.txt", IO.FileMode.Open)
Dim sReader As New System.IO.StreamReader(fStream)
Dim List As New List(Of Double)
Do While sReader.Peek >= 0
List.Add(sReader.ReadLine)
Loop
Dim i As Long
Dim txt As String
Dim thisArray As Double() = List.ToArray
For i = LBound(thisArray) To UBound(thisArray)
txt = thisArray(i) & vbCrLf
Next i
Array.Sort(thisArray)
For j As Integer = 0 To thisArray.Count - 1
Dim FILE_NAME As String = "C:\Users\Alex\desktop\test2.txt"
If System.IO.File.Exists(FILE_NAME) = True Then
Dim objWriter As New System.IO.StreamWriter(FILE_NAME, IO.FileMode.Append)
objWriter.WriteLine(thisArray(j))
objWriter.Close()
Else
MessageBox.Show("File Does Not Exist")
End If
Next
fStream.Close()
sReader.Close()
End Sub
I dont know where to start to do this..input number will be from a textbox.

File locked after encryption

I have a small app that is designed to go through a folder and encrypt all the files and delete the non-encrypted version. The encryption works correctly but when I go to delete the file it is locked. Once the app is closed the file is no longer locked. My code is
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim path As String = Directory.GetCurrentDirectory()
Dim parent As DirectoryInfo = Directory.GetParent(path)
Dim completions As String = parent.FullName & "\Attachments_Completions"
Dim di As New DirectoryInfo(completions)
Dim fi As FileInfo() = di.GetFiles()
Dim dra As FileInfo
For Each dra In fi
If dra.Name <> "Completions.txt" And dra.Name <> "Attachments.txt" Then
Dim tmpFileName As String = String.Format("{0}\qqzr_{1}", dra.DirectoryName, dra.Name)
Dim encryptedName As String = String.Format("{0}\{1}", dra.DirectoryName, dra.Name)
FileSystem.Rename(String.Format("{0}\{1}", dra.DirectoryName, dra.Name), String.Format("{0}\qqzr_{1}", dra.DirectoryName, dra.Name))
cryptFile(tmpFileName, encryptedName, False)
File.Delete(tmpFileName)
End if
Next
End Sub
Sub cryptFile(ByVal sInputFilename As String, ByVal sOutputFilename As String, ByVal switch As Boolean)
' * Used to Encrypt or Decrypt a file
' ***********************************
Dim sKey As String = "a2#R|+~"
Try
Dim DES As New DESCryptoServiceProvider()
DES.Key() = ASCIIEncoding.ASCII.GetBytes(sKey)
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey)
'Read the input file into array
Dim fsInput As New FileStream(sInputFilename, FileMode.Open, FileAccess.Read)
Dim bytearrayinput(fsInput.Length - 1) As Byte
fsInput.Read(bytearrayinput, 0, bytearrayinput.Length)
'Define the crypto transformer
Dim cryptoTransform As ICryptoTransform
If switch Then
cryptoTransform = DES.CreateEncryptor()
Else
cryptoTransform = DES.CreateDecryptor
End If
'Create the encrypting streams
Dim fsEncrypted As New FileStream(sOutputFilename, FileMode.Create, FileAccess.Write)
Dim cryptostream As New CryptoStream(fsEncrypted, cryptoTransform, CryptoStreamMode.Write)
'Write the output file
cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length)
cryptostream.Close()
cryptostream.Dispose()
'Release the input file
fsInput.Close()
fsInput.Dispose()
'Release the output file
fsEncrypted.Close()
fsEncrypted.Dispose()
Catch ex As Exception
End Try
End Sub
End Class
Can anyone help?
Cheers
James
Just add this
Catch ex As Exception
Debug.Write(ex.Message)
End Try
...and see what happens...
Thanks for the responses.
I have managed to resolve the problem by adding File.SetAttributes(tmpFileName, FileAttributes.Normal) before the File.Delete command

Copy files with progress

I am wanting the most efficient way to copy a file with a progress bar updating the copy percentage.
This is the standard copy code I am using:
System.IO.File.Copy(source,target)
This is very fast and efficient. However, I cannot report the copy percentage.
I have tried many functions that read and save a file by opening up the filestream and then looping while reading/writing the data. This enables me to report the progress.
Here are the functions that I am using:
Public Sub SaveBinaryFile(strFilename As String, bytesToWrite() As Byte)
Dim position As Integer = 0
Dim BufferSize As Integer = 4096
'frmMain.tsProgressBar.Value = 0
Using fsNew As FileStream = New FileStream(strFilename, FileMode.Create, FileAccess.Write)
Do
Dim intToCopy As Integer = Math.Min(BufferSize, bytesToWrite.Length - position)
Dim buffer(intToCopy - 1) As Byte
Array.Copy(bytesToWrite, position, buffer, 0, intToCopy)
fsNew.Write(buffer, 0, buffer.Length)
'frmMain.tsProgressBar.Value = ((position / bytesToWrite.Length) * 100)
'frmMain.tsProgressBar.Refresh()
Application.DoEvents()
position += intToCopy
Loop While position < bytesToWrite.Length
End Using
End Sub
Public Function ReadBinaryFile(strFilename As String) As Byte()
Dim position As Integer = 0
Dim bufferSize As Integer = 4096
Dim bytes() As Byte
'frmMain.tsProgressBar.Value = 0
Using fsOpen As FileStream = New FileStream(strFilename, FileMode.Open)
ReDim bytes((fsOpen.Length) - 1)
Do
If (position + bufferSize) > fsOpen.Length Then
fsOpen.Read(bytes, position, fsOpen.Length - position)
Exit Do
Else
fsOpen.Read(bytes, position, bufferSize)
End If
'frmMain.tsProgressBar.Value = ((position / fsOpen.Length) * 100)
'frmMain.tsProgressBar.Refresh()
Application.DoEvents()
position += bufferSize
Loop
End Using
Return bytes
End Function
The problem is that is a lot slower than using the straight copy code.
What is the best/efficient way to copy a file showing the copy progress?
thanks
There is a variant of System.IO.File that provides user feedback; it's called Microsoft.VisualBasic.FileIO.FileSystem. See also http://msdn.microsoft.com/en-us/library/cc165446.aspx.
hmm Try this function
Dim D As Integer
Function CopyFileWithProgress(ByVal Source As String, ByVal Destination As String) As Integer
Try
Dim SourceF As New IO.FileStream(TextBox1.Text, IO.FileMode.Open)
Dim DestinationF As New IO.FileStream(TextBox2.Text & "\" & TextBox3.Text & ".ps4game", IO.FileMode.Create)
Dim len As Long = SourceF.Length - 1
Dim buffer(1024) As Byte
Dim byteCFead As Integer
While SourceF.Position < len
byteCFead = (SourceF.Read(buffer, 0, 1024))
DestinationF.Write(buffer, 0, byteCFead)
D = CInt(SourceF.Position / len * 100)
Application.DoEvents()
End While
DestinationF.Flush()
DestinationF.Close()
SourceF.Close()
Return D
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Function
it will work
you can use:
Microsoft.VisualBasic.FileIO.FileSystem.CopyFile("C:\[Copy From]", "C:\[Copy To]", _
FileIO.UIOption.AllDialogs)
' this requires the Microsoft.VisualBasic.dll, which is referenced from Visual Basic .NET
' projects by default, but needs to be added to C# projects manually
OR :
Dim CF As New IO.FileStream("C:\[Copy From]", IO.FileMode.Open)
Dim CT As New IO.FileStream("C:\[Copy To]", IO.FileMode.Create)
Dim len As Long = CF.Length - 1
Dim buffer(1024) As Byte
Dim byteCFead As Integer
While CF.Position < len
byteCFead = (CF.Read(buffer, 0, 1024))
CT.Write(buffer, 0, byteCFead)
ProgressBar1.Value = CInt(CF.Position / len * 100)
Application.DoEvents()
End While
CT.Flush()
CT.Close()
CF.Close()
OR : Using WebClient
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If Not OpenFileDialog1.ShowDialog() = DialogResult.OK Then Return
If Not FolderBrowserDialog1.ShowDialog = DialogResult.OK Then Return
Button1.Enabled = False
WebClient1.DownloadFileAsync(New Uri(OpenFileDialog1.FileName), Path.Combine(FolderBrowserDialog1.SelectedPath, OpenFileDialog1.SafeFileName))
End Sub
Private Sub WebClient1_DownloadProgressChanged(sender As Object, e As DownloadProgressChangedEventArgs) Handles WebClient1.DownloadProgressChanged
ProgressBar1.Value = e.ProgressPercentage
End Sub
Private Sub WebClient1_DownloadFileCompleted(sender As Object, e As System.ComponentModel.AsyncCompletedEventArgs) Handles WebClient1.DownloadFileCompleted
Button1.Enabled = True
End Sub

Save binary file from SQL Server

I'm trying to save a binary file stored in a SQL database with a SaveDialog, the function RetrieveFile retrieves the specified file from the database as a Byte array, here's what I have so far:
Private Shared Function RetrieveFile(ByVal filename As String) As Byte()
Dim connection As New SqlConnection("Data Source=SERVER\SQL2008;Initial Catalog=NorthPole;Integrated Security=True")
Dim command As New SqlCommand("SELECT pcfFile FROM Items WHERE pcfFileName=#Filename", connection)
command.Parameters.AddWithValue("#Filename", filename)
connection.Open()
Dim reader As SqlDataReader = command.ExecuteReader(System.Data.CommandBehavior.SequentialAccess)
reader.Read()
Dim memory As New MemoryStream()
Dim startIndex As Long = 0
Const ChunkSize As Integer = 256
While True
Dim buffer As Byte() = New Byte(ChunkSize - 1) {}
Dim retrievedBytes As Long = reader.GetBytes(1, startIndex, buffer, 0, ChunkSize)
memory.Write(buffer, 0, CInt(retrievedBytes))
startIndex += retrievedBytes
If retrievedBytes <> ChunkSize Then
Exit While
End If
End While
connection.Close()
Dim data As Byte() = memory.ToArray()
memory.Dispose()
Return data
End Function
Private Sub SaveAsToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveAsToolStripMenuItem.Click
Dim saveFileDialog1 As New SaveFileDialog()
saveFileDialog1.Filter = "PCF File|*.pcf|"
saveFileDialog1.Title = "Save an pcf File"
saveFileDialog1.ShowDialog()
If saveFileDialog1.FileName <> "" Then
Dim fs As System.IO.FileStream = CType(RetrieveFile("FakePCF.pcf"), System.IO.FileStream)
fs.Close()
End If
End Sub
Files are saved as "SqlDbType.VarBinary" within the database.
I get: "Index was outside the bounds of the array." on:
Dim retrievedBytes As Long = reader.GetBytes(1, startIndex, buffer, 0, ChunkSize)
The MemoryStream appears to not be retrieving the data yet the SQL sytax is correct.
What am I doing wrong?
Well, first of all, your method returns byte[] and you're trying to cast it to FileStream. You should change your handler to following:
Private Sub SaveAsToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveAsToolStripMenuItem.Click
Dim saveFileDialog1 As New SaveFileDialog()
saveFileDialog1.Filter = "PCF File|*.pcf|"
saveFileDialog1.Title = "Save an pcf File"
saveFileDialog1.ShowDialog()
If saveFileDialog1.FileName <> "" Then
Dim fs As New System.IO.FileStream (saveFileDialog1.FileName, System.IO.FileMode.Create, System.IO.FileAccess.Write)
Dim data As Byte() = RetrieveFile("FakePCF.pcf")
fs.Write(data, 0, data.Length)
fs.Flush()
fs.Close()
End If
End Sub