This is my first question on the site and I am fairy new at how code works. I need to be able to open a file from a list view. I can get the file path to open up my file explorer, but can not get it to directly open the selected file. It gives me an error saying "System.ComponentModel.Win32Exception: 'The system cannot find the file specified" I've checked the file path from my file explorer and the path it pulls from and they both seem to match. Here is an example of what I've written.
Private Sub ListView1_Function(sender As Object, e As EventArgs) Handles ListView1.ItemSelectionChanged
If Not ListView1.SelectedItems.Item(0).Text = "" Then
For Each ListViewItemVar As ListViewItem In ListView1.Items
Dim filePath As String = $"C:\Users\{My.User.Name.Split("\").ElementAt(1)}\S & J Tube Inc\Files_Storage - Documents\Shipping Wizard\"
Dim selectedFile As String = ListViewItemVar.Text
If ListViewItemVar.Selected = True Then
If MessageBox.Show("You are about to open " & filePath & ". Are you sure?", "Open File", MessageBoxButtons.YesNo, MessageBoxIcon.Information) = DialogResult.Yes Then
Process.Start(filePath + selectedFile)
ElseIf DialogResult.No Then
MsgBox("You decided not to open the file.")
End If
End If
Next
End If
End Sub
You have to use ListView1_ItemActivate
1.Create a project with Form with ListView1 and Label1 controls on it
2.Replace yourName in dirInfo with your name from Users\eee\Documents
And all the code you need is :
Imports System.IO
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'CreateHeadersAndFillListView
ListView1.View = View.Details
ListView1.Columns.Add("Filename")
ListView1.Columns.Add("Size")
ListView1.Columns.Add("Last accessed")
Dim dirInfo As New DirectoryInfo("C:\Users\yourName\Documents")
Dim fileInfo As FileInfo
Dim lvi As ListViewItem
Dim lvsi As ListViewItem.ListViewSubItem
For Each fileInfo In dirInfo.GetFiles("*.*")
lvi = New ListViewItem With {
.Text = fileInfo.Name,
.ImageIndex = 1,
.Tag = fileInfo.FullName
}
lvsi = New ListViewItem.ListViewSubItem With {
.Text = fileInfo.Length.ToString()
}
lvi.SubItems.Add(lvsi)
lvsi = New ListViewItem.ListViewSubItem With {
.Text = fileInfo.LastAccessTime.ToString()
}
lvi.SubItems.Add(lvsi)
ListView1.Items.Add(lvi)
Next
'after populating the list this will size columns to the width of column data
ListView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent)
Label1.Text = "C:\Users\yourName\Documents" + Environment.NewLine + " (Double click to open file !)"
AddHandler ListView1.ItemActivate, AddressOf ListView1_ItemActivate
End Sub
Private Sub ListView1_ItemActivate(sender As Object, e As System.EventArgs)
Dim filename As String = ListView1.SelectedItems(0).Tag.ToString()
Try
Process.Start(filename)
Catch
Return
End Try
End Sub
I am coding a WPF application that will grab email's off of an IMAP account, and then export them into a user-selected folder.
I use a BackgroundWorker to download the emails. However, my UI isn't being updated until the loop is over.
Any tips would be appreciated.
Class MainWindow
Public MailRepo As MailRepository
Private bw_Connect As New BackgroundWorker
Private bw_Save As New BackgroundWorker
Public Sub New()
InitializeComponent()
bw_Connect.WorkerReportsProgress = True
bw_Connect.WorkerSupportsCancellation = True
AddHandler bw_Connect.DoWork, AddressOf bw_Connect_DoWork
bw_Save.WorkerReportsProgress = True
bw_Save.WorkerSupportsCancellation = True
AddHandler bw_Save.DoWork, AddressOf bw_Save_DoWork
AddHandler bw_Save.ProgressChanged, AddressOf bw_Save_ProgressChanged
End Sub
Private Sub bw_Save_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
If bw_Connect.CancellationPending = True Then
e.Cancel = True
Else
SaveEmails()
End If
End Sub
Private Sub SaveEmails()
Dim allMails As IEnumerable(Of Message)
'Get All Emails in Mailbox
Try
Dim mailBox As String
Dispatcher.Invoke(DirectCast(Sub()
mailBox = comboBoxEmailFolders.SelectedValue
End Sub, Action))
allMails = MailRepo.GetAllMails(mailBox)
Catch i4e As Imap4Exception
MsgBox("Error: Folder not found" & vbCrLf & i4e.Message)
Return
End Try
Dim msg As Message
Dim msgInt As Integer = 1
'Save each message
For Each msg In allMails
bw_Save.ReportProgress(100 / allMails.Count * msgInt, Nothing)
SaveMessage(msg)
msgInt += 1
Next
End Sub
Private Sub bw_Save_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
Dim percentDone As String = e.ProgressPercentage.ToString() & "%"
updateStatus("Saving Emails " & percentDone & " done.")
progressBarStatus.Value = e.ProgressPercentage
End Sub
I've the following code, it's a code that parses an external Log file to a datagridview, however when I load a big file the operation takes time and the form freezes for a bit, what I need is to show a progress bar while it's parsing the log file.
This is the code :
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
Using Reader As New Microsoft.VisualBasic.FileIO.
TextFieldParser(TextBox1.Text)
Reader.TextFieldType =
Microsoft.VisualBasic.FileIO.FieldType.FixedWidth
Reader.SetFieldWidths(Convert.ToInt32(txtDate.Text), Convert.ToInt32(txtTime.Text), Convert.ToInt32(txtExt.Text), Convert.ToInt32(txtCO.Text), _
Convert.ToInt32(txtNumber.Text), Convert.ToInt32(txtDuration.Text), Convert.ToInt32(txtAccCode.Text))
Dim currentRow As String()
While Not Reader.EndOfData
Try
currentRow = Reader.ReadFields()
Dim currentField As String
For Each currentField In currentRow
Dim curRowIndex = dg1.Rows.Add()
' Set the first cell of the new row....
dg1.Rows(curRowIndex).Cells(0).Value = currentRow(0)
dg1.Rows(curRowIndex).Cells(1).Value = currentRow(1)
dg1.Rows(curRowIndex).Cells(2).Value = currentRow(2)
dg1.Rows(curRowIndex).Cells(3).Value = currentRow(3)
dg1.Rows(curRowIndex).Cells(4).Value = currentRow(4)
dg1.Rows(curRowIndex).Cells(5).Value = currentRow(5)
dg1.Rows(curRowIndex).Cells(6).Value = currentRow(6)
Next
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message &
"is not valid and will be skipped.")
End Try
End While
MsgBox("Total records imported : " & dg1.RowCount)
lblTotal.Text = "Total Records: " & dg1.RowCount
End Using
Catch
MsgBox("Invalid file, please make sure you entered the right path")
End Try
End Sub
Add a BackgroundWorker and set its WorkerReportsProgressProperty to True.
Add a ProgressBar.
Then try this code out:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
Dim widths() As Integer = { _
Convert.ToInt32(txtDate.Text), Convert.ToInt32(txtTime.Text), Convert.ToInt32(txtExt.Text), _
Convert.ToInt32(txtCO.Text), Convert.ToInt32(txtNumber.Text), Convert.ToInt32(txtDuration.Text), _
Convert.ToInt32(txtAccCode.Text)}
ProgressBar1.Visible = True
ProgressBar1.Style = ProgressBarStyle.Marquee ' continuos animation
Dim input As New Tuple(Of String, Integer())(TextBox1.Text, widths)
BackgroundWorker1.RunWorkerAsync(input)
Catch ex As Exception
MessageBox.Show("Invalid Width!")
End Try
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim input As Tuple(Of String, Integer()) = DirectCast(e.Argument, Tuple(Of String, Integer()))
Try
Using Reader As New Microsoft.VisualBasic.FileIO.TextFieldParser(input.Item1)
Reader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.FixedWidth
Reader.SetFieldWidths(input.Item2)
Dim currentRow() As String
While Not Reader.EndOfData
Try
currentRow = Reader.ReadFields()
BackgroundWorker1.ReportProgress(-1, New Object() { _
currentRow(0), currentRow(1), currentRow(2), _
currentRow(3), currentRow(4), currentRow(5), _
currentRow(6)})
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MessageBox.Show("Line is not valid and will be skipped." & vbCrLf & vbCrLf & ex.Message)
End Try
End While
End Using
Catch
MsgBox("Invalid file, please make sure you entered the right path")
End Try
End Sub
Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
Dim values() As Object = DirectCast(e.UserState, Object())
dg1.Rows.Add(values)
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
MessageBox.Show("Total records imported : " & dg1.RowCount)
lblTotal.Text = "Total Records: " & dg1.RowCount
ProgressBar1.Style = ProgressBarStyle.Continuous
ProgressBar1.Visible = False
End Sub
EDIT:
I've tried to change the code, and eg. instead use different subs. But now, when something changes, the program only crash. I've disabled logging, setting breakpoints and so, but the program doesn't come long. This is the error message(s) in the Visual Basic logs (this coming every time the program crash):
A first chance exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll
And here's the code (I've made some process monitor tests if you wonder what ExecProtectCompareModule and ExecProtect is):
Imports System.IO
Imports System.Diagnostics
Imports System.Text
Imports System.Security.Cryptography
Public Class Form1
Dim processList As String
Dim processList2 As String
Public watchfolder As FileSystemWatcher
Dim log As String
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
watchfolder = New System.IO.FileSystemWatcher()
watchfolder.IncludeSubdirectories = True
watchfolder.Path = TextBox1.Text
watchfolder.NotifyFilter = IO.NotifyFilters.DirectoryName
watchfolder.NotifyFilter = watchfolder.NotifyFilter Or _
IO.NotifyFilters.FileName
watchfolder.NotifyFilter = watchfolder.NotifyFilter Or _
IO.NotifyFilters.Attributes
AddHandler watchfolder.Changed, AddressOf logchange
AddHandler watchfolder.Created, AddressOf logchange
AddHandler watchfolder.Deleted, AddressOf logchange
AddHandler watchfolder.Renamed, AddressOf logrename
watchfolder.EnableRaisingEvents = True
Button1.Enabled = False
Button2.Enabled = True
End Sub
Private Sub logchange(ByVal source As Object, ByVal e As _
System.IO.FileSystemEventArgs)
' Dim msg As String = Environment.NewLine & "File " & e.FullPath & " "
' Select Case e.ChangeType
' Case IO.WatcherChangeTypes.Created
' msg &= "has been created" + " " + "Time:" + " " + Format(TimeOfDay)
' Case IO.WatcherChangeTypes.Deleted
' msg &= "has been deleted" + " " + "Time:" + " " + Format(TimeOfDay)
' Case IO.WatcherChangeTypes.Changed
' msg &= "has been modified" + " " + "Time:" + " " + Format(TimeOfDay)
' End Select
'log &= msg
'log &= Chr(13)
'Dim writer As New IO.StreamWriter("log.txt", True)
'writer.WriteLine(msg)
'writer.Close()
Label6.Text = e.FullPath
md5checkdelay.Start()
End Sub
Public Sub logrename(ByVal source As Object, ByVal e As _
System.IO.RenamedEventArgs)
Select Case e.ChangeType
Case IO.WatcherChangeTypes.Created
Exit Sub
Case IO.WatcherChangeTypes.Changed
Exit Sub
Case IO.WatcherChangeTypes.Deleted
Exit Sub
Case Else
' Dim msgrn As String = Environment.NewLine & "File " + e.OldName + " "
' msgrn &= "has been renamed to" + " " + e.Name + " " + "Time:" + " " + Format(TimeOfDay)
' log &= msgrn
' log &= Chr(13)
'Dim writer As New IO.StreamWriter("log.txt", True)
'writer.WriteLine(msgrn)
'writer.Close()
Label5.Text = e.FullPath
md5checkdelay.Start()
End Select
End Sub
Sub md5check()
Dim md5code As String
Dim md5 As MD5CryptoServiceProvider = New MD5CryptoServiceProvider
Dim f As FileStream = New FileStream(Label5.Text, FileMode.Open, FileAccess.Read, FileShare.Read, 8192)
'f = New FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read, 8192)
md5.ComputeHash(f)
'Dim ObjFSO As Object = CreateObject("Scripting.FileSystemObject")
'Dim objFile = ObjFSO.GetFile(e.FullPath)
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:X1}", hashByte))
Next
md5code = buff.ToString()
If md5code = "D41D8CD98F0B24E980998ECF8427E" Then
Dim frm2 As New Form2
frm2.Show()
f.Close()
Else
f.Close()
End If
End Sub
Sub md5check2()
Dim md5code As String
Dim md5 As MD5CryptoServiceProvider = New MD5CryptoServiceProvider
Dim f As FileStream = New FileStream(Label5.Text, FileMode.Open, FileAccess.Read, FileShare.Read, 8192)
'f = New FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read, 8192)
md5.ComputeHash(f)
'Dim ObjFSO As Object = CreateObject("Scripting.FileSystemObject")
'Dim objFile = ObjFSO.GetFile(e.FullPath)
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:X1}", hashByte))
Next
md5code = buff.ToString()
If md5code = "D41D8CD98F0B24E980998ECF8427E" Then
Dim frm2 As New Form2
frm2.Show()
f.Close()
Else
f.Close()
End If
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
watchfolder.EnableRaisingEvents = False
Button1.Enabled = True
Button2.Enabled = False
End Sub
Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
Dim frm2 As New Form2
frm2.ShowDialog()
End Sub
Private Sub ExecProtect_Tick(sender As System.Object, e As System.EventArgs) Handles ExecProtectMonitorModule.Tick
For Each p As Process In Process.GetProcesses()
processList = processList & " " & p.ProcessName & vbNewLine
Next
Label3.Text = processList
End Sub
Private Sub ExecProtectCompareModule_Tick(sender As System.Object, e As System.EventArgs) Handles ExecProtectCompareModule.Tick
If Not Label2.Text = Label3.Text Then
MsgBox("New process started!", 0 + 64)
processList2refresh()
End If
End Sub
Sub processList2refresh()
For Each p As Process In Process.GetProcesses()
processList2 = processList2 & " " & p.ProcessName & vbNewLine
Exit Sub
Next
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
For Each p As Process In Process.GetProcesses()
processList2 = processList2 & " " & p.ProcessName & vbNewLine
Next
Label2.Text = processList2
End Sub
Private Sub md5checkdelay_Tick(sender As System.Object, e As System.EventArgs) Handles md5checkdelay.Tick
'The timer that adds 1 second delay before it checks the md5code after the file(s) is changed
Label4.Text = Label4.Text + 1
If Label4.Text = 1 Then
md5check()
End If
End Sub
Private Sub md5checkdelay2_Tick(sender As System.Object, e As System.EventArgs) Handles md5checkdelay2.Tick
'The timer that adds 1 second delay before it checks the md5code after the file(s) is changed but for the rename function instead
Label7.Text = Label7.Text + 1
If Label7.Text = 1 Then
md5check2()
End If
End Sub
End Class
EDIT END
I've made a question before, named "Folder monitor that monitors md5 code in the files only crashes", that someone told me to close the filestream and use another code to show the form. But it doesn't work. I've made a form named TestForm, that, doesn't contain anything, just the form, because the whole program closed when I tried to show Form2 that contains PictureBoxes and more, and I have writed the code to show TestForm when the md5 code of the modified file is equal to the md5 code I've specified in the code, but the form that shows only freeze up, and the filestream won't close, I tried f.Close() to close the filestream. But if I write the code to show a MsgBox when the md5 code of the modified file is equal to the md5 code I specified in the code, it works fine. Here is the code:
Imports System.IO
Imports System.Diagnostics
Imports System.Text
Imports System.Security.Cryptography
Public Class Form1
Public watchfolder As FileSystemWatcher
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
watchfolder = New System.IO.FileSystemWatcher()
watchfolder.IncludeSubdirectories = True
watchfolder.Path = TextBox1.Text
watchfolder.NotifyFilter = IO.NotifyFilters.DirectoryName
watchfolder.NotifyFilter = watchfolder.NotifyFilter Or _
IO.NotifyFilters.FileName
watchfolder.NotifyFilter = watchfolder.NotifyFilter Or _
IO.NotifyFilters.Attributes
AddHandler watchfolder.Changed, AddressOf logchange
AddHandler watchfolder.Created, AddressOf logchange
AddHandler watchfolder.Deleted, AddressOf logchange
AddHandler watchfolder.Renamed, AddressOf logrename
watchfolder.EnableRaisingEvents = True
Button1.Enabled = False
Button2.Enabled = True
End Sub
Private Sub logchange(ByVal source As Object, ByVal e As _
System.IO.FileSystemEventArgs)
If System.IO.Path.GetFileName(e.FullPath).ToLower = "log.txt" Then Exit Sub
Dim msg As String = Environment.NewLine & "File " & e.FullPath & " "
Select Case e.ChangeType
Case IO.WatcherChangeTypes.Created
msg &= "has been created" + " " + "Time:" + " " + Format(TimeOfDay)
Case IO.WatcherChangeTypes.Deleted
msg &= "has been deleted" + " " + "Time:" + " " + Format(TimeOfDay)
Case IO.WatcherChangeTypes.Changed
msg &= "has been modified" + " " + "Time:" + " " + Format(TimeOfDay)
End Select
Dim writer As New IO.StreamWriter("log.txt", True)
writer.WriteLine(msg)
writer.Close()
Dim md5code As String
Dim md5 As MD5CryptoServiceProvider = New MD5CryptoServiceProvider
Dim f As FileStream = New FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read, 8192)
f = New FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read, 8192)
md5.ComputeHash(f)
Dim ObjFSO As Object = CreateObject("Scripting.FileSystemObject")
Dim objFile = ObjFSO.GetFile(e.FullPath)
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:X1}", hashByte))
Next
md5code = buff.ToString()
If md5code = "D41D8CD98F0B24E980998ECF8427E" Then 'D41D8CD98F0B24E980998ECF8427E is the md5code of a blank txt file
' Dim frm2 As New Form2
' frm2.Show()
TestForm.Show()
f.Close()
Else
f.Close()
End If
End Sub
Public Sub logrename(ByVal source As Object, ByVal e As _
System.IO.RenamedEventArgs)
Select Case e.ChangeType
Case IO.WatcherChangeTypes.Created
Exit Sub
Case IO.WatcherChangeTypes.Changed
Exit Sub
Case IO.WatcherChangeTypes.Deleted
Exit Sub
Case Else
Dim msgrn As String = Environment.NewLine & "File " + e.OldName + " "
msgrn &= "has been renamed to" + " " + e.Name + " " + "Time:" + " " + Format(TimeOfDay)
Dim writer As New IO.StreamWriter("log.txt", True)
writer.WriteLine(msgrn)
writer.Close()
End Select
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
watchfolder.EnableRaisingEvents = False
Button1.Enabled = True
Button2.Enabled = False
End Sub
End Class
Dim f As FileStream = New FileStream(e.FullPath, FileMode.Open, _
FileAccess.Read, FileShare.Read, 8192)
f = New FileStream(e.FullPath, FileMode.Open, FileAccess.Read, _
FileShare.Read, 8192)
md5.ComputeHash(f)
Edit
Notice anything odd? You are opening a filestream on the file, then immediately opening another filestream on the same file using the same variable without closing the first. Thats one reason it reports the file open in VS. Delete the f = New FileStream... line.
You will have ANOTHER problem here when the event fires due to a File Delete.
Then:
Dim ObjFSO As Object = CreateObject("Scripting.FileSystemObject")
Dim objFile = ObjFSO.GetFile(e.FullPath)
These last 2 dont appear to do anything. The objects are created but not used. But since objFile is built from the file in question, it could be preventing you from deleting or working with the file.
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:X1}", hashByte))
Next
md5code = buff.ToString()
Since you now have the MD5 code, you should close the filestream (f) so you can do other things. You cannot delete or move the file while it is open.
If md5code = "D41D8CD98F0B24E980998ECF8427E" Then
' Dim frm2 As New Form2
' frm2.Show()
TestForm.Show()
f.Close()
Else
f.Close()
End If
As with your previous code, if TestForm is form class, you must create an instance of it:
Dim frm As New TestForm
frm.Show ' or frm.ShowDialog
Forms are just classes. You must instance them before using them.
Edit continued
Finally, the freeze is a result of doing too much in a log event (log change AND compute MD5 AND show a new form). You have probably noticed that your app does not slow down while monitoring many files in many folders. Thats because the filewatcher runs on a different thread. When you create an instance of a new form or show it from that event, the form apparently runs on that thread.
You need to rework your code to remove the stuff that does not relate to actual logging. In that event, instead of all that stuff you might add the changed file to a List(of String) which represents a todo list. Do the MD5 and form stuff elsewhere on that list so it takes place on your app's thread.
FINAL edit
If all you are worried about is the form freezing, add this:
watchfolder = New System.IO.FileSystemWatcher()
watchfolder.SynchronizingObject = Me
It will only delay more major issues, but you seem to think it is important. Next, I have told you this 3 times now, but you MUST exit the log routines if the file operation was a delete because you cannot open a deleted file:
Case IO.WatcherChangeTypes.Deleted
Exit Sub ' after the log
The next problem you will get is when 2+ files have changed. You need a way to queue files/tasks. Your approach to calling other subs for some stuff DOES break things down to discrete tasks, but those called sub are called from the FW thread so you just moved the problem around. For a queue I was thinking a List(of String) but a new class (as suggested in your last post) with its own BackgroundWorker might be better.
Public Class FileMgr
Friend thisFile As String
Friend thisHash As String = ""
Dim frm2 As Form2
Private WithEvents bw As BackgroundWorker
Public Sub New(ByVal f As String)
thisFile = f
bw = New BackgroundWorker
AddHandler bw.DoWork, AddressOf ProcessFile
' Explorer might not be done creating it yet,
' especially if you drop 3-4 files, so wait
Threading.Thread.Sleep(250)
' start the BW with the name of the file
bw.RunWorkerAsync(thisFile)
End Sub
ProcessFile is just your (fixed) MD5 sub with a new declaration:
Private Sub ProcessFile(ByVal sender As Object, _
ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork
Dim sFile As String = e.Argument
AGAIN, CLOSE THE FILE ONCE YOU HAVE THE HASH:
md5.ComputeHash(f)
f.Close()
DONT OPEN ANY FORMS. JUST GET THE HASH.
For Each hashByte In hash
buff.Append(String.Format("{0:X1}", hashByte))
Next
thisHash = buff.ToString() ' last line!!!
When the BackgroundWorker is done, it raises an event:
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, _
ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
Handles bw.RunWorkerCompleted
' I dont know why each file has to have its own form rather
' that a report item in a listbox but I also dont know why you
' are computing a hash for a 0 byte new file
If thisHash = "D41D8CD98F0B24E980998ECF8427E" Then
frm2 = New Form2
frm2.Label1.Text = thisFile
frm2.Show()
End If
End Sub
End Class
To use it, takes one line of code in the log events:
Dim fMgr As New FileMgr(e.FullPath)
EACH file operation Windows reports will create a new file helper which will run its own BackgroundWorker. Since you arent doing too much there wont be too many alive at one time until you are processing files larger than 0 bytes. You also need a Try/Catch in MD5Sub/ProcessFile for times when the file is open and in use.
I dropped 6 files in the watch folder, got 6 copies of Form2, no errors and no freezes (and not even an upvote for all this).
I'm trying to read a text file with multiple lines and then display it in a textbox. The problem is that my program only reads one line. Can someone point out the mistake to me?
Imports System.IO
Imports Microsoft.VisualBasic.FileIO
Public Class Form1
Private BagelStreamReader As StreamReader
Private PhoneStreamWriter As StreamWriter
Dim ResponseDialogResult As DialogResult
Private Sub OpenToolStripMenuItem_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles OpenToolStripMenuItem.Click
'Dim PhoneStreamWriter As New StreamWriter(OpenFileDialog1.FileName)
'Is file already open
If PhoneStreamWriter IsNot Nothing Then
PhoneStreamWriter.Close()
End If
With OpenFileDialog1
.InitialDirectory = Directory.GetCurrentDirectory
.FileName = OpenFileDialog1.FileName
.Title = "Select File"
ResponseDialogResult = .ShowDialog()
End With
'If ResponseDialogResult <> DialogResult.Cancel Then
' PhoneStreamWriter = New StreamWriter(OpenFileDialog1.FileName)
'End If
Try
BagelStreamReader = New StreamReader(OpenFileDialog1.FileName)
DisplayRecord()
Catch ex As Exception
MessageBox.Show("File not found or is invalid.", "Data Error")
End Try
End Sub
Private Sub DisplayRecord()
Do Until BagelStreamReader.Peek = -1
TextBox1.Text = BagelStreamReader.ReadLine()
Loop
'MessageBox.Show("No more records to display.", "End of File")
'End If
End Sub
Private Sub SaveToolStripMenuItem_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles SaveToolStripMenuItem.Click
With SaveFileDialog1
.InitialDirectory = Directory.GetCurrentDirectory
.FileName = OpenFileDialog1.FileName
.Title = "Select File"
ResponseDialogResult = .ShowDialog()
End With
PhoneStreamWriter.WriteLine(TextBox1.Text)
With TextBox1
.Clear()
.Focus()
End With
TextBox1.Clear()
End Sub
Private Sub ExitToolStripMenuItem_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles ExitToolStripMenuItem.Click
Dim PhoneStreamWriter As New StreamWriter(OpenFileDialog1.FileName)
PhoneStreamWriter.Close()
Me.Close()
End Sub
End Class
Here is a sample textfile:
Banana nut
Blueberry
Cinnamon
Egg
Plain
Poppy Seed
Pumpkin
Rye
Salt
Sesame seed
You're probably only getting the last line in the file, right? Your code sets TextBox1.Text equal to BagelSteramReader.ReadLine() every time, overwriting the previous value of TextBox1.Text. Try TextBox1.Text += BagelStreamReader.ReadLine() + '\n'
Edit: Though I must steal agree with Hans Passant's commented idea on this; If you want an more efficient algorithm, File.ReadAllLines() even saves you time and money...though I didn't know of it myself. Darn .NET, having so many features...
I wrote a program to both write to and read from a text file. To write the lines of a list box to a text file I used the following code:
Private Sub txtWriteToTextfile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtWriteToTextfile.Click
Dim FileWriter As StreamWriter
FileWriter = New StreamWriter(FileName, False)
' 3. Write some sample data to the file.
For i = 1 To lstNamesList.Items.Count
FileWriter.Write(lstNamesList.Items(i - 1).ToString)
FileWriter.Write(Chr(32))
Next i
FileWriter.Close()
End Sub
And to read and write the contents of the text file and write to a multi-line text box (you just need to set the multiple lines property of a text box to true) I used the following code. I also had to do some extra coding to break the individual words from the long string I received from the text file.
Private Sub cmdReadFromTextfile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdReadFromTextfile.Click
Dim sStringFromFile As String = ""
Dim sTextString As String = ""
Dim iWordStartingPossition As Integer = 0
Dim iWordEndingPossition As Integer = 0
Dim iClearedTestLength As Integer = 0
Dim FileReader As StreamReader
FileReader = New StreamReader(FileName)
sStringFromFile = FileReader.ReadToEnd()
sTextString = sStringFromFile
txtTextFromFile.Text = ""
Do Until iClearedTestLength = Len(sTextString)
iWordEndingPossition = CInt(InStr((Microsoft.VisualBasic.Right(sTextString, Len(sTextString) - iWordStartingPossition)), " "))
txtTextFromFile.Text = txtTextFromFile.Text & (Microsoft.VisualBasic.Mid(sTextString, iWordStartingPossition + 1, iWordEndingPossition)) & vbCrLf
iWordStartingPossition = iWordStartingPossition + iWordEndingPossition
iClearedTestLength = iClearedTestLength + iWordEndingPossition
Loop
FileReader.Close()
End Sub