How to Ignore Illegal Characters in Path when using StreamWriter? - vb.net

Full code at bottom.
I've been getting an ArgumentException: "Illegal characters in path" whenever I attempt to save my text file in the program I've created.
My thoughts are that it has something to do with the directory path(path is chosen by user when prompted to open the file using an inputbox). My path on my computer being:
C:\Users\User\Desktop\HighScoreEditor
I've read tab characters can be the cause of this exception so my thoughts were maybe it's caused by the "\" in the directory path. I'm a 2nd year University Student so I may be completely wrong.
What I'm looking for is how to ignore this exception so that my file is saved, or a way to fix it so this exception does not occur.
My file is read from a directory path input by the user during an inputbox:
Dim message, title, defaultValue As String
Dim myValue As Object
Dim inFile As StreamReader
Dim strLine As String
' Set prompt.
message = "Enter a directory path to open your HighScore List."
' Set title.
title = "Which HighScore List should I open?"
defaultValue = "" ' Set default value.
' Display message, title, and default value.
myValue = InputBox(message, title, defaultValue)
' If user has clicked Cancel.
If myValue Is "" Then
Exit Sub
End If
Try
If File.Exists(myValue) = False Then
MessageBox.Show("Error: File/Directory Path """ & myValue & """ does not exist.")
ElseIf File.Exists(myValue) = True Then
inFile = File.OpenText(myValue)
Do While inFile.Peek <> -1
strLine = inFile.ReadLine()
txtScores.Text = txtScores.Text & vbCrLf & strLine
Loop
' Close the file.
inFile.Close()
End If
Catch ex As Exception
MessageBox.Show("Error: File/Directory Path """ & myValue & """ was found, however could not be opened." & vbCrLf & "" & vbCrLf & "Please make sure the list has a .txt file extension.")
End Try
Here is my code for my StreamWriter and save button:
Private Sub mnuFile_Save_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuFile_Save.Click
Dim outFile As StreamWriter
outFile = File.CreateText(txtScores.Text)
outFile.WriteLine(txtScores.Text)
outFile.Close()
End Sub
------FULL CODE BELOW------
Imports System.IO
Public Class frmHighScore_Editor
Dim strTxt As String = "Click File > Open to display your HighScore List Here."
Private Sub mnuFile_Exit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuFile_Exit.Click
' Terminates the program.
Me.Close()
End Sub
Private Sub mnuFile_Open_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuFile_Open.Click
Dim frmContinue As New frmContinue
frmContinue.ShowDialog()
Dim message, title, defaultValue As String
Dim myValue As Object
Dim inFile As StreamReader
Dim strLine As String
' Set prompt.
message = "Enter a directory path to open your HighScore List."
' Set title.
title = "Which HighScore List should I open?"
defaultValue = "" ' Set default value.
' Display message, title, and default value.
myValue = InputBox(message, title, defaultValue)
' If user has clicked Cancel.
If myValue Is "" Then
Exit Sub
End If
txtScores.Text = String.Empty
Try
If File.Exists(myValue) = False Then
txtScores.Text = strTxt
MessageBox.Show("Error: File/Directory Path """ & myValue & """ does not exist.")
ElseIf File.Exists(myValue) = True Then
txtScores.Text = String.Empty
If myValue.Contains("Blackjack.txt") Then
pbGame_Photo.Image = HighScores.My.Resources.Blackjack
lblGameName_Output.Text = "Blackjack"
ElseIf myValue.Contains("Mahjong.txt") Then
pbGame_Photo.Image = HighScores.My.Resources.Mahjong
lblGameName_Output.Text = "Mahjong"
ElseIf myValue.Contains("Minesweeper.txt") Then
pbGame_Photo.Image = HighScores.My.Resources.Minesweeper
lblGameName_Output.Text = "MineSweeper"
ElseIf myValue.Contains("Pinball.txt") Then
pbGame_Photo.Image = HighScores.My.Resources.Pinball
lblGameName_Output.Text = "Pinball"
ElseIf myValue.Contains("Solitaire.txt") Then
pbGame_Photo.Image = HighScores.My.Resources.Solitaire
lblGameName_Output.Text = "Solitaire"
Else
pbGame_Photo.Image = HighScores.My.Resources.Blank
lblGameName_Output.Text = "Your Game"
End If
inFile = File.OpenText(myValue)
Do While inFile.Peek <> -1
strLine = inFile.ReadLine()
Dim Res As String = ""
Dim Array(0) As Integer
For Each c As Char In strLine
If IsNumeric(c) Then
Res = Res & c
If CInt(Res) > Array(0) Then
Array(0) = CInt(Res)
End If
End If
Next
txtScores.Text = txtScores.Text & vbCrLf & strLine
lblScoreAchieved_Output.Text = Array(0)
Loop
' Close the file.
inFile.Close()
txtScores.Enabled = True
End If
Catch ex As Exception
txtScores.Text = strTxt
MessageBox.Show("Error: File/Directory Path """ & myValue & """ was found, however could not be opened." & vbCrLf & "" & vbCrLf & "Please make sure the list has a .txt file extension.")
End Try
End Sub
Private Sub frmHighScore_Editor_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' Set the focus.
gbGameInfo.Focus()
pbGame_Photo.Image = HighScores.My.Resources.Blank
' Disable text box on load since it's empty anyways.
txtScores.Enabled = False
txtScores.Text = strTxt
End Sub
Private Sub mnuFile_Save_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuFile_Save.Click
Dim outFile As StreamWriter
outFile = File.CreateText(txtScores.Text)
outFile.WriteLine(txtScores.Text)
outFile.Close()
End Sub
End Class
------FULL CODE ABOVE------

myValue = InputBox(message, title, defaultValue)
That's a very poor way to ask for a filename. Use SaveFileDialog instead. Short from the intuitive dialog that any Windows user knows how to operate, it also automatically avoids that exception.

Related

Get percentage of files copied from a list

I have an app that copies files in a list to a new directory. I'm trying to get the progress bar to work but my formula results with a System.OverflowException: Arithmetic operation resulted in an over flow. I've looked at other examples using file copying but they are centered on using the source folder divided by destination folder. Mines a little bit different because I'm using files in a list.
Thank you for the help.
Code
Dim progress = fileCount * 100 / fileList.Count()
BackgroundWorker1.ReportProgress(progress)
Code for getting file Count
Dim FILE_NAME As String
FILE_NAME = txtFileName.Text
Dim fileNames = System.IO.File.ReadAllLines(FILE_NAME)
fCount = 0
For i = 0 To fileNames.Count() - 1
Dim fileName = fileNames(i)
sFileToFind = location & "\" & fileName & "*.*"
Dim paths = IO.Directory.GetFiles(location, fileName, IO.SearchOption.AllDirectories)
If Not paths.Any() Then
System.IO.File.AppendAllText(orphanedFiles, fileName & vbNewLine)
Else
For Each pathAndFileName As String In paths
If System.IO.File.Exists(pathAndFileName) = True Then
sRegLast = pathAndFileName.Substring(pathAndFileName.LastIndexOf("\") + 1)
Dim toFileLoc = System.IO.Path.Combine(createXMLFldr, sRegLast)
Dim moveToFolder = System.IO.Path.Combine(MoveLocation, "XML files", sRegLast)
'if toFileLoc = XML file exists move it into the XML files folder
If System.IO.File.Exists(toFileLoc) = False Then
System.IO.File.Copy(pathAndFileName, moveToFolder)
System.IO.File.AppendAllText(ListofFiles, sRegLast & vbNewLine)
fCount = fCount + 1
XMLFilename = (sRegLast) + vbCrLf
End If
End If
Next
End If
Dim srcCount = paths.Count()
If (paths.Count() = 0) Then
srcCount = 1
End If
Dim progress = CType(fCount * 100 / srcCount, Integer)
BackgroundWorker1.ReportProgress(progress)
Next
This for BackGroundWorker, I hope will this can resolve the trouble of the next call to update progress bar:
'This button1_click event to begin or stop async of backGrounedWorker
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
BackgroundWorker1.WorkerReportsProgress = True
BackgroundWorker1.WorkerSupportsCancellation = True
BackgroundWorker1.CancelAsync()
Try
BackgroundWorker1.RunWorkerAsync()
Catch ex As Exception
End Try
End Sub
'Here your backGroundProcess
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim FILE_NAME As String
FILE_NAME = txtFileName.Text 'can be changed
Dim fileNames = System.IO.File.ReadAllLines(FILE_NAME)
Dim Location As String = "C:\MyData\Folder1" 'can be changed
Dim moveToFolder As String = "C:\MyData\Folder2" 'can be changed
Dim fCount As Integer = 0
For Each fileName In fileNames
Dim paths = IO.Directory.GetFiles(Location, fileName,
IO.SearchOption.AllDirectories)
If paths.Count > 0 Then
Try
System.IO.File.Copy(paths(0), moveToFolder & "\" & fileName, True)
Catch ex As Exception
Debug.Print(ex.Message)
End Try
End If
For a = 1 To 100
Debug.Print(a.ToString)
Next
'If any request pending process will be stop (when Button1_click happen while process running (BackGroundWorker in Action))
If BackgroundWorker1.CancellationPending = True Then Exit For
fCount += 1
Dim Progress As Integer = Convert.ToInt32(fCount * 100 / fileNames.Count)
BackgroundWorker1.ReportProgress(progress)
Next
End Sub
'This will show you the progress in your progress bar
Private Sub bw1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
Me.ProgressBar1.Value = e.ProgressPercentage
End Sub
'Your Process Have Been Complete Here
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
MessageBox.Show("Finish")
End Sub
This last modification from me:
ListBox1.Items.Clear()
Dim FILE_NAME As String
FILE_NAME = "c:\YourFolder\YourFile.txt" 'can be changed
Dim fileNames = System.IO.File.ReadAllLines(FILE_NAME)
For Each MyFile In fileNames
ListBox1.Items.Add(MyFile)
Next
Dim Location As String = "C:\YourFolder1" 'can be changed
Dim moveToFolder As String = "C:\YourFolder2" 'can be changed
Dim fCount As Integer = 0
For Each fileName In fileNames
Dim paths = IO.Directory.GetFiles(Location, fileName,
IO.SearchOption.AllDirectories)
If paths.Count > 0 Then
Try
System.IO.File.Copy(paths(0), fileName)
Catch ex As Exception
End Try
End If
fCount += 1
Dim progress As Integer = Convert.ToInt32(fCount * 100 / fileNames.Count)
Next

Unable to cancel application

I have an application that copies files into different directories. As the application is running if I click the BtnExit_Click button nothing happens. I'm only able to exit out of the app after it has run through all the files to copy.
This is my code
Private Sub BtnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
BackgroundWorker1.CancelAsync()
Me.Close()
End Sub
Background Worker:
Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
Me.txtImgCount.Text = iCount
Me.txtImgCount.Update()
Me.fileCount.Text = fCount
Me.fileCount.Update()
Me.txtTotal.Update()
Me.Label8.Text = statusText
Me.Label8.Update()
Application.DoEvents()
Try
Me.RichTextBox1.Text &= (fileFilename)
Application.DoEvents()
Catch ei As DivideByZeroException
Debug.WriteLine("Exception caught: {0}", ei)
Finally
End Try
Try
Me.RichTextBox1.Text &= (imgFilename)
Application.DoEvents()
Catch ea As DivideByZeroException
Debug.WriteLine("Exception caught: {0}", ea)
Finally
End Try
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
RunCopyFiles()
End Sub
Private Sub RunCopyFiles()
BackgroundWorker1.WorkerReportsProgress = True
Dim sFileToFind As String
Dim location As String
'Dim File As String
statusText = "Initiating"
status = "Initiating..."
'Directory Files are located in
location = txtFolderPath.Text
'Directory ICN files are located in
imgLocation = txtSearchICN.Text
'Directory files are to copied into
MoveLocation = CopyToPath
createImgFldr = MoveLocation & "\Figures"
createReportFldr = MoveLocation & "\Reports"
createXMLFldr = MoveLocation & "\XML files"
'Create Figures Folder
If Not IO.Directory.Exists(createImgFldr) Then
IO.Directory.CreateDirectory(createImgFldr)
' MsgBox("folder created" & createFolder)
End If
'Create Reports folder
If Not IO.Directory.Exists(createReportFldr) Then
IO.Directory.CreateDirectory(createReportFldr)
'MsgBox("folder created" & createReportFldr)
End If
'Create XML folder
If Not IO.Directory.Exists(createXMLFldr) Then
IO.Directory.CreateDirectory(createXMLFldr)
' MsgBox("folder created" & createFolder)
End If
'Text file with list of file names
Dim filesToCopy = txtFileName.Text
orphanedFiles = MoveLocation & "\Reports\OrphanedFilesItems.txt"
' Create or overwrite the file.
System.IO.File.Create(orphanedFiles).Dispose()
ListofGraphics = MoveLocation & "\Reports\ListOfGraphics.txt"
' Create or overwrite the file.
System.IO.File.Create(ListofGraphics).Dispose()
Dim removDupBuildLog = MoveLocation & "\Reports\RemvoeDup.txt"
Dim ListLog = MoveLocation & "\Reports\ListOfGraphics.txt"
ListofFiles = MoveLocation & "\Reports\ListOfFiles.txt"
' Create or overwrite the file.
System.IO.File.Create(ListofFiles).Dispose()
MissingFiles = MoveLocation & "\Reports\MissingGraphicList.txt"
' Create or overwrite the file.
System.IO.File.Create(MissingFiles).Dispose()
Dim FILE_NAME As String
FILE_NAME = txtFileName.Text
Dim fileNames = System.IO.File.ReadAllLines(FILE_NAME)
status = "Copying SGML\XML Files"
statusText = "Copying SGML\XML Files..."
fCount = 0
For i = 0 To fileNames.Count() - 1
Dim fileName = fileNames(i)
sFileToFind = location & "\" & fileName & "*.*"
Dim paths = IO.Directory.GetFiles(location, fileName, IO.SearchOption.AllDirectories)
If Not paths.Any() Then
System.IO.File.AppendAllText(orphanedFiles, fileName & vbNewLine)
Else
For Each pathAndFileName As String In paths
If System.IO.File.Exists(pathAndFileName) = True Then
Dim sRegLast = pathAndFileName.Substring(pathAndFileName.LastIndexOf("\") + 1)
Dim toFileLoc = System.IO.Path.Combine(createXMLFldr, sRegLast)
Dim moveToFolder = System.IO.Path.Combine(MoveLocation, "XML files", sRegLast)
'if toFileLoc = XML file exists move it into the XML files folder
If System.IO.File.Exists(toFileLoc) = False Then
System.IO.File.Copy(pathAndFileName, moveToFolder)
System.IO.File.AppendAllText(ListofFiles, sRegLast & vbNewLine)
Application.DoEvents()
fileFilename = (fileName) + vbCrLf
fCount = fCount + 1
'fileCount.Text = fCount
End If
End If
Next
End If
BackgroundWorker1.ReportProgress(100 * (i + 1) / fileNames.Count)
Next
CreateGraphicsFunction()
GetImages()
Application.UseWaitCursor = False
Application.DoEvents()
End Sub
If you look at the code example in the documentation for the BackgroundWorker Class you will see that it checks the worker.CancellationPending property every time through the loop.
So you'll need a couple of changes:
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
RunCopyFiles(worker, e)
End Sub
Private Sub RunCopyFiles(worker As BackgroundWorker, e As DoWorkEventArgs)
... other code here
For Each pathAndFileName As String In paths
... other code here
If worker.CancellationPending Then
e.Cancel = True
Exit Sub
End If
Next
Maybe put another check just after the ReportProgress(...) too.
Also, you will need to set backgroundWorker1.WorkerSupportsCancellation = True.
The Application.UseWaitCursor = False should not be in the worker - put it in the code that calls backgroundWorker1.RunWorkerAsync().
As LarsTech wrote in a comment, you should remove all calls to Application.DoEvents(): problems with it are listed in Use of Application.DoEvents().
Finally, make sure that you are using Option Strict On.

Progress bar is not working in BackgroundWorker VB.Net

I'm trying to get a progress bar to show while a method is being executed. I've called BackgroundWorker1.RunWorkerAsync() from a button. Then in the DoWork I call the method to run "runCopyFiles". I update the progress in ProgressChanged, and exit with RunWorkerCompleted. I'm not sure what I have wrong. I've searched the net for tutorials and examples on how to do this and have created the code from them. But the progress bar doesn't show.
Code For executing from button
Private Sub btnExecuteFileCopy_Click(sender As Object, e As EventArgs) Handles btnExecuteFileCopy.Click
Me.Refresh()
If Not BackgroundWorker1.IsBusy = True Then
BackgroundWorker1.RunWorkerAsync()
End If
End Sub
Code for BackGroundWorker
Private Sub BackgroundWorker1_DoWork(sender As Object, e As ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
BackgroundWorker1.WorkerReportsProgress = True
Const Max As Integer = 1000
For i = 1 To Max
'' do something
'' (I put a sleep to simulate time consumed)
Threading.Thread.Sleep(100)
'' report progress at regular intervals
BackgroundWorker1.ReportProgress(CInt(100 * i / Max), "Running..." & i.ToString)
'' check at regular intervals for CancellationPending
If BackgroundWorker1.CancellationPending Then
BackgroundWorker1.ReportProgress(CInt(100 * i / Max), "Cancelling...")
Exit For
End If
Next
runCopyFiles()
End Sub
Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
ProgressBar1.Value = e.ProgressPercentage
lblStatus.Text = e.ProgressPercentage.ToString() + " %"
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If e.Cancelled = True Then
MsgBox(" Operation Cancelled ")
ProgressBar1.Value = 0
lblStatus.Text = ""
ElseIf e.Error IsNot Nothing Then
MsgBox(e.Error.Message)
Else
MsgBox(" Process Complete ")
End If
End Sub
Code RunCopy
Private Sub runCopyFiles()
Application.UseWaitCursor = True
Application.DoEvents()
Me.Refresh()
Dim sFileToFind As String
Dim location As String
Dim File As String
'Dim createReportFldr As String
'Dim createXMLFldr As String
'Dim createImgFldr As String
'Directory Files are located in
location = txtFolderPath.Text
'Directory files are to copied into
MoveLocation = CopyToPath
createImgFldr = MoveLocation & "\Figures"
createReportFldr = MoveLocation & "\Reports"
createXMLFldr = MoveLocation & "\XML files"
'Create Figures Folder
If Not IO.Directory.Exists(createImgFldr) Then
IO.Directory.CreateDirectory(createImgFldr)
' MsgBox("folder created" & createFolder)
End If
'Create Reports folder
If Not IO.Directory.Exists(createReportFldr) Then
IO.Directory.CreateDirectory(createReportFldr)
'MsgBox("folder created" & createReportFldr)
End If
'Create XML folder
If Not IO.Directory.Exists(createXMLFldr) Then
IO.Directory.CreateDirectory(createXMLFldr)
' MsgBox("folder created" & createFolder)
End If
orphanedFiles = MoveLocation & "\Reports\OrphanedFilesItems.txt"
' Create or overwrite the file.
System.IO.File.Create(orphanedFiles).Dispose()
ListofFiles = MoveLocation & "\Reports\ListOfFiles.txt"
' Create or overwrite the file.
System.IO.File.Create(ListofFiles).Dispose()
MissingFiles = MoveLocation & "\Reports\MissingGraphicList.txt"
' Create or overwrite the file.
System.IO.File.Create(MissingFiles).Dispose()
Dim FILE_NAME As String
FILE_NAME = txtFileName.Text
Dim objReader As New System.IO.StreamReader(FILE_NAME)
Dim sFile As String
Do While objReader.Peek() <> -1
File = objReader.ReadLine()
sFileToFind = location & "\" & File & "*.*"
sFile = File
Dim paths() As String = IO.Directory.GetFiles(location, sFile, IO.SearchOption.AllDirectories)
If paths.Count = 0 Then
System.IO.File.AppendAllText(orphanedFiles, sFile & vbNewLine)
' Debug.Print(File)
'If System.IO.File.Exists(orphanedFiles) = True Then
' Dim objWriter As New System.IO.StreamWriter(orphanedFiles, IO.FileMode.Append)
' objWriter.WriteLine(File)
' objWriter.Close()
'Else
'MsgBox("Creating Orphaned File Now. ")
'End If
Else
For Each pathAndFileName As String In paths
Dim moveToFolder As String
If System.IO.File.Exists(pathAndFileName) = True Then
Dim sRegLast As String = pathAndFileName.Substring(pathAndFileName.LastIndexOf("\") + 1)
Dim toFileLoc As String
'MsgBox("sRegLast " & sRegLast)
' fileLoc = MoveLocation & sRegLast
moveToFolder = MoveLocation & "\XML files\" & sRegLast
toFileLoc = createXMLFldr & "\" & sRegLast
'MsgBox("FileLoc " & fileLoc)
'if toFileLoc = XML file exists move it into the XML files folder
If System.IO.File.Exists(toFileLoc) = False Then
System.IO.File.Copy(pathAndFileName, moveToFolder)
System.IO.File.AppendAllText(ListofFiles, sRegLast & vbNewLine)
End If
End If
Next
End If
Loop
'MsgBox("Files have been moved")
Call CreateGraphicsFunction(Nothing, System.EventArgs.Empty)
Call getImages()
MsgBox("Process Complete", MsgBoxStyle.DefaultButton1)
Application.UseWaitCursor = False
Application.DoEvents()
' Me.Close()
End Sub
If you loop while there are more lines in your file, there's no way to know how many total lines there are, and that is a crucial component in the percent calculation for the progress bar:
percent = 100 * currentFile / totalFiles
So instead, we can read all lines up front and iterate over them. This should be your runCopyFiles
Dim fileNames = System.IO.File.ReadAllLines(FILE_NAME)
For i = 0 To fileNames.Count() - 1
Dim fileName = fileNames(i)
sFileToFind = location & "\" & fileName & "*.*"
Dim paths = IO.Directory.GetFiles(location, fileName, IO.SearchOption.AllDirectories)
If Not paths.Any() Then
System.IO.File.AppendAllText(orphanedFiles, fileName & vbNewLine)
Else
For Each pathAndFileName As String In paths
If System.IO.File.Exists(pathAndFileName) = True Then
Dim sRegLast = pathAndFileName.Substring(pathAndFileName.LastIndexOf("\") + 1)
Dim toFileLoc = System.IO.Path.Combine(createXMLFldr, sRegLast)
Dim moveToFolder = System.IO.Path.Combine(moveLocation, "XML files", sRegLast)
'if toFileLoc = XML file exists move it into the XML files folder
If System.IO.File.Exists(toFileLoc) = False Then
System.IO.File.Copy(pathAndFileName, moveToFolder)
System.IO.File.AppendAllText(ListofFiles, sRegLast & vbNewLine)
End If
End If
Next
End If
BackgroundWorker1.ReportProgress(100 * i / fileNames.Count())
Next
That is where the progress should be reported.
And all you should have in your DoWork is this
Private Sub BackgroundWorker1_DoWork(sender As Object, e As ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
runCopyFiles()
End Sub
You never need Application.DoEvents, and if you find that you do need it, then you are doing something wrong. DoWork calls code on a background thread which
Shouldn't access the UI without invoking calls on the UI thread
In turn doesn't block the UI from updating...
... which is really why you use it - so you can run processing code behind the UI without slowing it down.
In total, here are all the things you should remember to do
Don't access UI from background thread
Use Using to automatically dispose IDisposable objects
Use System.IO.Path.Combine to combine paths instead of using string concatenation
Don't call runCopyFiles 101 times
BackgroundWorker1.ReportProgress is meant to be called when you are doing work
If booleanValue = True Then is redundant, just do If booleanValue Then

VB2010 read a csv in datagrid, update in grid and save to same csv

Created a procedure in VB2010 to read a csv-file in datagridviewer, update cells in grid and save to same csvfile
Opening the csvfile in the datagridviewer works fine,
Updating in the datagridviewer works fine also
But when I save the datagrid to a csv-file with the same name, I get an error message "The process Can not access the file because it is used by an other process".
But if I save it to an other filename it is ok.
Then I tried to copy the new file with the new filename back to the original filename.
I received still the same error message that I cant copy because the file is still in use.
Does anybody now how to solve this.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim fName As String = ""
OpenFileDialog1.InitialDirectory = "H:\Data\2014\Software\VB2010\"
OpenFileDialog1.Filter = "CSV files (*.csv)|*.CSV"
OpenFileDialog1.FilterIndex = 2
OpenFileDialog1.RestoreDirectory = True
If (OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK) Then
fName = OpenFileDialog1.FileName
End If
Me.TextBox1.Text = fName
Dim TextLine As String = ""
Dim SplitLine() As String
DataGridView1.ColumnCount = 5
DataGridView1.Columns(0).Name = "Name"
DataGridView1.Columns(1).Name = "Gender"
DataGridView1.Columns(2).Name = "Age"
DataGridView1.Columns(3).Name = "Ranking"
DataGridView1.Columns(4).Name = "Date"
If System.IO.File.Exists(fName) = True Then
Dim objReader As New System.IO.StreamReader(fName)
Do While objReader.Peek() <> -1
TextLine = objReader.ReadLine()
SplitLine = Split(TextLine, ",")
Me.DataGridView1.Rows.Add(SplitLine)
Loop
Else
MsgBox("File Does Not Exist")
End If
End Sub
Private Sub SaveGridDataInFile(ByRef fName As String)
'method called by button2
Dim I As Integer = 0
Dim j As Integer = 0
Dim cellvalue$
Dim rowLine As String = ""
Try
Dim objWriter As New System.IO.StreamWriter(fName, True)
For j = 0 To (DataGridView1.Rows.Count - 2)
For I = 0 To (DataGridView1.Columns.Count - 1)
If Not TypeOf DataGridView1.CurrentRow.Cells.Item(I).Value Is DBNull Then
cellvalue = DataGridView1.Item(I, j).Value
Else
cellvalue = ""
End If
rowLine = rowLine + cellvalue + ","
Next
objWriter.WriteLine(rowLine)
rowLine = ""
Next
objWriter.Close()
objWriter = Nothing
MsgBox("Text written to file")
Catch e As Exception
MessageBox.Show("Error occured while writing to the file." + e.ToString())
Finally
FileClose(1)
End Try
Call copy_file()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
'çall method SaveGridDataInFile
SaveGridDataInFile(Me.TextBox1.Text)
' FileCopy("H:\Data\2014\Software\VB2010\datagr_ex2.csv", "H:\Data\2014\Software\VB2010\datagr_ex.csv")
End Sub
Sub copy_file()
Dim FileToDelete As String
FileToDelete = "H:\Data\2014\Software\VB2010\datagr_ex.csv"
If System.IO.File.Exists(FileToDelete) = True Then
System.IO.File.Delete(FileToDelete)
MsgBox("File Deleted")
End If
FileCopy("H:\Data\2014\Software\VB2010\datagr_ex2.csv", "H:\Data\2014\Software\VB2010\datagr_ex.csv")
End Sub
My guess is you need to close the StreamReader you use to load the file before you can reopen the file to save it. The StreamReader class implements IDisposable so you can use VB.Net's Using Statement to automatically close the file when you're finished reading, i.e.
If System.IO.File.Exists(fName) = True Then
Using objReader As New System.IO.StreamReader(fName)
Do While objReader.Peek() <> -1
TextLine = objReader.ReadLine()
SplitLine = Split(TextLine, ",")
Me.DataGridView1.Rows.Add(SplitLine)
Loop
End Using
Else
MsgBox("File Does Not Exist")
End If

How to attach a file to temporary location before sending a email with attachment?

I'm having a bit of trouble attaching a chosen file to my VB.net form before pressing my submit button which then sends a email with the attachment.
At the moment, my form can can open a dialog box to browse for file but I receive errors after choosing a file from a location on my machine.
Can anybody help please? Thanks.
This is the code I've used for the attachment button:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim openDLG As New OpenFileDialog
'openDLG.AddExtension = True
openDLG.ReadOnlyChecked = True
openDLG.Multiselect = True
openDLG.Title = "Select the file(s) you want added to the message..."
openDLG.Filter = "All Files (*.*)|*.*"
If openDLG.ShowDialog = Windows.Forms.DialogResult.OK Then
For Each item As String In openDLG.FileNames
'Create a new System.NET.Mail.Attachment class instance for each file.
attachToMsg = New System.Net.Mail.Attachment(item)
'Then add the attachment to your message. You have to do this everytime you run the code
'above.
EmailMessage.Attachments.Add(attachToMsg)
Next
MsgBox("I have finished adding all of the selected files! You can do more if you want!")
End If
End Sub
Button3 code:
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Using message As New MailMessage()
'set to the from, to and subject fields
message.From = (New MailAddress(TextBox3.Text.ToString()))
message.[To].Add(New MailAddress("NO.ONE#elsewhere.com"))
message.Subject = "New commission query"
'code the message body
Dim MsgBody As String
MsgBody = TextBox1.Text.ToString() & vbCr & _
TextBox2.Text.ToString() & vbCr & _
TextBox3.Text.ToString() & vbCr & _
ComboBox1.Text.ToString() & vbCr & _
ComboBox2.Text.ToString() & vbCr & _
ComboBox3.Text.ToString() & vbCr & _
ComboBox4.Text.ToString() & vbCr
message.Body = MsgBody
Dim client As New SmtpClient()
client.Host = "mailhost"
client.Send(message)
End Using
'display submitted box
MessageBox.Show("Your request has been submitted!", "Congratulations!")
'close form
Me.Close()
End Sub
Your "message" object in Button3_Click code and the "EmailMessage" in Button1_Click code ought to be the same "message" object.
As Steve mentions above...
Where do you have defined and initialized EmailMessage variable? Use the debugger and check if that variable is Nothing when you try to add an attachement – Steve 5 hours ago
Its all a case of WHERE you have DEFINED the EmailMessage object?
Maybe you should declare your EmailMessage object at FORM Level scope and then modify your Button3 code to access THAT SAME EmailMessage Instead of in the Attachment Procedure (Button1_Click code) and also you would need to "Instantiate" your EmailMessage message object before you attempt to modify its properties.
So you would have something along the lines of....
'Declarations section (form scope)
Dim TheEmailMessage As New MailMessage()
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim openDLG As New OpenFileDialog
'openDLG.AddExtension = True
openDLG.ReadOnlyChecked = True
openDLG.Multiselect = True
openDLG.Title = "Select the file(s) you want added to the message..."
openDLG.Filter = "All Files (*.*)|*.*"
If openDLG.ShowDialog = Windows.Forms.DialogResult.OK Then
For Each item As String In openDLG.FileNames
'Create a new System.NET.Mail.Attachment class instance for each file.
attachToMsg = New System.Net.Mail.Attachment(item)
'Then add the attachment to your message.
'You have to do this everytime you run the code above
TheEmailMessage.Attachments.Add(attachToMsg)
Next
MsgBox("I have finished adding all of the selected files! You can do more if you want!")
End If
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Using TheEmailMessage
'set to the from, to and subject fields
TheEmailMessage.From = (New MailAddress(TextBox3.Text.ToString()))
TheEmailMessage.[To].Add(New MailAddress("NO.ONE#elsewhere.com"))
TheEmailMessage.Subject = "New commission query"
'code the message body
Dim MsgBody As String
MsgBody = TextBox1.Text.ToString() & vbCr & _
TextBox2.Text.ToString() & vbCr & _
TextBox3.Text.ToString() & vbCr & _
ComboBox1.Text.ToString() & vbCr & _
ComboBox2.Text.ToString() & vbCr & _
ComboBox3.Text.ToString() & vbCr & _
ComboBox4.Text.ToString() & vbCr
TheEmailMessage.Body = MsgBody
Dim client As New SmtpClient()
client.Host = "mailhost"
client.Send(message)
End Using
'display submitted box
MessageBox.Show("Your request has been submitted!", "Congratulations!")
'close form
Me.Close()
End Sub
Put it in a temporary file (folder). Here is an example to extract the file from resource, put in a temporary file and open it. Returns the temporary folder used.
Public Overloads Function EXTRACT_FILE_FROM_RESOURCE(ByVal sFile As String, Optional ByVal andStart As Boolean = True) As String
Dim assembly As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
Dim root As String = assembly.GetName().Name
Dim stream As System.IO.Stream = assembly.GetManifestResourceStream(root & "." & sFile)
Dim buffer(Convert.ToInt32(stream.Length) - 1) As Byte
stream.Read(buffer, 0, buffer.Length)
stream.Close()
Dim sFolderUsed As String = GetTempDirectory()
Dim sFilePath As String
sFilePath = IO.Path.Combine(sFolderUsed , sFile )
Using f As New IO.FileStream(sFilePath , IO.FileMode.Create, IO.FileAccess.Write)
f.Write(buffer, 0, buffer.Length)
f.Close()
File.SetAttributes(sFilePath , File.GetAttributes(sFilePath ) And Not FileAttributes.ReadOnly)
End Using
If andStart Then
StartProcess(sFilePath )
End If
Return sFolderUsed
End Function
Public Function GetTempDirectory() As String
Dim pathx As String
Do
pathx = IO.Path.Combine(IO.Path.GetTempPath(), IO.Path.GetRandomFileName())
Loop Until Not Directory.Exists(pathx)
Directory.CreateDirectory(pathx)
Return pathx
End Function