• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 711
  • Last Modified:

Parse the output of DOS command

Hello,

I have a console (vb.net) program in which I am opening a DOS prompt and running the PSINFO command:
:\PSINFO "Kernel version" \\computername>
What I need is to pick up only the machine's OS from the results that this command brings back.  The below is what the PSINFO output looks like.  I need to pluck out only the part that has the OS version info.  From the below example it would be "Microsoft Windows Server 2003, Multiprocessor Free".  I have done all kinds of string manipulations, but haven't succeeded in picking out just the OS version.  I hope someone can help me.:
====================================================
C:\GARTDiscoverServerOS>psinfo "Kernel version" \\entlc201

PsInfo v1.75 - Local and remote system information viewer
Copyright (C) 2001-2007 Mark Russinovich
Sysinternals - www.sysinternals.com

System information for \\entlc201:
Kernel version:            Microsoft Windows Server 2003, Multiprocessor Free


C:\GARTDiscoverServerOS>
=======================================================
Function GetOSVersionThruPSINFO(ByVal strServerIP As String, ByVal strDomain As String) As String
        Dim myProcess As New System.Diagnostics.Process
        Dim s, serverOS As String
        Dim startlocation, endlocation As Integer
 
        Try
            ''''''' Starting DOS Prompt
            myProcess.StartInfo.FileName = "cmd.exe"
            myProcess.StartInfo.UseShellExecute = False
            myProcess.StartInfo.CreateNoWindow = True
            myProcess.StartInfo.RedirectStandardInput = True
            myProcess.StartInfo.RedirectStandardOutput = True
            myProcess.StartInfo.RedirectStandardError = True
 
            myProcess.Start()
 
            Dim sIn As StreamWriter = myProcess.StandardInput
            Dim sOut As StreamReader = myProcess.StandardOutput
            Dim sErr As StreamReader = myProcess.StandardError
 
            sIn.AutoFlush = True
 
            log.Info("*******************Now performing PSINFO for Incoming Server Name: " & strDomain & " - " & strServerIP)
            ''''''' This command filters everything else out....except for what I need which is the Kernal version
            sIn.Write("psinfo ""Kernel version"" \\" & strDomain & System.Environment.NewLine)
 
            sIn.Write("exit" & System.Environment.NewLine)
 
            '''''''' going into read mode - read the results of DOS command
            s = sOut.ReadToEnd()
 
            If Not myProcess.HasExited Then
                myProcess.Kill()
            End If
 
            sIn.Close()
            sOut.Close()
            sErr.Close()
            myProcess.Close()
            log.Info("Output of PSINFO: " & s)
 
            If s.IndexOf("Kernel version") > 1 Then
                startlocation = (s.IndexOf("Kernel version") + 27)
            End If
 
            '''''''''End If
 
            Dim intEntireLen As Integer = s.Length()
            Dim intFirstSpace As Integer = s.IndexOf(" ", startlocation)
 
            serverOS = s.Substring(startlocation, ((intFirstSpace - 1) - startlocation))
 
            Return serverOS
        Catch ex As Exception
            log.Error("Error occurred: " & ex.Message)
        End Try
    End Function

Open in new window

0
msyed1
Asked:
msyed1
  • 7
  • 7
1 Solution
 
AmazingTechCommented:
From DOS on the command line.
for /f "tokens=2,* delims=: " %a in ('psinfo "kernel version" \\entlc201 ^| find /i "kernel version"') do echo %b

Open in new window

0
 
msyed1Author Commented:
AmazingTech:
I need more help then that.  Please explain what this command does and where exactly does it fit in...in my code ??  
0
 
AmazingTechCommented:
Hmm...

Replace line 25 with code below.

If it works properly it should display

Output of PSINFO: Microsoft Windows Server 2003, Multiprocessor Free


     sIn.Write("for /f ""tokens=2,* delims=: "" %a in ('psinfo ""kernel version"" \\" & strDomain & " ^| find /i ""kernel version""') do echo %b" & System.Environment.NewLine)

Open in new window

0
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
msyed1Author Commented:
AmazingTech:
I did what you advised and still 's' which is the output of the command has all kinds of junk in it...so I will still need to parse out the OS Version, which is Microsoft Windows 2000.  All I need is machine's OS version.  Please see the attachment that shows the value of 's' in debug mode.  msyed1
debug-screen.doc
0
 
AmazingTechCommented:
Oh... I see now.

There's probably 2 different ways to fix this. I really only want to get the info you want so we'll try and get it to only output what we want in sOut.ReadToEnd() instead of parsing this.


Function GetOSVersionThruPSINFO(ByVal strServerIP As String, ByVal strDomain As String) As String
        Dim myProcess As New System.Diagnostics.Process
        Dim s, serverOS As String
        Dim startlocation, endlocation As Integer
 
        Try
            ''''''' Starting DOS Prompt
            myProcess.StartInfo.FileName = "cmd.exe"
            myProcess.StartInfo.UseShellExecute = False
            myProcess.StartInfo.CreateNoWindow = True
            myProcess.StartInfo.RedirectStandardInput = True
            myProcess.StartInfo.RedirectStandardOutput = True
            myProcess.StartInfo.RedirectStandardError = True
 
            myProcess.Start()
 
            Dim sIn As StreamWriter = myProcess.StandardInput
            Dim sOut As StreamReader = myProcess.StandardOutput
            Dim sErr As StreamReader = myProcess.StandardError
 
            sIn.AutoFlush = True
 
            log.Info("*******************Now performing PSINFO for Incoming Server Name: " & strDomain & " - " & strServerIP)
            ''''''' This command filters everything else out....except for what I need which is the Kernal version
            sIn.Write("/c @for /f ""tokens=2,* delims=: "" %a in ('@psinfo ""kernel version"" \\" & strDomain & " ^| @find /i ""kernel version""') do @echo %b" & System.Environment.NewLine)
  
            '''''''' going into read mode - read the results of DOS command
            s = sOut.ReadToEnd()
 
            If Not myProcess.HasExited Then
                myProcess.Kill()
            End If
 
            sIn.Close()
            sOut.Close()
            sErr.Close()
            myProcess.Close()
            log.Info("Output of PSINFO: " & s)
 
            serverOS = "Not Available"
            if s <> "" then serverOS = s
 
            Return serverOS
        Catch ex As Exception
            log.Error("Error occurred: " & ex.Message)
        End Try
    End Function

Open in new window

0
 
msyed1Author Commented:
AmazingTech:  I am trying to test the latest you sent, but the  's = sOut.ReadToEnd()' takes a very LOOOONNG time.  It goes into the DOS mode at that line and stays there for hours.  Right now I am testing with only 1 servername.  Do you have any idea why the command ReadToEnd() takes so long ?? msyed1.
0
 
AmazingTechCommented:
Hmm... Maybe it doesn't work properly with /c to close cmd.exe when the code is finished.

OK. Let's go back to your original code and now see if we can get the proper line.
Function GetOSVersionThruPSINFO(ByVal strServerIP As String, ByVal strDomain As String) As String
        Dim myProcess As New System.Diagnostics.Process
        Dim s, serverOS As String
        Dim startlocation, endlocation As Integer
 
        Try
            ''''''' Starting DOS Prompt
            myProcess.StartInfo.FileName = "cmd.exe"
            myProcess.StartInfo.UseShellExecute = False
            myProcess.StartInfo.CreateNoWindow = True
            myProcess.StartInfo.RedirectStandardInput = True
            myProcess.StartInfo.RedirectStandardOutput = True
            myProcess.StartInfo.RedirectStandardError = True
 
            myProcess.Start()
 
            Dim sIn As StreamWriter = myProcess.StandardInput
            Dim sOut As StreamReader = myProcess.StandardOutput
            Dim sErr As StreamReader = myProcess.StandardError
 
            sIn.AutoFlush = True
 
            log.Info("*******************Now performing PSINFO for Incoming Server Name: " & strDomain & " - " & strServerIP)
            ''''''' This command filters everything else out....except for what I need which is the Kernal version
            sIn.Write("for /f ""tokens=2,* delims=: "" %a in ('psinfo ""kernel version"" \\" & strDomain & " ^| find /i ""kernel version""') do echo %b" & System.Environment.NewLine)
            sIn.Write("exit" & System.Environment.NewLine)
 
            '''''''' going into read mode - read the results of DOS command
            s = split(sOut.ReadToEnd(), System.Environment.NewLine)
 
            If Not myProcess.HasExited Then
                myProcess.Kill()
            End If
 
            sIn.Close()
            sOut.Close()
            sErr.Close()
            myProcess.Close()
            log.Info("Output of Kernel Version: " & s(6))
 
            serverOS = "Not Available"
            if s(6) <> "" then serverOS = s(6)
 
            Return serverOS
        Catch ex As Exception
            log.Error("Error occurred: " & ex.Message)
        End Try
    End Function

Open in new window

0
 
msyed1Author Commented:
Now I am getting
"Value of type '1-dimensional array of string' cannot be converted to string. on
s = split(sOut.ReadToEnd(), System.Environment.NewLine)
0
 
AmazingTechCommented:
Opps sorry you dim s as string.

How about this?
Function GetOSVersionThruPSINFO(ByVal strServerIP As String, ByVal strDomain As String) As String
        Dim myProcess As New System.Diagnostics.Process
        Dim s, serverOS As String
        Dim startlocation, endlocation As Integer
 
        Try
            ''''''' Starting DOS Prompt
            myProcess.StartInfo.FileName = "cmd.exe"
            myProcess.StartInfo.UseShellExecute = False
            myProcess.StartInfo.CreateNoWindow = True
            myProcess.StartInfo.RedirectStandardInput = True
            myProcess.StartInfo.RedirectStandardOutput = True
            myProcess.StartInfo.RedirectStandardError = True
 
            myProcess.Start()
 
            Dim sIn As StreamWriter = myProcess.StandardInput
            Dim sOut As StreamReader = myProcess.StandardOutput
            Dim sErr As StreamReader = myProcess.StandardError
 
            sIn.AutoFlush = True
 
            log.Info("*******************Now performing PSINFO for Incoming Server Name: " & strDomain & " - " & strServerIP)
            ''''''' This command filters everything else out....except for what I need which is the Kernal version
            sIn.Write("for /f ""tokens=2,* delims=: "" %a in ('psinfo ""kernel version"" \\" & strDomain & " ^| find /i ""kernel version""') do echo %b" & System.Environment.NewLine)
            sIn.Write("exit" & System.Environment.NewLine)
 
            '''''''' going into read mode - read the results of DOS command
            stemp = split(sOut.ReadToEnd(), System.Environment.NewLine)
 
            If Not myProcess.HasExited Then
                myProcess.Kill()
            End If
 
            sIn.Close()
            sOut.Close()
            sErr.Close()
            myProcess.Close()
            log.Info("Output of Kernel Version: " & stemp(6))
 
            serverOS = "Not Available"
            if stemp(6) <> "" then serverOS = stemp(6)
 
            Return serverOS
        Catch ex As Exception
            log.Error("Error occurred: " & ex.Message)
        End Try
    End Function

Open in new window

0
 
msyed1Author Commented:
It's working! but there is a but...  I used the code you sent but just changed 's' to a string array and it worked.  See code attached.  
I have close to 93 servers in an arraylist that I am processing.  See the .csv file.  For some reason after the first few, column 4 which is where I am placing the Server OS version says "'Not Available" even for servers that I know for sure are Windows servers and I can successfully do a psinfo on them through the command line.  Do you think we need to put a delay mechanism in there ?? because the psinfo command takes a long time.  I don't understand why it didn't go through and get the OS version of all those servers.  

Thank you very much.  You have helped me a lot.  msyed1.

Function GetOSVersionThruPSINFO(ByVal strServerIP As String, ByVal strDomain As String) As String
        Dim myProcess As New System.Diagnostics.Process
        Dim serverOS As String
        Dim s() As String
        Dim startlocation, endlocation As Integer
 
        Try
            ''''''' Starting DOS Prompt
            myProcess.StartInfo.FileName = "cmd.exe"
            myProcess.StartInfo.UseShellExecute = False
            myProcess.StartInfo.CreateNoWindow = True
            myProcess.StartInfo.RedirectStandardInput = True
            myProcess.StartInfo.RedirectStandardOutput = True
            myProcess.StartInfo.RedirectStandardError = True
 
            myProcess.Start()
 
            Dim sIn As StreamWriter = myProcess.StandardInput
            Dim sOut As StreamReader = myProcess.StandardOutput
            Dim sErr As StreamReader = myProcess.StandardError
 
            sIn.AutoFlush = True
 
            log.Info("*******************Now performing PSINFO for Incoming Server Name: " & strDomain & " - " & strServerIP)
            ''''''' This command filters everything else out....except for what I need which is the Kernal version
            sIn.Write("for /f ""tokens=2,* delims=: "" %a in ('psinfo ""kernel version"" \\" & strDomain & " ^| find /i ""kernel version""') do echo %b" & System.Environment.NewLine)
            sIn.Write("exit" & System.Environment.NewLine)
 
            '''''''' going into read mode - read the results of DOS command and split each line using 
            '''''''' System.Environment.Newline as the delimeter.
 
            s = split(sOut.ReadToEnd(), System.Environment.NewLine)
 
            If Not myProcess.HasExited Then
                myProcess.Kill()
            End If
 
            sIn.Close()
            sOut.Close()
            sErr.Close()
            myProcess.Close()
            log.Info("Output of Kernel Version: " & s(6))
 
            serverOS = "Not Available"
            If s(6) <> "" Then serverOS = s(6)
 
            Return serverOS
        Catch ex As Exception
            log.Error("Error occurred: " & ex.Message)
        End Try
    End Function

Open in new window

0
 
msyed1Author Commented:
Here is the csv file.  CSV file is not going through.  I changed it to .txt.
RuntimeInfo5122009-6-39-PM.txt
0
 
AmazingTechCommented:
Hmm.. Reading on the internet it seems that you're running this asynchronously. Basically it doesn't wait for PSINFO to finish.

Try this.

myProcess.WaitForExit()

http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput.aspx
Function GetOSVersionThruPSINFO(ByVal strServerIP As String, ByVal strDomain As String) As String
        Dim myProcess As New System.Diagnostics.Process
        Dim serverOS As String
        Dim s() As String
        Dim startlocation, endlocation As Integer
 
        Try
            ''''''' Starting DOS Prompt
            myProcess.StartInfo.FileName = "cmd.exe"
            myProcess.StartInfo.UseShellExecute = False
            myProcess.StartInfo.CreateNoWindow = True
            myProcess.StartInfo.RedirectStandardInput = True
            myProcess.StartInfo.RedirectStandardOutput = True
            myProcess.StartInfo.RedirectStandardError = True
 
            myProcess.Start()
 
            Dim sIn As StreamWriter = myProcess.StandardInput
            Dim sOut As StreamReader = myProcess.StandardOutput
            Dim sErr As StreamReader = myProcess.StandardError
 
            sIn.AutoFlush = True
 
            log.Info("*******************Now performing PSINFO for Incoming Server Name: " & strDomain & " - " & strServerIP)
            ''''''' This command filters everything else out....except for what I need which is the Kernal version
            sIn.Write("for /f ""tokens=2,* delims=: "" %a in ('psinfo ""kernel version"" \\" & strDomain & " ^| find /i ""kernel version""') do echo %b" & System.Environment.NewLine)
            sIn.Write("exit" & System.Environment.NewLine)
 
            '''''''' going into read mode - read the results of DOS command and split each line using 
            '''''''' System.Environment.Newline as the delimeter.
 
            s = split(sOut.ReadToEnd(), System.Environment.NewLine)
            myProcess.WaitForExit()
 
            If Not myProcess.HasExited Then
                myProcess.Kill()
            End If
 
            sIn.Close()
            sOut.Close()
            sErr.Close()
            myProcess.Close()
            log.Info("Output of Kernel Version: " & s(6))
 
            serverOS = "Not Available"
            If s(6) <> "" Then serverOS = s(6)
 
            Return serverOS
        Catch ex As Exception
            log.Error("Error occurred: " & ex.Message)
        End Try
    End Function

Open in new window

0
 
msyed1Author Commented:
THANKS A LOT for working with me on this.  You've been great.  The Wait is doing the job.  msyed1.
0
 
AmazingTechCommented:
OK. Great. Thanks for the grade.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

  • 7
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now