2

I'm trying to read battery information from cmd. How can I extract each value and put them in their respective textbox, as shown in the image below?

User Interface

Here's my code:

Private Results As String
Private Delegate Sub delUpdate()
Private Finished As New delUpdate(AddressOf UpdateText)

Private Sub UpdateText()
    TextBox11.Text = Results
End Sub

Private Sub batt_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim CMDThread As New Threading.Thread(AddressOf CMDAutomate)
    CMDThread.Start()
End Sub

Private Sub CMDAutomate()
    Dim myprocess As New Process
    Dim StartInfo As New System.Diagnostics.ProcessStartInfo
    StartInfo.FileName = "cmd" 'starts cmd window
    StartInfo.RedirectStandardInput = True
    StartInfo.RedirectStandardOutput = True
    StartInfo.UseShellExecute = False 'required to redirect
    StartInfo.CreateNoWindow = False 'creates no cmd window
    myprocess.StartInfo = StartInfo
    myprocess.Start()
    Dim SR As System.IO.StreamReader = myprocess.StandardOutput
    Dim SW As System.IO.StreamWriter = myprocess.StandardInput
    SW.WriteLine("adb shell dumpsys battery") 'the command you wish to run.....
    SW.WriteLine("exit") 'exits command prompt window
    Results = SR.ReadToEnd 'returns results of the command window
    SW.Close()
    SR.Close()
    'invokes Finished delegate, which updates textbox with the results text
    Invoke(Finished)
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim value As String = TextBox11.Text
    Dim topic_start As String = topic_start = value.LastIndexOf("AC Powered:") + 1
    Dim topic As String = value.Substring(topic_start, value.Length - topic_start)
    TextBox1.Text = topic.ToString
End Sub

Button1 is labeled Get Battery Information in the image.

Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
  • You might want to show how that data got inside the TextBox. However, you just need to `.Split()` the TextBox.Text using VbCrLf as separator. – Jimi Dec 30 '17 at 13:33
  • What code have you written so far? We cannot simple write entire code for you – Sunil Dec 30 '17 at 13:43
  • All relevant information should be posted in the question, not linked on another site. – Visual Vincent Dec 30 '17 at 14:26
  • So what's wrong with the code you already have? What happens/doesn't happen when you run it? – Visual Vincent Dec 30 '17 at 14:40
  • Do you need that TextBox or not? From what I see, you want to fill those "fields" when the user presses a button. If so, you need to store those values returned in `Results` inside a List() or Array(), then, on demand, fill the textboxes/labels with the items of that List/Array. – Jimi Dec 30 '17 at 15:04
  • I highly discourage calling ReadToEnd on the process output stream. I've had the problem where it hangs before. Here are some alternative recommended solutions here on reading the stream: https://stackoverflow.com/questions/7160187/standardoutput-readtoend-hangs – Ctznkane525 Dec 30 '17 at 18:47

3 Answers3

2
 Private Sub UpdateText()
  Dim xList As New List(Of KeyValuePair(Of String, String))
    Results = Results.Replace(vbLf, "")
    Dim LineSplit() As String = Results.Split(vbCr)
    For Each xLine As String In LineSplit
        If xLine <> "" Then
            xList.Add(New KeyValuePair(Of String, String)(xLine.Split(":")(0), xLine.Split(":")(1).Trim.Replace(" ", "")))
        End If
    Next
'do some work here to put the values in the right textboxes

End Sub

You can make yourself a custom control made of a label and a textbox that you use in your app. Then you just pass each entry of the list to your custom controls. Makes it easier to add or remove fields without having tons of IF then or a big Select Case

Chillzy
  • 468
  • 3
  • 9
2

Here one way to extract values from text that is separated with new lines (Enviroment.NewLine) using IndexOf(), Substring() methods and Length property:

Private Sub UpdateGUI()
    Dim lines As String() = TextBox1.Text.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)

    For Each itm In lines
        MsgBox(itm.Substring(itm.IndexOf(":") + 1, itm.Length - itm.IndexOf(":") - 1))
    Next
End Sub
Jonathan Applebaum
  • 5,738
  • 4
  • 33
  • 52
2

Unless your TextBoxes are named exactly like the value in your return string (you'd have to convert the space to some other character anyways), there really isn't any way to do this except to manually code each case. Something like this should do it, just change the name of the TextBoxes accordingly:

Private Sub UpdateText()
    Dim lines() As String = Results.Split(vbCrLf.ToCharArray, StringSplitOptions.RemoveEmptyEntries)
    For Each line In lines
        Dim values() As String = line.Split(":")
        Select Case values(0).ToUpper.Trim
            Case "AC POWERED"
                TextBox1.Text = values(1).ToUpper.Trim
            Case "USB POWERED"
                TextBox2.Text = values(1).ToUpper.Trim
            Case "WIRELESS POWERED"
                TextBox3.Text = values(1).ToUpper.Trim
            Case "STATUS"
                TextBox4.Text = values(1).ToUpper.Trim
            Case "HEALTH"
                TextBox5.Text = values(1).ToUpper.Trim
            Case "PRESENT"
                TextBox6.Text = values(1).ToUpper.Trim
            Case "LEVEL"
                TextBox7.Text = values(1).ToUpper.Trim
            Case "SCALE"
                TextBox8.Text = values(1).ToUpper.Trim
            Case "VOLTAGE"
                TextBox9.Text = values(1).ToUpper.Trim
            Case "TEMPERATURE"
                TextBox10.Text = values(1).ToUpper.Trim
            Case "TECHNOLOGY"
                TextBox11.Text = values(1).ToUpper.Trim
            Case Else
                MessageBox.Show(line, "Unknown Value")
        End Select
    Next
End Sub

If you named your TextBoxes in a predictable manner, then you can use Controls.Find() and shorten the code to the below. For instance, change spaces to underscore, and prepend "txt" in front: "txtAC_Powered", "txtUSB_Powered", "txtStatus", "txtHealth", etc. Case does NOT matter as a match will be found regardless. This means you're doing the manual work in naming your controls, as opposed to writing a long select case statement (or something else):

Private Sub UpdateText()
    Dim lines() As String = Results.Split(vbCrLf.ToCharArray, StringSplitOptions.RemoveEmptyEntries)
    For Each line In lines
        Dim values() As String = line.Split(":")
        Dim ctlName As String = "txt" & values(0).Replace(" ", "_").Trim
        Dim ctl As Control = Me.Controls.Find(ctlName, True).FirstOrDefault
        If Not IsNothing(ctl) Then
            ctl.Text = values(1).ToUpper.Trim
        End If
    Next
End Sub
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40