Why is the file being overwritten? - vb.net

I'm designing a new server application, which includes a subroutine that parses the input into the console window, for example
LogAlways("--- CPU detection ---")
will be written as:
[net 21:8:38.939] --- CPU detection ---
This is the subroutine:
Public Sub LogAlways(ByVal input As String)
Dim dm As String = "[net " + Date.Now.Hour.ToString + ":" + Date.Now.Minute.ToString + ":" + Date.Now.Second.ToString + "." + Date.Now.Millisecond.ToString + "] "
Console.WriteLine(dm + input)
Dim fName As String = Application.StartupPath() + "\LogBackups\" + Date.Now.Day.ToString + Date.Now.Month.ToString + "" + Date.Now.Year.ToString + ".log"
Dim stWt As New Global.System.IO.StreamWriter(fName)
stWt.Write(dm + input)
stWt.Close()
End Sub
This works, but however only the last line of my desired input is written to the file.
Why is this happening, and how can I make it so that it does not overwrite the log file?
This is using the Wildfire Server API.
This is not a duplicate, as the destination question has a different answer which would otherwise not answer this question.

This occurs as the StreamWriter has not been told to append the output to the end of the file with the parameter set to True, Visual Studio actually gives it as a version of the StreamWriter:
To correctly declare it:
Dim stWt As New Global.System.IO.StreamWriter(fName, True)
or in the subroutine:
Public Sub LogAlways(ByVal input As String)
Dim dm As String = "[net " + Date.Now.Hour.ToString + ":" + Date.Now.Minute.ToString + ":" + Date.Now.Second.ToString + "." + Date.Now.Millisecond.ToString + "] "
Console.WriteLine(dm + input)
Dim fName As String = Application.StartupPath() + "\LogBackups\" + Date.Now.Day.ToString + Date.Now.Month.ToString + "" + Date.Now.Year.ToString + ".log"
Dim stWt As New Global.System.IO.StreamWriter(fName, True)
stWt.Write(dm + input)
stWt.Close()
End Sub
Requires the following to be Imports:
System.IO
System.Windows.Forms
It will now correctly write to the end of the file, but however it is noted that stWt.Close()'ing the file on every call may cause issues, therefore a queuing system may be better:
Desired log output is inserted into a single-dimensional array
A Timer dumps this array to the log file on every, say, five to ten seconds
When this is done, the array is cleared

Related

Overflow.Exception crashing my program

I know this is how it's supposed to be done however, in VB.NET it gives me an overflow exception crashing my program. If there is any "VB.NET equivalent" of doing this, help is much appreciated.
Dim hActiveWeapon = _mem.rdInt(GetLocalBase() + &H2EE8)
Dim wepEntity = _mem.rdInt(_client + Offsets.EntityList + ((hActiveWeapon & &HFFF) - 1) * &H10) ' Crashes here # hActiveWeapon & &HFFF
Dim wepIndex = _mem.rdInt(wepEntity + Offsets.iItemDefinitionIndex)
I am doing this to get the lower 12 bytes of m_hActiveWeapon (0xFFF = 0b111111111111 = 4095), so I can get the index of the active weapon.
Meh the answer was simple, changing "&" to "And" fixed it.

FileInfo returning wrong value?

Okay, so I'm working in VB.NET, manually writing error logs to log files (yes, I know, I didn't make the call). Now, if the files are over an arbitrary size, when the function goes to write out the new error data, it should start a new file with a new file name.
Here's the function:
Dim listener As New Logging.FileLogTraceListener
listener.CustomLocation = System.Configuration.ConfigurationManager.AppSettings("LogDir")
Dim loc As String = DateTime.UtcNow.Year.ToString + DateTime.UtcNow.Month.ToString + DateTime.UtcNow.Day.ToString + DateTime.UtcNow.Hour.ToString + DateTime.UtcNow.Minute.ToString
listener.BaseFileName = loc
Dim logFolder As String
Dim source As String
logFolder = ConfigurationManager.AppSettings("LogDir")
If ex.Data.Item("Source") Is Nothing Then
source = ex.Source
Else
source = ex.Data.Item("Source").ToString
End If
Dim errorFileInfo As New FileInfo(listener.FullLogFileName)
Dim errorLengthInBytes As Long = errorFileInfo.Length
If (errorLengthInBytes > CType(System.Configuration.ConfigurationManager.AppSettings("maxFileSizeInBytes"), Long)) Then
listener.BaseFileName = listener.BaseFileName + "1"
End If
Dim msg As New System.Text.StringBuilder
If String.IsNullOrEmpty(logFolder) Then logFolder = ConfigurationManager.AppSettings("LogDir")
msg.Append(vbCrLf & "Exception" & vbCrLf)
msg.Append(vbTab & String.Concat("App: AppMonitor | Time: ", Date.Now.ToString) & vbCrLf)
msg.Append(vbTab & String.Concat("Source: ", source, " | Message: ", ex.Message) & vbCrLf)
msg.Append(vbTab & "Stack: " & ex.StackTrace & vbCrLf)
listener.Write(msg.ToString())
listener.Flush()
listener.Close()
I have this executing in a loop for testing purposes, so I can see what happens when it gets (say) 10000 errors in all at once. Again, I know there are better ways to handle this systemically, but this was the code I was told to implement.
How can I reliably get the size of the log file before writing to it, as I try to do above?
Well, as with many things, the answer to this turned out to be "did you read your own code closely" with a side order of "eat something, you need to fix your blood sugar."
On review, I saw that I was always checking BaseFileName and, if it was over the arbitrary limit, appending a character and writing to that file. What I didn't do was check to see if that file or, indeed, other more recent files existed. I've solved the issue be grabbing a directory list of all the files matching the "BaseFileName*" argument in Directory.GetFiles and selecting the most recently accessed one. That ensures that the logger will always select the more current file to write to or -if necessary- use as the base-name for another appended character.
Here's that code:
Dim directoryFiles() As String = Directory.GetFiles(listener.Location.ToString(), listener.BaseFileName + "*")
Dim targetFile As String = directoryFiles(0)
For j As Integer = 1 To directoryFiles.Count - 1 Step 1
Dim targetFileInfo As New FileInfo(targetFile)
Dim compareInfo As New FileInfo(directoryFiles(j))
If (targetFileInfo.LastAccessTimeUtc < compareInfo.LastAccessTimeUtc) Then
targetFile = directoryFiles(j)
End If
Next
Dim errorFileInfo As New FileInfo(listener.Location.ToString() + targetFile)
Dim errorLengthInBytes As Long = errorFileInfo.Length

VBA Excel Dynamically Display Added Results

So I am modeling my question with a simple Grocery List applications.
Program GUI:
Now what I want is for the Customer to enter: Eggs, Milk, and Bread and for that to enter and output to a .txt file.
Current Code:
Private Sub CreateList_Click()
Dim myFile As String, myString As String
myFile = "C:\Reformatted.txt"
Open myFile For Output As #1
myString = First.Value + Second.Value + Third.Value + Fourth.Value + Fifth.Value
Print #1, myString
Close #1
Shell "C:\Windows\Notepad.exe C:\Reformatted.txt", 1
End Sub
Desired Operation:
What I want to happen is that ther enter there first 5 items. Then it prompts them if they want another 5. If they do then they can add another line.
So I understand that I can add a MsgBox in VB and just design a while loop for that. My question is how to display the results of their first/previous submissions?
Desired Result:
I understand that VB stores the values as variables, but how can I show them to the user while they still have a chance to enter more entries. Also how to add all this with the preferred formatting to a notepad file?
----------------------------After Miss Palmer's Answer--------------------------
Private Sub AddEntry_Click()
Dim UserEntry As String
UserEntry = First.Value + DDPP.Value + Filer.Value + EntryNumber.Value
myString = myString & Chr(13) & UserEntry
GroceryList.UserDisplay.Caption = "You have entered:" & myString
End Sub
Scenario 1 - First Addition
Scenario 2 - Second Addition
The two additions should be placed one after the other. But currently it just replaces it.
You can update a label on the form on each iteration of your while loop using something of the form:
FormName.LabelName.Caption = "you have entered:" & myString
and then add to the string each loop with
myString = myString & First.Value + Second.Value + Third.Value + Fourth.Value + Fifth.Value
EDIT
myString = myString & chr(13) & First.Value + Second.Value + Third.Value + Fourth.Value + Fifth.Value

Running Multiple Processes

The following code I'm about to posts works fine, however I need to be able to kick off multiple processes at the same time.
So to give some background, the listbox contains files that will be run through another process to create PDF files (essentially passing arguments to the other process which is the exe listed in the StartInfo.Filename). What's currently happening, say the listbox contains 10 files. Each file will be processed separately before the additional files are processed. I'd like to be able to kick off all 10 files at the same time instead of waiting. Some files may take longer than others, so I'm wasting time waiting for each file to finish.
Suggestions?
Dim UPSFiles = (From i In ListBoxUPSFiles.Items).ToArray()
For Each Item In UPSFiles
Dim UPSFiles2 = Item.ToString
Using psinfo As New Process
psinfo.StartInfo.FileName = "\\dgrvdp1\ClientServices\APPS\Printtrack\HeliosPNetExecuter\HeliosPNetExecuter.exe "
psinfo.StartInfo.Arguments = Arg2 + Arg3 + Arg4 + (Chr(34) + DATA_PATH + "\" + UPSFiles2 + Chr(34) + " ") + Arg6 + Arg7 + Arg8 + Arg9a + Arg10 + Arg11 + Arg13
psinfo.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
psinfo.Start()
'psinfo.WaitForExit()
End Using
Next
EDIT
Here's my current code, based on the Parallel.ForEach suggestion. It appears to sort of worked but submitted 10x the number of files I need to run. In my case, I have two files to process however like I mention the code produced 10x the number of processes I truly need.
Dim SequentialFiles = (From i In ListBoxSequentialFiles.Items).ToString
For Each Item In SequentialFiles
Dim SequentialFiles2 = Item.ToString
Parallel.ForEach(SequentialFiles2, Sub(processFiles)
Using psinfo As New Process
psinfo.StartInfo.FileName = "\\dgrvdp1\ClientServices\APPS\Printtrack\HeliosPNetExecuter\HeliosPNetExecuter.exe "
psinfo.StartInfo.Arguments = Arg2 + Arg3 + Arg4 + (Chr(34) + DATA_PATH + "\" + SequentialFiles2 + Chr(34) + " ") + Arg6 + Arg7 + Arg8 + Arg9c + Arg10 + Arg11 + Arg12
psinfo.StartInfo.WindowStyle = ProcessWindowStyle.Normal
psinfo.Start()
psinfo.WaitForExit()
End Using
End Sub)
Next
Depends how is PDF processor work. You can avoid creting threads, but simply launch 10 processes, by feeding inside one file per process. No need of multi threading, at this stage at least.

VB.Net Substring Error

At the moment, I have three different times that the following code is ran, back-to-back just with the variables changed:
txtCourseName.LoadFile(strRootLocation + "\subject\" + strSubject + "\" + "\class\" + cmbCourses.SelectedItem, RichTextBoxStreamType.PlainText)
aData = txtCourseName.Text
i = aData.IndexOf("<h3 class=""panel-title"">") + "<h3 class=""panel-title"">".Length
j = aData.IndexOf("</h3>") - i
txtCourseName.Text = aData.Substring(i, j)
For every time it is ran, the rich-text box that is being used is changed, aData is changed to bData, cData, etc., and the data that i and j are indexing is changed. It will run properly for the first two iterations, returning what it is supposed to into the text box, however on the third one, it gives me a System.ArgumentOutOfRangeException with the additional information of Length cannot be less than zero.
My only assumption for what could be causing this is that the third iteration, which I included below, is only supposed to find a 7-letter long string of characters and this is causing some math issues.
I have no idea how to fix this.
txtCourseNumber.LoadFile(strRootLocation + "\subject\" + strSubject + "\" + "\class\" + cmbCourses.SelectedItem, RichTextBoxStreamType.PlainText)
cData = txtCourseNumber.Text
i = cData.IndexOf("Course Number: </b>") + "Course Number: </b>".Length
j = cData.IndexOf("</li>") - i
txtCourseNumber.Text = cData.Substring(i, j)
Example Data That Is Returned By Each Iteration
aData - "English 4"
bData - "insert some really long course description here"
cData - "10045C"