Hey all,
First, a little foreword: My boss had some .cmd scripts that he used to install various programs on our network, and since I had free time, I was asked to consolidate these scripts into one overarching project. I chose to start fiddling with vb.net because I have never really programmed before, and we already had visual studio installed. I trust that if you looked at my code you would be shocked at my bad practices. But for now, my crappy, almost nonexistent programming skills have paid the bills.
So basically, this lumbering beast of a program monitors the progress of software installation. For the most part, it works fine.
In the future I would like to get into multi-threading, but I am hesitant due to my lack of experience. I managed to set up a background worker, and it works beautifully, allowing me to have a responsive program, a progress bar and a status bar. Before I get into multi-threading I need to fix my one major issue.
My code spawns an invisible command prompt and then uses that command prompt to start another program called rex with the installation parameters. Rex then does the heavy lifting regarding the installation, and then tells the command prompt we spawned if the installation was successful or not.
I read the feedback, and then log the details. So this generally takes a minute or two, but it occasionally takes over twelve hours.
Also, I would love and appreciate any unrelated advice about my code.
First, a little foreword: My boss had some .cmd scripts that he used to install various programs on our network, and since I had free time, I was asked to consolidate these scripts into one overarching project. I chose to start fiddling with vb.net because I have never really programmed before, and we already had visual studio installed. I trust that if you looked at my code you would be shocked at my bad practices. But for now, my crappy, almost nonexistent programming skills have paid the bills.
So basically, this lumbering beast of a program monitors the progress of software installation. For the most part, it works fine.
In the future I would like to get into multi-threading, but I am hesitant due to my lack of experience. I managed to set up a background worker, and it works beautifully, allowing me to have a responsive program, a progress bar and a status bar. Before I get into multi-threading I need to fix my one major issue.
My code spawns an invisible command prompt and then uses that command prompt to start another program called rex with the installation parameters. Rex then does the heavy lifting regarding the installation, and then tells the command prompt we spawned if the installation was successful or not.
I read the feedback, and then log the details. So this generally takes a minute or two, but it occasionally takes over twelve hours.
Here's My Question + Stuff I've Tried:
I will be linking my code at the bottom of this post, in that code you will see line = installSR.readline. I was hoping someone could help me figure out how to make a timeout work. I have tried a bunch of different methods to function as a timeout, but the issue is that my code locks up on that one line until the command prompt responds with information from Rex.
- I tried measuring time before and after the readline, but that didn't work because when the timeouts happen the code literally hangs on that one line and never progresses to the timeout checking code.
- I tried checking to see if the command prompt has exited before I let it start reading lines. And though that seemed promising, and even works in other parts of my code, it didn't work here. (And I don't know why it didn't work.) It just says that the command prompt has been closed, and then the readline hangs anyway. I really don't know why, if anyone could shed some light on that I would appreciate it.
- I also tried putting all of this code in a separate worker, and the timeout would count down correctly. However, even when I sent the .abort command or .dispose commands (for the streamreader, writer, and command prompt process) I could tell that the processes weren't actually responding with their abort catch information. And then eventually the program would crash. I assume this is because I had too many open threads? Maybe I need to look into that more? It seems like maybe the only possible way to make this work is to get this solution working.
Also, I would love and appreciate any unrelated advice about my code.
VB.NET:
For Index = 1 To installArray.GetUpperBound(0)
Try
If installArray(Index) <> "" Then
'Here we dim a Command Prompt that we will be using to enter batch commands *SW = streamwriter* *SR = streamreader*
Dim CMD As New Process
Dim installSW As System.IO.StreamWriter
Dim installSR As System.IO.StreamReader
installCMD.StartInfo.FileName = "cmd"
installCMD.StartInfo.UseShellExecute = False
installCMD.StartInfo.Domain = configNetwork
installCMD.StartInfo.UserName = halfUsername
installCMD.StartInfo.Password = password
installCMD.StartInfo.RedirectStandardInput = True
installCMD.StartInfo.RedirectStandardOutput = True
installCMD.StartInfo.CreateNoWindow = True
installCMD.Start()
installSW = installCMD.StandardInput
installSR = installCMD.StandardOutput
fixCount = 0
'These bw.CancellationPending chunks just exist to check if the cancel button has been pushed.
If bw.CancellationPending = True Then
e.Cancel = True
SetControlEnabled(prRunButton, True)
SetControlEnabled(prResetButton, True)
Thread.Sleep(25)
'PerformClick(prResetButton)
Call Reset_Tab_1(Me, e)
Return
Else
End If
Thread.Sleep(1000)
installSW.WriteLine("start /B C:\Windows\rex.exe \\" & installArray(Index) & " -u " & username & " -p " & insecurePassword & " -b -c " & installFileLocation)
installSW.WriteLine("exit")
logString = logNum & ": Sending install command to: " & installArray(Index) & "..." & vbCrLf
SetControlTxt(logTB, logString)
LogScroll(logTB)
logNum += 1
Do
'\\ This loop generally takes a minute. But occasionally it takes 14+ hours.
'\\ During these 14+ hours, the code is just hanging on the installSR.ReadLine.
[COLOR=#ff8c00][SIZE=3] [B][U] line = installSR.ReadLine[/U][/B][/SIZE][/COLOR]
Loop Until line.Contains("code") Or line.Contains("specified network") Or line.Contains("executable") Or line.Contains("Error 5") Or line.Contains("Error 53")
If line.Contains("Error 53") Then
debugLine = (logNum & ": " & "The network path was not found. " & vbCrLf)
SetControlTxt(logTB, debugLine)
LogScroll(logTB)
logNum += 1
debugLine = " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" & vbCrLf
SetControlTxt(logTB, debugLine)
LogScroll(logTB)
Thread.Sleep(15)
GoTo installSkip
ElseIf line.Contains("Error 5") Then
debugLine = (logNum & ": " & "Access was denied. " & vbCrLf)
SetControlTxt(logTB, debugLine)
LogScroll(logTB)
logNum += 1
debugLine = " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" & vbCrLf
SetControlTxt(logTB, debugLine)
LogScroll(logTB)
Thread.Sleep(15)
GoTo installSkip
ElseIf line.Contains("executable") Then
debugLine = (logNum & ": " & "Rex responded with syntax information. Please ensure that your password does not end with special characters such as & before trying again. " & vbCrLf)
SetControlTxt(logTB, debugLine)
LogScroll(logTB)
logNum += 1
debugLine = " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" & vbCrLf
SetControlTxt(logTB, debugLine)
LogScroll(logTB)
Thread.Sleep(15)
GoTo installSkip
End If
logString = logNum & ": " & line & vbCrLf
SetControlTxt(logTB, logString)
LogScroll(logTB)
logNum += 1
Thread.Sleep(15)
debugLine = " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" & vbCrLf
SetControlTxt(logTB, debugLine)
LogScroll(logTB)
Thread.Sleep(15)
installMsgArray(Index) = line
installskip:
If fixCount >= 180 Then
logString = logNum & ": The Install command timed out. (180 seconds)" & vbCrLf
SetControlTxt(logTB, logString)
LogScroll(logTB)
logNum += 1
Thread.Sleep(15)
debugLine = " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" & vbCrLf
SetControlTxt(logTB, debugLine)
LogScroll(logTB)
Thread.Sleep(15)
installArray(Index) = ""
installMsgArray(Index) = ""
installTimeoutCounter += 1
installTimeoutArray(Index) = installArray(Index)
End If
installCMD.Dispose()
installSW.Dispose()
installSR.Dispose()
End If
Catch ee As Exception
debugLine = (logNum & ": " & "Mistakes were made.... (some non-descriptive error occured) [during install index number " & Index & "]" & vbCrLf)
SetControlTxt(logTB, debugLine)
LogScroll(logTB)
logNum += 1
debugLine = (logNum & ": " & ee.ToString & vbCrLf)
SetControlTxt(logTB, debugLine)
LogScroll(logTB)
logNum += 1
Thread.Sleep(15)
debugLine = " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" & vbCrLf
SetControlTxt(logTB, debugLine)
LogScroll(logTB)
Thread.Sleep(15)
End Try
If Sum < 100 Then
Sum += ProgressBarCounter
Percent = (FormatNumber(Sum) & "%")
bw.ReportProgress(Sum)
Else
Percent = "100%"
bw.ReportProgress(100)
End If
'This is just updating the percentage & status bar
Next