Try-catch issue - vb.net

I am running across an issue in my program. I am reading a folder containing csv files and entering the data into a list of arrays. I have data enclosed within quotes.
However, the data is not pristine, and there are fields that have spare quotes that are causing issues.
I have set up a try/catch function that shunts the bad data into a manual verification routine. However, today the try/catch has started clearing the stack and reprocessing all the files from the top of the folder.
I have been using the messageboxes to trace exactly when the stack is getting cleared. It's happening at the start of the try/catch statement. It's not making it to the first messagebox.
Does anyone have any tips for continuing the program without losing the stack data?
files_ = Directory.GetFiles(path_, "*.ldf") 'picks out only the .ldf files
For i = 0 To files_.Length - 1 'i is the index for the number of ldf files in the folder. Number is i+1
i_string = CStr(i)
Using filereader1 As New Microsoft.VisualBasic.FileIO.TextFieldParser(files_(i), System.Text.Encoding.Default)
filereader1.TextFieldType = FieldType.Delimited
filereader1.Delimiters = New String() {","}
filereader1.HasFieldsEnclosedInQuotes = True
While Not filereader1.EndOfData
Try
split_string = filereader1.ReadFields()
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MessageBox.Show(ex.Message & " : " & FileName & " ; " & filereader1.ErrorLine & " LIST")
error_throw = filereader1.ErrorLine
MsgBox("LIST error throw")
Throw_Error = True
End Try

Related

Why does this command sometimes throw array bounds exceptions when it contains no arrays

I have a process that loops through an array which is a list of PDF filenames, for each file it must write a template PDF which is stored in the same folder as the exe and copy this to a network share as "pdffilename"~001.pdf and then copy the data file from an S3 bucket to the network share as "pdffilename"~002.pdf. In some cases, the file won't exist but we would still need the separator and sometimes the code would just be writing multiple separators (~001) and no data files but when this happens I randomly get failures in writing the separator pdf.
This works fine when running on my laptop through VS but when I deploy the app up to our application server it fails when there are lots of missing files.
If sFile(0) <> "999-Envelopes" Then
Try
boxTriggerReqd = True
My.Computer.FileSystem.CopyFile("doc_sep.pdf", OutputFolder & "\" & Replace(oFileName, "~002.pdf", "~001.pdf"), True)
Log.writeline("Document Separator written:" & vbTab & OutputFolder & "\" & Replace(oFileName, "~002.pdf", "~001.pdf"))
Catch ex As Exception
Call EndTask(ex.Message, "Unable to transfer Document separator", 11)
End Try
Else
envTriggerReqd = True
End If
Try
dlResponse = s3client.GetObject(GetFile)
With dlResponse
.WriteResponseStreamToFile(OutputFolder & "\" & oFileName)
.Dispose()
End With
Log.WriteLine("Data file written:" & vbTab & vbTab & OutputFolder & "\" & oFileName)
Catch ex As Exception
results.WriteLine(sFile(1))
Call EndTask(ex.Message, targetFile, 12)
results.Flush()
End Try
The error log shows
****** S3 PULL ******
Index was outside the bounds of the array.
Unable to transfer Document separator
****** S3 PULL ******
Where it has called EndTask contains the "Unable to transfer Document separator" so it has happened in one of three commands
I'm assuming its the CopyFile command but there is no reference to an array in any of those three. Is it possibly a memory error on the server itself?

VB.net SQL output loop rename file error on next loop

new to the stack here. I am developing some tools for work that allow us to pull information from a database and then operate on it with additional custom code. Since I need the output to not have a header, I want to have one file (as defined by schema.ini) that I will temporarily write the data into then copy and rename it before starting again. Using VS2017, when I debug it spits out the error that it cannot find RawC.txt after the first iteration. I cannot seem to figure out why. It is probably something simple but I have been unable to locate online. Can anyone help me out here? Below is the block I am having trouble with:
For each of the three files, output the sorted list. Schema has the correct format
For index = 0 To 2
If index = 0 Then
whicharr = arrSt(1)
ElseIf index = 1 Then
whicharr = arrSe(1)
ElseIf index = 2 Then
whicharr = arrVi(1)
End If
stopFile = "SELECT " & complist(index) & " INTO [Text;Database=" & TMPath & "].[RawC.txt] FROM [" & whicharr & "] ORDER BY " & complist(index)
cmd = New OleDbCommand(stopFile, conn)
cmd.ExecuteNonQuery()
'Now Copy and rename this file
My.Computer.FileSystem.CopyFile(TMPath & "\RawC.txt", TMPath & "\" & whicharr & ".txt")
'And delete the old RawC.txt file
My.Computer.FileSystem.DeleteFile(TMPath & "\RawC.txt")
Next
The final output from this loop should be three unique files that I will pass to another code that will perform some math on it.

How to read and write to controls or settings with Visual Basic

I am copying the string values out of text boxes on a form and saving them in the settings. The way I am doing it here seems kind of long handed. Is there a way to reference the TextBox1.Text and the My.Settings.Value1 with a string. If so then I could just loop through and keep changing the strings to point at the different controls. See the way I am currently doing it.
My.Settings.F1LabelCol0Save = F1LabelCol0.Text
My.Settings.F1LabelCol1Save = F1LabelCol1.Text
My.Settings.F1LabelCol2Save = F1LabelCol2.Text
My.Settings.F1LabelCol3Save = F1LabelCol3.Text
My.Settings.F1LabelCol4Save = F1LabelCol4.Text
My.Settings.F1LabelCol5Save = F1LabelCol5.Text
My.Settings.F1LabelCol6Save = F1LabelCol6.Text
My.Settings.F1LabelCol7Save = F1LabelCol7.Text
My.Settings.F1LabelCol8Save = F1LabelCol8.Text
My.Settings.F1LabelCol9Save = F1LabelCol9.Text
You can access both settings and controls dynamically via My.Settings.Item() and Me.Controls.Item().
I present you with two options:
1) Use a For loop for a fixed number range:
For x = 0 To 9
My.Settings("F1LabelCol" & x & "Save") = Me.Controls("F1LabelCol" & x).Text
Next
Upside: Does not swallow exceptions (see next example).
Downside: You must change the upper bound (currently 9) when you add new settings/controls.
2) Use a While loop for a dynamic number range.
Dim x As Integer = 0
While True
Try
My.Settings("F1LabelCol" & x & "Save") = Me.Controls("F1LabelCol" & x).Text
Catch
Exit While 'If an exception is thrown we've most likely hit the setting/control limit.
End Try
End While
Upside: Dynamic number range, you do not need to change anything when adding new settings/controls.
Downside: Swallows exceptions, i.e. you won't know when an exception is thrown for another reason than when a setting/control does not exist.
If you want to load data dynamically as well just reverse the get/set operation:
Me.Controls("F1LabelCol" & x).Text = My.Settings("F1LabelCol" & x & "Save")
I did some more research and here is how to do it. Now obviously it needs to be a number of of them very similarly named to to be worth it.
For i = 0 To 39
My.Settings("F1LabelCol" & i.ToString & "Save") = Me.Controls("F1LabelCol" & i.ToString).Text
Next

Many instances of the same process writing to the same log file

I am kicking off a number of instances of the same process and the issue is that they all write to the same log file. I know it is not a good practice and was wondering what can I do to avoid possible issues. Here is the procedure I use to write to file:
Sub WriteToErrorLog(ByVal Msg As String)
Dim path As String
path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)
Dim strFile As String = System.IO.Path.Combine(path, "Log_" & DateTime.Today.ToString("dd-MMM-yyyy") & ".txt")
Dim sw As StreamWriter
Dim fs As FileStream = Nothing
Try
If (Not File.Exists(strFile)) Then
fs = File.Create(strFile)
fs.Close()
End If
sw = File.AppendText(strFile)
sw.WriteLine(Msg & vbcrlf)
Catch ex As Exception
MsgBox("Error Creating Log File")
MsgBox(ex.Message & " - " & ex.StackTrace)
Finally
sw.Close()
End Try
End Sub
I would appreciate any suggestions/improvements. thanks!
As I have said in my comment, the scenario of multiple access to the same file resource should be handled carefully and probably the best solution is to use a well tested log library like Log4Net or NLog.
In any case you could improve your code in a couple of point
Sub WriteToErrorLog(ByVal Msg As String)
Dim path As String
path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)
Dim strFile As String = System.IO.Path.Combine(path, "Log_" & DateTime.Today.ToString("dd-MMM-yyyy") & ".txt")
Dim retry as Integer = 3 ' this could be changed if you experience a lot of collisions.'
Dim sw As StreamWriter = Nothing
While retry > 0
Try
Using sw = File.AppendText(strFile)
sw.WriteLine(Msg & vbcrlf)
End Using
Exit While
Catch ex as Exception
retry -= 1
End Try
End While
' If retry has reached zero then we have exausted our tentatives and give up....'
if retry = 0 Then
MessageBox.Show("Error writing to Log File")
End if
End Sub
I have removed all the part that check if file exists and then create it. This is not necessary because as the documentation explains, File.Append is the same that calling StreamWriter(file, true) and this means that if the file doesn't exist it will be created.
Next, to try to handle possible collision with other process writing to the same file concurrently, I have added a retry loop that could get access to the log file just after another process finishes.
(this is really a poor-man solution but then it is better to use a well tested library)
It is important to enclose the opening and writing of the file inside a using statement that closes and disposes the Stream also in case of exceptions. This is mandatory to be sure to leave the file always closed for the other processes to work.

Copy Resources to disk

First attempt at a VB.NET application. I am trying to create an application to copy standard configurations for an application then customize certain settings for that user. I have most of the application working fine but I'm having an issue with resource files.
Because the number of files may change I'm using a sub-folder for my resources. I have the files set to content and always copy. I can get the following code to work in debug but it seems I'm not doing it properly for build.
For Each strFile In Directory.GetFiles(".\Files")
If Path.GetExtension(Path.GetFileName(strFile)) = ".vbs" Then
strDestination = strDataPath & "Scripts\"
Else
strDestination = strDataPath
End If
If Not Directory.Exists(strDestination) Then
Directory.CreateDirectory(strDestination)
End If
If My.Settings.chkForceOverwrite = True Then
Try
File.Copy(strFile, strDestination & Path.GetFileName(strFile), True)
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
Else
Try
File.Copy(strFile, strDestination & Path.GetFileName(strFile), False)
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End If
Next
I have attempted several ways of copying the data but I can find nothing compatible, like the following.
Dim strFileName As String = Path.GetFileNameWithoutExtension(strFile)
File.WriteAllBytes(strDestination & strFile, My.Resources.strFileName, True)
Can someone point me in the proper and correct direction to do this? Currently the file types are 1 .vbs and 1 .exe.config file but I may need to add different file types in the future.
About this code ..
File.WriteAllBytes(strDestination & strFile, My.Resources.strFileName, True)
If you access some special folder such as Desktop and retrieve from app resource , you make it like this
File.WriteAllBytes(My.Computer.FileSystem.SpecialDirectories.Desktop & "\" & strFile, My.Resources.ResourceManager.GetObject(strFileName), True)
It seems the issue is this line For Each strFile In Directory.GetFiles(".\Files")
.\Files is referring to a relative path that doesn't exist when you move the .exe.