File locked after encryption - vb.net

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

Related

Incorrect progressbar value reported by the backgroundworker

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)

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.

How to Encrypt and Decrypt multiple text and image files within folders

Encryption and decryption for a single .txt file using the following code works:
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles SelectFile.Click
'Create a File Dialog Box to select the source file
Dim dlg As New OpenFileDialog
'If OK Button is Click then add file name with path to textBox1
If dlg.ShowDialog() = DialogResult.OK Then
TextBox1.Text = dlg.FileName
End If
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Encrypt.Click
Dim outputFile As String
outputFile = "M:\Encryptions\Encrypted.txt"
Dim fsInput As New FileStream(TextBox1.Text, FileMode.Open, FileAccess.Read)
Dim fsEncrypted As New FileStream(outputFile, FileMode.Create, FileAccess.Write)
Dim sKey As String
sKey = "Helloabc"
Dim DES As New DESCryptoServiceProvider
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey)
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey)
Dim desencrypt As ICryptoTransform
desencrypt = DES.CreateEncryptor()
Dim cryptostream As New CryptoStream(fsEncrypted, desencrypt, CryptoStreamMode.Write)
Dim bytearrayinput(fsInput.Length) As Byte
fsInput.Read(bytearrayinput, 0, bytearrayinput.Length)
cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length)
cryptostream.Close()
fsInput.Close()
fsEncrypted.Close()
TextBox2.Text = "M:\Encryptions\Encrypted.txt"
End Sub
Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Decrypt.Click
Dim DES As New DESCryptoServiceProvider
Dim sKey As String
sKey = "Helloabc"
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey)
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey)
Dim fsread As New FileStream(TextBox2.Text, FileMode.Open, FileAccess.Read)
Dim desdecrypt As ICryptoTransform
desdecrypt = DES.CreateDecryptor()
Dim cryptostreamDecr As New CryptoStream(fsread, desdecrypt, CryptoStreamMode.Read)
Dim fsDecrypted As New StreamWriter("M:\Decryptions\Decrypted.txt")
fsDecrypted.Write(New StreamReader(cryptostreamDecr).ReadToEnd())
fsDecrypted.Flush()
fsDecrypted.Close()
TextBox3.Text = "M:\Decryptions\Decrypted.txt"
End Sub
However when attempting to encrypt/decrypt multiple files, the original output encryption/decryption file ("Encrypted.txt") will be replaced by the new output.
How do you create a loop in order to create multiple encrypted files with different file names?
Use a counter: 0, 1, 2, 3, 4 ... Append the counter to the filename and step the counter after each file is written:
Encrypted00.dat
Encrypted01.dat
Encrypted02.dat
Encrypted03.dat
...
It is probably a mistake to call the encrypted files .txt since they will not be text. They are binary data. If you want them as text then you will need to convert to Base64 format, and convert back to binary data before decrypting.
Alternatively, zip all the files in the directory into a single file and encrypt that single file.

encrypting a folder in vb.net

I am currently trying to encrypt a Folder in VB.net. To do this, I am using In IO.Directory.GetFiles to get each file from the folder, and encrypt each file using a loop. Each encrypted file will then be saved to a location, in its original name . I am currently struggling to understand how to have the output file save each file in their original name. My code so far is displayed below, any help or guidance would be greatly appreciated.
Imports System.Windows.Forms
Imports System.Security.Cryptography
Imports System.Security
Imports System.Text
Imports System.IO
Imports System.Runtime.InteropServices
Public Class Folder
Private Sub Select_btn_Click(sender As Object, e As EventArgs) Handles Select_btn.Click
'Allows user to select folder
If FolderBrowserDialog1.ShowDialog() = DialogResult.OK Then
FileSelect_tb.Text = FolderBrowserDialog1.SelectedPath
End If
' Gets files in folder
Dim directory As New IO.DirectoryInfo(FileSelect_tb.Text)
Dim directorylist As IO.FileInfo() = directory.GetFiles()
Dim dra As IO.FileInfo
'Lists files in listbox
For Each dra In directorylist
ListBox1.Items.Add(dra)
Next
End Sub
Private Sub Encrypt_btn_Click(sender As Object, e As EventArgs) Handles Encrypt_btn.Click
'Password authentication
Dim skey As String = InputBox("Enter a password of 8 characters:")
'Check its 8 characters and repeat until its correct
While skey.Length <> 8
skey = InputBox("Password is not correct. Please try again:")
End While
For Each filePath In IO.Directory.GetFiles(FolderBrowserDialog1.SelectedPath)
'Allows user to select file destination
If FolderBrowserDialog2.ShowDialog() = DialogResult.OK Then
Encrypted_tb.Text =
End If
'Reads the file to create encryption
Dim fsInput As New FileStream(filePath, FileMode.Open, FileAccess.Read)
Dim fsEncrypted As New FileStream(Encrypted_tb.Text, FileMode.Create, FileAccess.Write)
'Defines encryption method
Dim DES As New DESCryptoServiceProvider
DES.Key = ASCIIEncoding.ASCII.GetBytes(skey)
DES.IV = ASCIIEncoding.ASCII.GetBytes(skey)
'Encrypts File
Dim desencrypt As ICryptoTransform
desencrypt = DES.CreateEncryptor()
Dim cryptostream As New CryptoStream(fsEncrypted, desencrypt, CryptoStreamMode.Write)
Dim bytearrayinput(fsInput.Length) As Byte
fsInput.Read(bytearrayinput, 0, bytearrayinput.Length)
cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length)
cryptostream.Close()
fsInput.Close()
fsEncrypted.Close()
Next
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