List that this enumerator is bound to has been modified - vb.net

I have this bit of code here, and at the next statement it's giving me an error saying:
List that this enumerator is bound to has been modified. An enumerator can only be used if the list does not change.
I really don't know how to further explain this issue, but if you need me to I can try.
For Each itemChecked In storedAuthorsListbox.CheckedItems
Dim selectedAuthor As String = storedAuthorsListbox.SelectedItem.ToString()
Dim authorFile As String = "Authors\" & itemChecked.ToString()
Dim document As XmlReader = New XmlTextReader(authorFile)
metaInfo &= "[Author]" & vbNewLine
While (document.Read())
Dim type = document.NodeType
If (type = XmlNodeType.Element) Then
If (document.Name = "Name") Then
metaInfo &= "Name=" & document.ReadInnerXml.ToString() & vbNewLine
ElseIf (document.Name = "Website") Then
metaInfo &= "Website=" & document.ReadInnerXml.ToString() & vbNewLine
ElseIf (document.Name = "Notes") Then
metaInfo &= "Notes=" & document.ReadInnerXml.ToString() & vbNewLine
End If
End If
End While
document.Close()
Next

Some code somewhere is changing storedAuthorsListbox while you are iterating it. That code is not visible in the snippet. Do make sure that the posted code is not running in a worker thread, that is not legal. It certainly quacks like the kind of code you'd run in a worker.
The generic solution is to make a copy of the items and work from that copy instead of the control:
Dim copy = storedAuthorsListBox.SelectedItems.OfType(Of String)().ToList()
For Each itemchecked In copy
'' etc..
Next
If this runs in a worker thread then pass the copy to the worker.

Related

Read message from text file and display in message box in vb.net

JavaError.128 = "project creation failed. & vbLf & Please try again and if the problem persists then contact the administrator"
I am able to read this message from text file. the issue is vbLf is not considered as newline in msgbox. it prints vbLf in msgbox.
Using sr As System.IO.StreamReader = My.Computer.FileSystem.OpenTextFileReader(errorfilePath)
While ((sr.Peek() <> -1))
line = sr.ReadLine
If line.Trim().StartsWith("JavaError." & output) Then
isValueFound = True
Exit While
End If
End While
sr.Close()
End Using
If isValueFound Then
Dim strArray As String() = line.Split("="c)
MsgBox(strArray(1).Replace("""", "").Trim({" "c}))
End If
You can make all your code a simpler one line version using File.ReadAllLines and LINQ. This code will put all the lines starting with javaerror into the textbox, not just the first:
textBox.Lines = File.ReadAllLines(errorFilePath) _
.Where(Function(s) s.Trim().StartsWith("JavaError")) _
.Select(Function(t) t.Substring(t.IndexOf("= ") + 2).Replace(" & vbLf & ", Environment.NewLine)) _
.ToArray()
You need to Imports System.IO and System.Linq
This code reads all the lines of the file into an array, then uses LINQ to pull out only those starting with java error, then projects a new string of everything after the = with vbLf replaced with a newline, converts the enumerable projection to an array of strings and assigns it to the textBox lines
If you don't want all the lines but instead only the first:
textBox.Text = File.ReadLines(errorFilePath) _
.FirstOrDefault(Function(s) s.Trim().StartsWith("JavaError")) _
?.Substring(t.IndexOf("= ") + 2).Replace(" & vbLf & ", Environment.NewLine))
This one uses ReadLine instead of ReadALlLines - ReadLines works progressively, and it makes sense to be able to stop reading after we foundt he first rather than have the overhead of reading ALL (million) lines only to then end up pulling the first out and throwing 999,999 lines of effort away. So it's reading line by line, pulls out the first that starts with "JavaError" (or Nothing if there is no such line), then checks if Nothing came out (the ?) and skips the Substring if it was Nothing, or it does a Substring on everything after the = and replaces vbLf with newline
For a straight up mod of your original code:
Using sr As System.IO.StreamReader = My.Computer.FileSystem.OpenTextFileReader(errorfilePath)
While ((sr.Peek() <> -1))
line = sr.ReadLine
If line.Trim().StartsWith("JavaError." & output) Then
isValueFound = True
line = line.Replace(" & vbLf & ", Environment.NewLine))
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ added code
Exit While
End If
End While
sr.Close()
End Using
If isValueFound Then
Dim strArray As String() = line.Split("="c)
MsgBox(strArray(1).Replace("""", "").Trim({" "c}))
End If
Note that I've always made my replacement on & vbLf & with a space at each end to avoid stray spaces being left behind - if your file sometimes doesn't have them, consider using Regex to do the replace, e.g. Regex.Replace(line, " ?& vbLf & ?", Environment.NewLine
This could work:
Dim txtFile As String = "project creation failed. & vbLf & Please try again and if the problem persists then contact the administrator"
Dim arraytext() As String = txtFile.Split("&")
Dim txtMsgBox As String = Nothing
For Each row As String In arraytext
If Trim(row) = "vbLf" Then
txtMsgBox = txtMsgBox & vbLf
Else
txtMsgBox = txtMsgBox & Trim(row)
End If
Next
MsgBox(txtMsgBox)

vb.net WPF application combobox not waiting for user to choose

I have a wpf vb.net application (written in VS 2019 community) containing two website searches. The first search is a string search and that either produces one result, which I then load into the second search, or it produces more than one result, which I load into a combobox to let the user choose. My problem is getting the application to stop and allow the user to choose from the combobox. I have implemented a workaround that uses a modal form containing a combobox and this allows the user to choose from the combobox and supply the value to the second search. I have been advised to use the 'change' event for the combobox but there isn't one available, I have also been advised to use the selectedindexchanged but the control doesn't let the dropdown list occur to select anything. I have also tried using various forms of addhandler (commented out in the code below).
' Build the 'Search API' URL.
Dim uri = New Uri("https://api.themoviedb.org/3/search/tv?" _
& "api_key=" & TMDBAPIKey _
& "&language=en-US" _
& "&query=" & sLvl1NodeName _
& "&page=1" _
& "&first_air_date_year=" & sFirstXmitYear)
' Retrieve the IMDB ID with an API Search function using the series title
Try
Dim Site = New WebClient()
Answer = Site.DownloadString(uri)
Catch ex As NullReferenceException
Dim messagetext As String = "The 'Search API' from GetDetails popup failed with : " _
& ex.Message & " for: Title=" & sLvl1NodeName
Me.txtErrorMessageBox.Text = messagetext
Exit Sub
End Try
' Deserialise the answer
Dim JsonElem As TMDBtitle = JsonConvert.DeserializeObject(Of TMDBtitle)(Answer)
' If the websearch finds only one result this is the TV series we want, if more than
' one result is found load the results into a combobox and get the user to choose.
If JsonElem.results.Length = 1 Then
TVSeriesID = JsonElem.results(0).id
Else
Me.cmbChooseSeries.BeginUpdate()
Me.lblChooseSeries.Text = Me.lblChooseSeries.Text & "( " & JsonElem.results.Length & " )"
Me.cmbChooseSeries.Items.Clear()
For Each titleresult In JsonElem.results
ComboSeriesChoice = titleresult.name & " | " &
titleresult.id & " | " &
titleresult.first_air_date & " | " &
titleresult.overview
Me.cmbChooseSeries.Items.Add(ComboSeriesChoice)
Next
cmbChooseSeries.DroppedDown = True
Me.cmbChooseSeries.EndUpdate()
If cmbChooseSeries.SelectedIndex <> -1 Then
Dim var1 = cmbChooseSeries.SelectedText
Else
Threading.Thread.Sleep(3000)
End If
'AddHandler cmbChooseSeries.MouseDoubleClick,
'Sub()
'Threading.Thread.Sleep(3000)
'End Sub
TVSeriesID = cmbChooseSeries.SelectedItem
End If
' Build the 'TV Search API' call URL.
Dim urix = New Uri("https://api.themoviedb.org/3/tv/" _
& TVSeriesID & "?" _
& "api_key=" & TMDBAPIKey _
& "&language=en-US")
Try
Dim site = New WebClient()
Answer = site.DownloadString(urix) ' download the JSON from the server.
Catch ex As NullReferenceException
Dim MessageText As String = "The 'TV Search API' from GetDetails popup failed with : " _
& ex.Message & " for: Title=" & sLvl1NodeName & " ID=" & popupid
Me.txtErrorMessageBox.Text = MessageText
Exit Sub
End Try
Dim jsonelemx = JsonConvert.DeserializeObject(Of TVResult)(Answer)
lstDetailItems(0) = "Name"
lstDetailItems(1) = jsonelemx.name
lstDetailItems(2) = (String.Empty)
Dim DelItems = New ListViewItem(lstDetailItems)
Me.lstSeriesDetails.Items.Add(DelItems)
lstDetailItems(0) = "Status"
lstDetailItems(1) = jsonelemx.status
lstDetailItems(2) = (String.Empty)
DelItems = New ListViewItem(lstDetailItems)
Me.lstSeriesDetails.Items.Add(DelItems)
lstDetailItems(0) = "Episode run time"
lstDetailItems(1) = Convert.ToString(jsonelemx.episode_run_time(0))
lstDetailItems(2) = (String.Empty)
DelItems = New ListViewItem(lstDetailItems)
Me.lstSeriesDetails.Items.Add(DelItems)

Getting BC31019 excepetion while compiling vb.net at runtime on Windows 10

we are generating a mass of documents very dynamically. Therefore we concatenate source code and build a dll at runtime. This is running since windows XP.
Now we are in tests of windows 10 and it fails compiling this dll with the error "BC31019: Unable to write to output file 'C:\Users[name]AppData\Local\Temp\xyz.dll': The specified image file did not contain a resource section"
For testing purposes we remove all generated source code and replace it by a rudimental class with only one function (throwing an exception with specified text) and no referenced assemblies.
This is also running on all machines except windows 10. Same error.
Can anybody guess why?
This is the rudimental method
Public Sub Compile()
Dim lSourceCode = "Namespace DynamicOutput" & vbCrLf &
" Public Class Template" & vbCrLf &
" Sub New()" & vbCrLf &
" End Sub" & vbCrLf &
" Public Sub Generate(ByVal spoolJob As Object, ByVal print As Object)" & vbCrLf &
" Throw New System.Exception(""Generate reached"")" & vbCrLf &
" End Sub" & vbCrLf &
"" & vbCrLf &
" End Class" & vbCrLf &
"End Namespace"
Dim lParams As CodeDom.Compiler.CompilerParameters = New CodeDom.Compiler.CompilerParameters
lParams.CompilerOptions = "/target:library /rootnamespace:CompanyName /d:TRACE=TRUE /optimize "
lParams.IncludeDebugInformation = True
lParams.GenerateExecutable = False
lParams.TreatWarningsAsErrors = False
lParams.GenerateInMemory = True
Dim lProviderOptions As New Dictionary(Of String, String) From {{"CompilerVersion", "v4.0"}}
Dim lResult As CodeDom.Compiler.CompilerResults = Nothing
Using provider As New VBCodeProvider(lProviderOptions)
lResult = provider.CompileAssemblyFromSource(lParams, lSourceCode)
End Using
' ... check for errors
Dim lInstance As Object = lResult.CompiledAssembly.CreateInstance("CompanyName.DynamicOutput.Template")
lInstance.GetType.GetMethod("Generate").Invoke(lInstance, New Object() {Me.SpoolJob, Me.Print})
End Sub

File not getting created - Visual Basic

I'm making a skype tool, and I'm creating the config file automatically, or at least that's what I think I am doing. The problem is just that for some reason the FileNotFoundException is fired because of some of my code is refering to the file which doesn't exist yet. So is visual basic checking for exceptions before firing code, or am I doing something wrong?
Here's my file creation code:
If My.Computer.FileSystem.DirectoryExists("C:\BaconSkypeTool") Then
Else
My.Computer.FileSystem.CreateDirectory("C:\BaconSkypeTool")
End If
If My.Computer.FileSystem.FileExists(Path) Then
Else
Dim fs As FileStream = File.Create(Path)
Dim line1 As Byte() = New UTF8Encoding(True).GetBytes("This is the configuration file for BaconSkypeTool" & vbCrLf & "Please do not change anything in here if you don't know what you're doing." & vbCrLf & vbCrLf & "Values below" & vbCrLf & "ChangeStatusInCall = True" & vbCrLf & "Status = Online" & vbCrLf & "Enable .cancel command = True")
fs.Write(line1, 0, line1.Length)
fs.Close()
End If
And here's the code that fires the exception:
skype.CurrentUserStatus = SKYPE4COMLib.TOnlineStatus.olsOnline
Dim text = My.Computer.FileSystem.ReadAllText("C:\BaconSkypeTool\config.cfg")
Dim textAfterStatus As String = Nothing
Dim indexOfStatus = text.IndexOf("Status = ")
Dim text1 As String = Nothing
If indexOfStatus >= 0 Then
textAfterStatus = text.Substring(indexOfStatus + "Status = ".Length)
text1 = textAfterStatus.Split("Blacklist").First().Trim()
End If
The file creation is at the top of my file and therefore should be the first thing to be fired, but maybe that's just something I think.

Trying to create a function

So I'm trying to change this sub in to a function so that I can reference it and set a label.text as it's result, this is so I don't have to creating new subs to update different labels.
Dim drive As String = "C"
Dim disk As ManagementObject = _
New ManagementObject _
("win32_logicaldisk.deviceid=""" + drive + ":""")
disk.Get()
Dim serial As String = disk("VolumeSerialNumber").ToString()
Label1.Text = ("Serial: " & serial)
Can someone tell me how I can change this in to a function? I've tried declaring Serial as an empty String and then changing the last line to read:
Return serial = disk("VolumeSerialNumber").ToString()
At the moment this just sets Label1.Text to display "False", like I've set it as a Boolean or something?!
I'm learning functions at the moment, I'm trying to make things cleaner as up until now I've just been creating different subs to update labels etc...
I'm looking for some tips so I can try and get this myself.
It is really a simple refactoring operation.
Sub Main
Dim driveLetter = "X"
Try
Dim result = DriveSerialNumber(driveLetter)
Console.WriteLine(result)
Catch ex as Exception
Console.WriteLine("Error: drive " & driveLetter & ": " & ex.Message)
End Try
End Sub
Public Function DriveSerialNumber(drive as String) As String
Dim disk As ManagementObject = _
New ManagementObject _
("win32_logicaldisk.deviceid=""" + drive + ":""")
disk.Get()
return disk("VolumeSerialNumber").ToString()
End Function
However, be prepared to receive Exceptions if you pass an invalid drive letter