I'm trying to encrypt a .txt file which is created in my application.
To create this file, I'm using the following code:
Dim fileExists As Boolean = File.Exists(directorypath & "dbpw.txt")
If File.Exists(directorypath & "dbpw.txt") = False Then
Using sw As New StreamWriter(File.Open(directorypath & "dbpw.txt", FileMode.Create))
IIf(fileExists, "", "")
sw.Close()
End Using
End If
Then, to write and encrypt the file, I'm using the following code, calling subroutines that I tweaked from examples on the internet.
bytKey = CreateKey(txtCode.Text)
bytIV = CreateIV(txtCode.Text)
EncryptOrDecryptFile(directorypath & "dbpw.txt", directorypath & "dbpw.txt", bytKey, bytIV, CryptoAction.ActionEncrypt)
When the code gets to the final line, calling the EncryptOrDecrypt subroutine, an error is thrown saying
The process cannot access the file 'myDirectoryPath\dbpw.txt' because it is being used by another process
What do I need to do to release the file?
I also tried just using File.Create along with File.Encrypt but the same error was thrown either way.
Code for EncryptOrDecryptFile()
Public Sub EncryptOrDecryptFile(ByVal strInputFile As String, ByVal strOutputFile As String, ByVal bytKey() As Byte, ByVal bytIV() As Byte, ByVal Direction As CryptoAction)
Try
fsInput = New System.IO.FileStream(strInputFile, FileMode.Open, FileAccess.Read)
fsOutput = New System.IO.FileStream(strOutputFile, FileMode.OpenOrCreate, FileAccess.Write)
fsOutput.SetLength(0)
' Currently fails, file not being released for read/write once it's created.
Dim bytBuffer(4096) As Byte
Dim lngBytesProcessed As Long = 0
Dim lngFileLength As Long = fsInput.Length
Dim intBytesInCurrentBlock As Integer
Dim csCryptoStream As CryptoStream
Dim cspRijndael As New System.Security.Cryptography.RijndaelManaged
Select Case Direction
Case CryptoAction.ActionEncrypt
csCryptoStream = New CryptoStream(fsOutput, _
cspRijndael.CreateEncryptor(bytKey, bytIV), _
CryptoStreamMode.Write)
Case CryptoAction.ActionDecrypt
csCryptoStream = New CryptoStream(fsOutput, _
cspRijndael.CreateDecryptor(bytKey, bytIV), _
CryptoStreamMode.Write)
End Select
While lngBytesProcessed < lngFileLength
intBytesInCurrentBlock = fsInput.Read(bytBuffer, 0, 4096)
csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock)
lngBytesProcessed = lngBytesProcessed + _
CLng(intBytesInCurrentBlock)
End While
csCryptoStream.Close()
fsInput.Close()
fsOutput.Close()
Catch ex As Exception
errorLog(ex)
End Try
End Sub
Together with the parameters you pass it, in your
EncryptOrDecryptFile()method you are trying to open two streams (fsInputandfsOutput) to the same file. Once you've openedfsInputit has exclusive access to the file, makingfsOutputunable to open it for writing.Your only options are:
Rename either the input file or the output file so that the two streams open two different files, or:
Keep a "global" encryption stream open to the file, which you use every time you want to write data to it.
NOTE: Someone in the future might suggest that you open
fsInputwithFileShare.Writein order to allow other processes to open the file for writing, thus also allowing thefsOutputstream to write to it as well. - DON'T DO THAT!Allowing other processes to write to the file while you're reading from it can cause problems, even if it's your
fsOutputstream. This is because you'll never be able to know how much datafsOutputis going to write. What if the encrypted data is longer than the original? That would result in it overwriting whatfsInputis going to read next, thus corrupting the file.