Call Stack size? - vb.net

Greetings from Michigan,
I have a program that runs continuously (logging data) where it runs inside a While loop within one Sub ("logging data" Sub), then when the log file becomes "full", it jumps to another Sub to create a new file, then jumps back to the "logging data" Sub to continue on. Anyway, it keeps doing this and can run for hours like this, creating 100+ files or more of data. The problem is that the program crashes at some point and it always crashes within this part of the program (one of these two subs, although I haven't pinpointed which one. When I run the debugger on the machine in which the program is deployed, the Call Stack is rather large. I'm wondering if that is a problem, and how is that managed. Could that be the reason for the program crashing (Call stack getting too large?). I have gotten some sort of memory exception error on at least one of the crashes. I made some edits to the code yesterday to try and alleviate this. This last crash (this morning when I got into the office) that I experienced was a nullreference exception error, although I can't pinpoint where unless I run the program from my development machine in debug mode, which I plan to do next to catch exactly what line of code the crash is happening within either of these two Subs. I'll need to run it overnight as like I said, the program can run for hours before a crash occurs. Anyway, the question is in regards to the Call Stack. Is the large Call Stack a problem? How is that managed/cleared?
Thanks,
D
Public Sub dataAcquiring()
'Receive the collection of channels in this sub and append data to each of the channels
'Set up the channel group
Dim message1 As String = "The data file may have been deleted or moved prior to a new data file and directory being created. Check the main 'Data' directory and be sure the file exists, or simply create a new data file."
Dim testBool As Boolean = False
'Set the global variable to True if running the application from the development machine in debug mode. Otherwise, initialize it to false for deployment.
If Connectlocal = True Then
statsFile = "C:\Users\dmckin01\Desktop\Data\" & folderName & "\" & dataFileName & "_stats.csv"
Else : statsFile = "D:\Data\" & folderName & "\" & dataFileName & "_stats.csv"
End If
Try
logFile.Open()
Catch ex As Exception
MessageBox.Show(Me, ex.Message & message1, "File not found", MessageBoxButtons.OK, MessageBoxIcon.Error)
cbRecord.Checked = False
Return
End Try
Dim i As Integer = 0, n As Integer = 0, hvar As Integer, value As Single, count As Integer = 0, maxValue As Single
Dim b As Boolean = False, returnValue As Type, stringVar As String, lastValidNumber As Integer
Dim dtype As System.Type
Dim channelGroupName As String = "Main Group"
Dim channelGroup As TdmsChannelGroup = New TdmsChannelGroup(channelGroupName)
Dim channelGroups As TdmsChannelGroupCollection = logFile.GetChannelGroups()
If (channelGroups.Contains(channelGroupName)) Then
channelGroup = channelGroups(channelGroupName)
Else
channelGroups.Add(channelGroup)
End If
'Set up the TDMS channels
Dim Names As String() = New String(13) {" Spindle Speed (rpm) ", " Oil Flow (ccm) ", " Torque (Nm) ", " LVDT Displacement (mm) ", " Linear Pot Displacement (mm) ", _
" Pneu. Actuator (0=OFF, 1=ON) ", " Elec. Actuator (0=OFF, 1=ON) ", " Hydr. Actuator (0=OFF, 1=ON) ", _
" Upper Tank Oil Temp. (°F) ", " Lower Tank Oil Temp. (°F) ", " Exit Oil Temp. (°F) ", _
" Inlet Oil Temp. (°F) ", " Part Temp. (°F) ", " Time Stamp "}
Dim dataArrayNames As String() = New String(13) {"arrSpeed", "arrFlow", "arrTorque", "arrLVDT", "arrLinPot", "arrActPneu", "arrActElec", "arrActHydr", _
"arrUpperOil", "arrLowerOil", "arrExitOil", "arrInletOil", "arrTestPart", "arrTimeStamp"}
Dim OPCTagNames As String() = New String(13) {"peakTorque", "peakTorqueSpeed", "peakTorquePlatePos", "timeToPeakTorque", "firstPeakTorque", "firstPeakTorqueSpeed", _
"firstPeakTorquePlatePos", "timeToFirstPeakTorque", "peakDecel", "peakJerk", "engagementSpeed", "slidePlateSpeed", _
"timeOfEngagement", "totalEnergy"}
Dim bools As Boolean() = New Boolean(13) {recSpeed, recOilFlow, recTorque, recLVDT, recLinPot, recActPneu, recActElec, recActHydr, recUpperOil, recLowerOil, _
recExitOil, recInletOil, recTestPart, recTimeStamp}
'Instantiate the TDMS channels to be used. We have to do this each and every time this Sub is executed because National Instruments
'does not have a method to 'clear' the channel group.
Dim ch0 As TdmsChannel = New TdmsChannel(Names(0), TdmsDataType.Float) 'spindle speed
Dim ch1 As TdmsChannel = New TdmsChannel(Names(1), TdmsDataType.Float) 'oil flow
Dim ch2 As TdmsChannel = New TdmsChannel(Names(2), TdmsDataType.Float) 'torque
Dim ch3 As TdmsChannel = New TdmsChannel(Names(3), TdmsDataType.Float) 'actuator position (LVDT)
Dim ch4 As TdmsChannel = New TdmsChannel(Names(4), TdmsDataType.Float) 'actuator position (LINEAR POT)
Dim ch5 As TdmsChannel = New TdmsChannel(Names(5), TdmsDataType.Float) 'actuator state (pneu)
Dim ch6 As TdmsChannel = New TdmsChannel(Names(6), TdmsDataType.Float) 'actuator state (elec)
Dim ch7 As TdmsChannel = New TdmsChannel(Names(7), TdmsDataType.Float) 'actuator state (hydr)
Dim ch8 As TdmsChannel = New TdmsChannel(Names(8), TdmsDataType.Float) 'upper oil tank temp
Dim ch9 As TdmsChannel = New TdmsChannel(Names(9), TdmsDataType.Float) 'lower oil tank temp
Dim ch10 As TdmsChannel = New TdmsChannel(Names(10), TdmsDataType.Float) 'Exit oil tank temp
Dim ch11 As TdmsChannel = New TdmsChannel(Names(11), TdmsDataType.Float) 'Inlet oil temp
Dim ch12 As TdmsChannel = New TdmsChannel(Names(12), TdmsDataType.Float) 'Part temp
Dim ch13 As TdmsChannel = New TdmsChannel(Names(13), TdmsDataType.String) 'Time stamp
Dim Channels As TdmsChannelCollection
Dim chans As TdmsChannel() = New TdmsChannel(13) {ch0, ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8, ch9, ch10, ch11, ch12, ch13}
Channels = channelGroup.GetChannels()
ch0.UnitString = "RPM" : ch0.Description = "Rotational speed of the spindle shaft."
ch1.UnitString = "CCM" : ch1.Description = "Oil flow from the specimen pump."
ch2.UnitString = "Nm" : ch2.Description = "Torque from the torque cell."
ch3.UnitString = "mm" : ch3.Description = "Linear displacement of the linear velocity displacement transducer."
ch4.UnitString = "mm" : ch4.Description = "Linear displacement of the linear potentiometer."
ch5.UnitString = "BIT" : ch5.Description = "Binary state of the pneumatic actuator (0=OFF, 1=ON)."
ch6.UnitString = "BIT" : ch6.Description = "Binary state of the electric actuator (0=OFF, 1=ON)."
ch7.UnitString = "BIT" : ch7.Description = "Binary state of the hydraulic actuator (0=OFF, 1=ON)."
ch8.UnitString = "°F" : ch8.Description = "Upper tubular tank oil temperature."
ch9.UnitString = "°F" : ch9.Description = "Lower (main) tank oil temperature."
ch10.UnitString = "°F" : ch10.Description = "Thermocouple (Location: Remote rack, EL3318, Ch.2)."
ch11.UnitString = "°F" : ch11.Description = "Thermocouple (Location: Remote rack, EL3318, Ch.3)."
ch12.UnitString = "°F" : ch12.Description = "Thermocouple (Location: Remote rack, EL3318, Ch.1)"
ch13.UnitString = "nS" : ch13.Description = "Time when the data was captured."
'The only TDMS channels that get added to the collection are the ones that the user selects on the 'Configure Data File' form.
'That is what this If-Then block is for.
If Channels.Count = 0 Then
jArray.Clear()
plcArrayNames.Clear()
For Each [boolean] In bools
If [boolean] = True Then
Channels.Add(chans(i))
Channels = channelGroup.GetChannels 'new
jArray.Add(jaggedarray(i))
plcArrayNames.Add(dataArrayNames(i))
End If
i += 1
Next
End If
'At this point, we are ready to write data to the TDMS file.
'Establish the line of communication to the PLC so we can read the data arrays.
Dim tcClient As New TwinCAT.Ads.TcAdsClient()
Dim dataStreamRead As TwinCAT.Ads.AdsStream = New AdsStream
Dim binaryReader As System.IO.BinaryReader = New BinaryReader(dataStreamRead)
If Connectlocal = True Then
tcClient.Connect(851) 'local
Else : tcClient.Connect(AMSNetID, 851)
End If
While cbRecord.Checked = True
b = tcClient2.ReadAny(DRHvar, GetType(Boolean)) 'read the handshaking variable from the PLC
If b = False Then
'This For loop reads the appropriate arrays in the PLC and then writes that data to the appropriate arrays here.
'The arrays in here will eventually get written to the TDMS file.
i = 0
n = 0
writingData = True
For Each [string] In dataArrayNames
If dataArrayNames(n) = plcArrayNames(i) Then
hvar = tcClient.CreateVariableHandle("IO_HS.Data." & dataArrayNames(n))
value = 0
returnValue = jArray(i).GetType
If returnValue.Name = "Single[]" Then
dataStreamRead.SetLength(jArray(0).Length * 4)
dataStreamRead.Position = 0
tcClient.Read(hvar, dataStreamRead)
For Each [element] In jArray(0)
jArray(i)(value) = binaryReader.ReadSingle()
value += 1
Next
ElseIf returnValue.Name = "Int64[]" Then
dataStreamRead.SetLength(jArray(0).Length * 8)
dataStreamRead.Position = 0
tcClient.Read(hvar, dataStreamRead)
For Each [element] In jArray(0)
jArray(i)(value) = binaryReader.ReadInt64()
value += 1
Next
ElseIf returnValue.Name = "String[]" Then
dataStreamRead.SetLength(jArray(0).Length * 32)
dataStreamRead.Position = 0
tcClient.Read(hvar, dataStreamRead)
For Each [element] In jArray(0)
stringVar = binaryReader.ReadChars(32)
lastValidNumber = Math.Max(Math.Max(Math.Max(Math.Max(Math.Max(Math.Max(Math.Max(Math.Max(Math.Max(stringVar.LastIndexOf("0"), stringVar.LastIndexOf("1")), stringVar.LastIndexOf("2")), stringVar.LastIndexOf("3")), stringVar.LastIndexOf("4")), stringVar.LastIndexOf("5")), stringVar.LastIndexOf("6")), stringVar.LastIndexOf("7")), stringVar.LastIndexOf("8")), stringVar.LastIndexOf("9"))
If lastValidNumber > 0 Then
jArray(i)(value) = stringVar.Substring(0, lastValidNumber + 1)
Else
jArray(i)(value) = "Invalid Timestamp"
End If
value += 1
Next
End If
tcClient.DeleteVariableHandle(hvar)
i += 1
If i = plcArrayNames.Count Then
Exit For
End If
End If
n += 1
Next
'This For loop appends/writes the data from each array to the actual TDMS file.
i = 0
For Each [array] In jArray
dtype = Channels(i).GetDataType
If dtype.Name = "Int32" Then
Channels(i).AppendData(Of Integer)(jArray(i))
ElseIf dtype.Name = "Single" Then
Channels(i).AppendData(Of Single)(jArray(i))
ElseIf dtype.Name = "Boolean" Then
Channels(i).AppendData(Of Boolean)(jArray(i))
ElseIf dtype.Name = "String" Then
Channels(i).AppendData(Of String)(jArray(i))
End If
i += 1
Next
Try
'Call the DataAnalyzer dll to write stats of the cycle to stats CSV file. Also plot the data of the cycle on the chart on the UI
Invoke(Sub() DataAnalyzer.Analyze(arrSpeed, arrTorque, arrLinPot))
Invoke(Sub() plotData())
Invoke(Sub() DataAnalyzer.WriteData(statsFile, logFile.Path, arrTimeStamp(0), plcData.cyclesCompleted))
Catch ex As Exception
testBool = True
End Try
'Populate the datagridview cells with the data values
dgvStats.Item(1, 0).Value = DataAnalyzer.peakTorque
dgvStats.Item(1, 1).Value = DataAnalyzer.engagementSpeed
dgvStats.Item(1, 2).Value = DataAnalyzer.slidePlateSpeed
dgvStats.Item(1, 3).Value = plcData.bimbaTravSpeed
dgvStats.Item(1, 4).Value = plcData.lastCycleTime
dgvStats.Item(1, 5).Value = plcData.currentCycleTime
dgvStats.Item(1, 6).Value = plcData.meanCycleTime
dgvStats.Item(1, 7).Value = plcData.cyclesPerHr
'NEW CODE to Evalute the elements in the arrTorque array to get the Max value recorded
maxValue = 0
For Each [element] In arrTorque
maxValue = Math.Max(maxValue, element)
Next
If maxValue <= plcData.torqueAlrmSP And plcData.cycleStarted Then
torqueLowCount += 1
Else : torqueLowCount = 0
End If
'Let the PLC know that we received the data and are now ready for the next set (handshaking variable).
tcClient2.WriteAny(DRHvar, True)
End If
'If the data count in the first column of the TDMS file exceeds the number here, then
'close the file and create a new one, then continue to append/write data
If Channels(0).DataCount >= 1020000 Then
For Each channel As TdmsChannel In chans
channel.Dispose() : channel = Nothing
Next
chans = Nothing
channelGroup.Dispose() : channelGroup = Nothing
If tcClient.IsConnected Then
dataStreamRead.Dispose() : dataStreamRead = Nothing
tcClient.Disconnect() : tcClient.Dispose() : tcClient = Nothing
End If
'Jump to the CreateNewFile Sub to create the next TDMS file
CreateNewFile()
End If
End While
If logFile.IsOpen = True Then
logFile.Close()
End If
If tcClient.IsConnected Then
dataStreamRead.Dispose() : dataStreamRead = Nothing
tcClient.Disconnect() : tcClient.Dispose() : tcClient = Nothing
End If
writingData = False
End Sub
Private Sub CreateNewFile()
'Create the new folder where the data file/s will reside
Dim newFilename As String = dataFileName & "_" & fileNum
Dim customFilePropertyNames() As String = {"Date"}
Dim customFilePropertyVals() As String = {""}
Dim newAuthor As String = logFile.Author
Dim newDescription As String = logFile.Description
Dim newTitle As String = logFile.Title
Dim newPath1 As String = "C:\Users\dmckin01\Desktop\Data\" & folderName
Dim newPath2 As String = "D:\Data\" & folderName
fileNum += 1
'Create the TDMS file and save it to the user specified directory
customFilePropertyVals(0) = Date.Today.ToShortDateString()
logFile.Close() 'Close the old logfile after we've gotten values/properties from it
logFile.Dispose() : logFile = Nothing
Try
If Connectlocal = True Then
logFile = New TdmsFile(newPath1 & "\" & newFilename & ".tdms", New TdmsFileOptions())
Else : logFile = New TdmsFile(newPath2 & "\" & newFilename & ".tdms", New TdmsFileOptions())
End If
Catch ex As Exception
MessageBox.Show("Directory not created. Make sure the TDMS file and/or directory that you are referencing are not already currently opened.", "Directory Creation Failed", MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
End Try
logFile.Author = newAuthor
logFile.Description = newDescription
logFile.Title = newTitle
logFile.AddProperty(customFilePropertyNames(0), TdmsPropertyDataType.String, customFilePropertyVals(0))
logFile.AutoSave = True
dataAcquiring()
End Sub

Stack errors are always caused by loops in your code that call back on themselves. Often caused by property setting handlers that set other properties that, in their turn, try to set the initial property. They can be difficult to pinpoint sometimes.
In your case, you have called the logging function
dataAcquiring()
End Sub
At then end of the file creation routine... this is a SERIOUS bug.
Each time you start a new file you start a new instance of the log loop and the old one remains on the stack... it's just a matter of time till it runs out of room
In this instance... the create routine should just exit..
However, if it were me I would make that code a function that returns true or false. Have it return false if the file could not be created for some reason and handle it gracefully in the main loop.

Related

VBA Macros in CorelDraw. Export current selection

Everyone! 
I'm working on macros which should select cdrBitmapShape and save it as a separate file.
I've already found out how to search and select such an object, but I've run into a problem of saving it.
I don't get how should I save the chosen image, it is quite unclear from the docs.
As I understand from here  I should somehow assign to the Document variable the current selection Item and export it.
Here is the test file
How can I do that?
Sub Findall_bit_map()
' Recorded 03.02.2020
'frmFileConverter.Start
'Dim d As Document
Dim retval As Long
Dim opt As New StructExportOptions
opt.AntiAliasingType = cdrNormalAntiAliasing
opt.ImageType = cdrRGBColorImage
opt.ResolutionX = 600
opt.ResolutionY = 600
Dim pal As New StructPaletteOptions
pal.PaletteType = cdrPaletteOptimized
pal.NumColors = 16
pal.DitherType = cdrDitherNone
Dim Filter As ExportFilter
Set OrigSelection = ActivePage.ActiveLayer.Shapes.All
For Each shpCheck In OrigSelection
re = shpCheck.Type
If shpCheck.Type = cdrBitmapShape Then
retval = MsgBox("BITMAP", vbOKCancel, "Easy Message")
shpCheck.AddToSelection
Set Filter = Document.ExportBitmap("D:\some.jpg", cdrJPEG)
If Filter.ShowDialog() Then
Filter.Finish
Else
MsgBox "Export canceled"
End If
End If
Next shpCheck
retval = MsgBox("Click OK if you agree.", vbOKCancel, "Easy Message")
'ActivePage.Shapes.FindShapes(Query:="#type='BitmapShape'")
If retval = vbOK Then
MsgBox "You clicked OK.", vbOK, "Affirmative"
End If
End Sub
I don't know were was the bug, but here is the working version.
Sub Findall_bit_map_snip()
Dim retval As Long
Dim doc As Document
Dim pal As New StructPaletteOptions
pal.PaletteType = cdrPaletteOptimized
pal.ColorSensitive = True
pal.NumColors = 300000000
pal.DitherType = cdrDitherNone
Dim Filter As ExportFilter
Set OrigSelection = ActivePage.ActiveLayer.Shapes.All
For Each shpCheck In OrigSelection
Set doc = ActiveDocument
doc.ClearSelection
re = shpCheck.Type
If shpCheck.Type = cdrBitmapShape Then
retval = MsgBox("BITMAP", vbOKCancel, "Easy Message")
shpCheck.AddToSelection
Set Filter = doc.ExportBitmap("D:\some.jpg", cdrJPEG, cdrSelection, , , , 600, 600, cdrNoAntiAliasing, , False, , , , pal)
Filter.Finish
End If
Next shpCheck
End Sub

Adding Multiple TreeNode Levels with Multi threading

i'm having alot of trouble trying to get a background worker properly functioning to populate a couple of TreeView Nodes. In said TreeView i have multiple levels of Nodes. For example
FileName
Model
Test & Result.
Model refers to a MicroStation Model (CAD Drawing Program), easiest way to explain it is a Sheet within a Spreadsheet.
I'm using a FileDialog to select files, once the files are selected each filename is added to the TreeView with its own Node.
The idea is that the program will then open each file, scan each model and add a sub TreeNode under the files Node wih the type of test and the result.
The DoWork function for the Background worker is below. I have removed alot of the code to simply my post. But there are 7 "tests" that the program does, i have included 2.
In the below example, "CheckFonts" is a function that just counts the text elements in a file and returns a number.
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
For i As Integer = 0 To m_CountTo
If BackgroundWorker1.CancellationPending Then
e.Cancel = True ' Set Cancel to True
Exit For
End If
Dim sError As String = ""
Dim bBorderFound As Boolean = False
Dim oDesignFile As DesignFile
Dim oModel As ModelReference
Dim oFontNode As New TreeNode
Dim oFontResultNode As New TreeNode
For Each oNode As TreeNode In trvItems.Nodes
Dim ustn As New MicroStationDGN.Application
oDesignFile = ustn.OpenDesignFileForProgram(oNode.Text, True)
For Each oModel In oDesignFile.Models
'####### Checks for Items on Default Level #######
If bDefaultPass = True Then
Dim iDefaultItems As Long
iDefaultItems = DefaultItems(oModel)
If iDefaultItems > 0 Then
sDefaultMessage = "There are " & iDefaultItems & " items on the Default Level"
bDefaultPass = False
Else
sDefaultMessage = "There are no items on the Default Level"
bDefaultPass = True
End If
End If
'####### Checks for Non Standard Fonts #######
If bFontPass = True Then
Dim iFontCheck As Long
iFontCheck = CheckFonts(oModel)
If iFontCheck > 0 Then
sFontMessage = "There are " & iFontCheck & " Text Elements that use a Non Standard Font."
bFontPass = False
ElseIf iFontCheck = -99999 Then
sFontMessage = "There are some corrupt or invalid Fonts used in the Design File"
bFontPass = False
Else
sFontMessage = "All Text Elements use the Correct Font"
bFontPass = True
End If
End If
Next ' End Model
oFontNode = oNode.Nodes.Add("Font Check")
oFontResultNode = oFontNode.Nodes.Add("")
If bFontPass = True Then
oFontResultNode.Text = "PASS - " & sFontMessage
oFontResultNode.ImageIndex = 0
oNode.Collapse()
Else
oFontResultNode.Text = "FAIL - " & sFontMessage
bPass = False
oFontResultNode.ImageIndex = 1
oFontNode.ImageIndex = 1
oNode.Expand()
oFontNode.Expand()
End If
oDefaultItemsNode = oNode.Nodes.Add("Default Items Check")
oDefaultItemsResultNode = oDefaultItemsNode.Nodes.Add("")
If bDefaultPass = True Then
oDefaultItemsResultNode.Text = "PASS - " & sDefaultMessage
oDefaultItemsResultNode.ImageIndex = 0
oNode.Collapse()
Else
oDefaultItemsResultNode.Text = "FAIL - " & sDefaultMessage
oDefaultItemsResultNode.ImageIndex = 1
oDefaultItemsResultNode.ImageIndex = 1
oNode.Expand()
bPass = False
End If
Next ' End File
Next
End Sub
I have worked with Background Workers before but this is a bit more complex to what i have done, i understand that you cant update controls from a different thread and that Invoke is used to pass it information. But i'm confused how to do it with multiple nodes. The best example I saw was here
Adding nodes to treeview with Begin Invoke / Invoke
But with multiple nodes the code became quite confusing and didn't work. The error message keeps coming up regarding the Invoke / BeginInvoke being called.
So, i guess my main question is where i would call the Invoke command to best make use of the Background worker?
Thanks in advance!!

VB Reading a text file into a 2D array?

I am trying to create a sudoku game, with load and save game functions in VB and I was wondering how it would be possible to load a save file(the numbers on the sudoku board and time score) and make the numbers within the file correspond to their exact location on the new board. For saving the file I have this:
Private Sub saveBoard(fileName As String)
Dim f As StreamWriter = New StreamWriter(fileName)
For col = 0 To 8
Dim sudokuLine = ""
For row = 0 To 8
If (board(row, col).Text = "") Then
sudokuLine += "0"
Else : sudokuLine += board(row, col).Text
End If
sudokuLine += " "
Next
f.WriteLine(sudokuLine)
Next
f.WriteLine(lblMinutes.Text + " " + lblSeconds.Text)
f.Close()
End Sub
Also I know about StreamReader...
This could be the loadBoard that corresponds to your saveBoard.
Of course a bit of testing is required here and a more fool proof approach to handle critical errors (like a different file passed as input) .
Notice that I have added the using statement around the opening of the Stream. This should be done also in the saveBoard above to avoid problems with files locked in case of exceptions.
Private Sub loadBoard(fileName As String)
Using f = New StreamReader(fileName)
For col = 0 To 8
Dim sudokuColumn = f.ReadLine()
Dim cells() = sudokuColum.Split()
For row = 0 To 8
If cells(row, col) = "0") Then
boards(row, col).Text = ""
Else
board(row, col).Text = cells(row,col)
End If
Next
Next
lblMinutes.Text = f.ReadLine()
End Using
End Sub

What is causing 'Index was outside the bounds of the array' error?

What is causing 'Index was outside the bounds of the array' error? It can't be my file, defianetly not. Below is my code:
Sub pupiltest()
Dim exitt As String = Console.ReadLine
Do
If IsNumeric(exitt) Then
Exit Do
Else
'error message
End If
Loop
Select Case exitt
Case 1
Case 2
Case 3
End Select
Do
If exitt = 1 Then
pupilmenu()
ElseIf exitt = 3 Then
Exit Do
End If
Loop
Dim score As Integer
Dim word As String
Dim totalscore As Integer = 0
'If DatePart(DateInterval.Weekday, Today) = 5 Then
'Else
' Console.WriteLine("You are only allowed to take the test on Friday unless you missed it")
' pupiltest()
'End If
Dim founditem() As String = Nothing
For Each line As String In File.ReadAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv")
Dim item() As String = line.Split(","c)
founditem = item
Next
Dim stdntfname As String = founditem(3)
Dim stdntsname As String = founditem(4)
Dim stdntyear As String = founditem(5)
Console.Clear()
If founditem IsNot Nothing Then
Do
If stdntyear = founditem(5) And daytoday = founditem(6) Then
Exit Do
ElseIf daytoday <> founditem(6) Then
Console.WriteLine("Sorry you are not allowed to do this test today. Test available on " & item(6).Substring(0, 3) & "/" & item(6).Substring(3, 6) & "/" & item(6).Substring(6, 9))
Threading.Thread.Sleep(2500)
pupiltest()
ElseIf stdntyear <> founditem(5) Then
Console.WriteLine("Year not found, please contact the system analysts")
Threading.Thread.Sleep(2500)
pupiltest()
End If
Loop
End If
For Each line As String In File.ReadAllLines("F:\Computing\Spelling Bee\testtests.csv")
Dim item() As String = line.Split(","c)
Dim mine As String = String.Join(",", item(2), item(3), item(4), item(5), item(6))
For i As Integer = 1 To 10
Console.WriteLine(i.ToString & "." & item(1))
Console.Write("Please enter the word: ")
word = Console.ReadLine
If word = Nothing Or word <> item(0) Then
score += 0
ElseIf word = item(0) Then
score += 2
ElseIf word = mine Then
score += 1
End If
Next
If score > 15 Then
Console.WriteLine("Well done! Your score is" & score & "/20")
ElseIf score > 10 Then
Console.WriteLine("Your score is" & score & "/20")
ElseIf score Then
End If
Next
Using sw As New StreamWriter("F:\Computing\Spelling Bee\stdntscores", True)
sw.Write(stdntfname, stdntsname, stdntyear, score, daytoday, item(7))
Try
Catch ex As Exception
MsgBox("Error accessing designated file")
End Try
End Using
End
End Sub
All help is highly appreciated,
You are constantly replacing the foundItem array when you do founditem = item:
Dim founditem() As String = Nothing
For Each line As String In File.ReadAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv")
Dim item() As String = line.Split(","c)
founditem = item
Next
Also, you are using (=) the assignment operation instead of (==) relational operator, to compare. Refer to this article for help in understanding the difference between the two.
Instead of this: If stdntyear = founditem(5) And daytoday = founditem(6) Then
Use this: If (stdntyear == founditem(5)) And (daytoday == founditem(6)) Then
Now back to your main error. You continue to assign the itemarray to founditem every time you iterate (Which overwrites previous content). At the end of the Iteration you will be left with the last entry in your CSV only... So in other words, founditem will only have 1 element inside of it. If you try to pick out ANYTHING but index 0, it will throw the exception index was outside the bounds of the array
So when you try to do the following later, it throws the exception.
Dim stdntfname As String = founditem(3) 'index 3 does not exist!
To fix it do the following change:
Dim founditem() As String = Nothing
For Each line As String In File.ReadAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv")
'NOTE: Make sure you know exactly how many columns your csv has or whatever column
' you wish to access.
Dim item() As String = line.Split(","c)
founditem(0) = item(0) 'Assign item index 0 to index 0 of founditem...
founditem(1) = item(1)
founditem(2) = item(2)
founditem(3) = item(3)
founditem(4) = item(4)
founditem(5) = item(5)
founditem(6) = item(6)
Next
For more help on how to work with VB.NET Arrays visit this site: http://www.dotnetperls.com/array-vbnet
In your line Dim item() As String = line.Split(","c) there's no guarantee that the correct number of elements exist. It's possible that one of the lines is missing a comma or is a blank trailing line in the document. You might want to add a If item.Length >= 7 and skipping rows that don't have the right number of rows. Also, remember that unlike VB6, arrays in .Net are 0 based not 1 based so make sure that item(6) is the value that you think it is.

Difficulty reading and writing binary files

My code works on my 64-bit machine but I encounter the following error (occasionally the code works fine however) when running it on a 32-bit machine:
InvalidCastException was unhandled
The next few lines provide my code:
To write to the binary file:
Dim writeStream = New FileStream(path, FileMode.Open)
Dim BinReader As BinaryReader
next_byte = Len(CStr(time)) + Len("EndOfHeader") + 16 + 2
first_time = True
BinWriter = New BinaryWriter(writeStream)
For i = 0 To Form1.signals.Length - 1
If IsNothing(Form1.signals(i)) = False Then
'once for each test
BinWriter.Write(Int(Form1.signals(i).picodata.GetLength(0) - 1)) 'n for each signal in test
BinWriter.Write(Form1.signals(i).picodata(1, 0) - Form1.signals(i).picodata(0, 0)) 'timestep
BinWriter.Write(next_byte) 'position of start of test
BinWriter.Write(CStr(time))
Exit For
End If
Next
BinWriter.Write("EndOfHeader")
For i = 0 To Form1.signals.Length - 1
If IsNothing(Form1.signals(i)) = False Then
BinWriter.Write(i)
For j = 1 To Form1.signals(i).picodata.GetLength(0) - 1
BinWriter.Write(Form1.signals(i).picodata(j, 1))
Next
End If
Next
BinWriter.Close()
To read in:
Dim readstream As FileStream
Dim end_test As Integer
Dim Index As Integer
Dim BinReader As BinaryReader
Dim end_head as Boolean=false
Dim count as integer=0
selected_test=0
ReadStream = New FileStream(readFileName, FileMode.Open)
BinReader = New BinaryReader(ReadStream)
'read header
While end_head = False
Try
pos_old = ReadStream.Position
try_string = BinReader.ReadString
If try_string = "EndOfHeader" Then
Exit While
Else
ReadStream.Position = pos_old
End If
Catch ex As Exception
ReadStream.Position = pos_old
End Try
'this approach allows for flexibility
number_arr(count) = BinReader.ReadInt32
TimeStep_arr(count) = BinReader.ReadDouble
position_arr(count) = BinReader.ReadInt32
time_arr(count) = CDate(BinReader.ReadString)
count += 1
End While
'read in data
While readstream.Position <> read_stream.length
ReDim PicoData(number_arr(selected_test), 1)
Index = BinReader.ReadInt32
n = number_arr(selected_test)
For i = 1 To n
PicoData(i, 1) = BinReader.ReadDouble
PicoData(i, 0) = TimeStep_arr(selected_test) * i
Next
ReDim TimeShort(Int(n / 20))
ReDim FiltVoltsShort(Int(n / 20))
ReDim FiltVelShort(Int(n / 20))
ReDim RawVoltsShort(Int(n / 20))
'generate new reading here
Call FourierFilter(PicoData, 0)
signals(Index) = New reading(Index, TimeShort, RawVoltsShort, FiltVelShort, FiltVoltsShort, Points_Store(ii, 2), Points_Store(ii, 1), DataChart, VelocityChart, SelectedTimeBox, SelectedVelocityBox, True, PicoData)
End While
BinReader.Close()
readstream.Close()
The date occasionally is not read in correctly. I will get some character + the date I want. Parts of my code have been cut out (since the program is pretty huge) but hopefully what I have sent will make some sense. Thanks
Your first step should be to find a simple-as-possible reproducible test case where you can make it fail every time. Then it will be much easier to identify the source of the problem.
Code like this might help you narrow down how BinaryWriter encodes strings on different platforms.
Dim content As String = New String("!"c, 255)
Using outStream As New System.IO.MemoryStream()
Using bw As New System.IO.BinaryWriter(outStream)
bw.Write(content)
bw.Flush()
outStream.Flush()
Console.WriteLine("I am a " & If(Environment.Is64BitProcess, "64", "32") & _
"-bit process")
Console.WriteLine("I generated a string of {0} characters into a stream " & _
"of {1} bytes", content.Length, outStream.Length)
End Using
End Using