Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Parse the output of DOS command

Posted on 2009-05-12
14
Medium Priority
?
697 Views
Last Modified: 2012-05-06
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
Comment
Question by:msyed1
  • 7
  • 7
14 Comments
 
LVL 21

Expert Comment

by:AmazingTech
ID: 24365665
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
 

Author Comment

by:msyed1
ID: 24365757
AmazingTech:
I need more help then that.  Please explain what this command does and where exactly does it fit in...in my code ??  
0
 
LVL 21

Expert Comment

by:AmazingTech
ID: 24365905
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:msyed1
ID: 24366393
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
 
LVL 21

Expert Comment

by:AmazingTech
ID: 24366652
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
 

Author Comment

by:msyed1
ID: 24368476
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
 
LVL 21

Expert Comment

by:AmazingTech
ID: 24369275
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
 

Author Comment

by:msyed1
ID: 24369390
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
 
LVL 21

Expert Comment

by:AmazingTech
ID: 24369575
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
 

Author Comment

by:msyed1
ID: 24371139
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
 

Author Comment

by:msyed1
ID: 24371154
Here is the csv file.  CSV file is not going through.  I changed it to .txt.
RuntimeInfo5122009-6-39-PM.txt
0
 
LVL 21

Accepted Solution

by:
AmazingTech earned 2000 total points
ID: 24371834
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
 

Author Closing Comment

by:msyed1
ID: 31580567
THANKS A LOT for working with me on this.  You've been great.  The Wait is doing the job.  msyed1.
0
 
LVL 21

Expert Comment

by:AmazingTech
ID: 24375589
OK. Great. Thanks for the grade.
0

Featured Post

 [eBook] Windows Nano Server

Download this FREE eBook and learn all you need to get started with Windows Nano Server, including deployment options, remote management
and troubleshooting tips and tricks

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

YESTERDAY YESTERDAY.BAT is inspired by a previous article I wrote entitled: TOMORROW.BAT (http://www.experts-exchange.com/OS/Microsoft_Operating_Systems/MS_DOS/A_4196-Advanced-Batch-File-Programming-TOMORROW-BAT.html). The crux of this batch f…
The purpose of this article is to demonstrate how we can use conditional statements using Python.
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
Suggested Courses

783 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question