Link to home
Start Free TrialLog in
Avatar of NO7EMBER
NO7EMBER

asked on

Need a script to find out if connected machines are running auto, full duplex 100Mbs or 10Mbs.

We have thousands of computers connected to our lan and want all of them to run at 100mbs full duplex.  This however is not the case and we often get flags that show us that there are some machines not to speed.  Is there anyway to tell which hardware is running at auto, full 100Mbs or 10Mbps on our LAN?  I read on the internet a few months ago about a script written that could detect this.  Any help would be greatly appreciated.
Avatar of grblades
grblades
Flag of United Kingdom of Great Britain and Northern Ireland image

On Windows there is a piece of software called Aida (not currently being developed/supported any more unfortunetly) which among other thing I think will tell you at what speed you are connected at. You can download it from
http://www.majorgeeks.com/downloadget.php?id=181&file=9&evp=e292483f0de3e518ff57fb57cf6eb944

Personally I would recomend that you use managed switches and query them for the speed which clients are connected to it at.
Avatar of NO7EMBER
NO7EMBER

ASKER

Thanks grblades for the aida32 application, unfortunately it wasn't exactly what I was looking for.  What I need is a script that I can put into the logon script to run and identify computers connected to my lan that are not set at 100Mbs full duplex.  
That information is not "instrumented" by Windows.  Which means the only practical way to determine the connection speed and duplex-edness (did I just make up a word?) is to query the device driver directly.

While this is not too difficult for a system-level program to do on a workstation, it would be very difficult to do remotely via a poll of the network devices.  Do you have a programmer on staff that can whoop out a quick-n-dirty program?   If so you could paste it in the login batch and collect the data in a logfile or database
Here are a series of free, or nearly so, network monitoring tools that can check individual IPs on the network.

http://www.freewarehome.com/Internet/Networking/Network_Monitoring_t.html

You will want something more robust in the end, but these will at least show you what is available for a song, so when you shelll out several grand for software that someone like Computer Associates wants to sell you, you'll have a good perspective on its value.

 I know this can be done, because I saw a network guru at a fortune 100 Co using it, and he could finger each individual card for speed, thruput, packets, etc.
Also look at this -- suggested by dullz, on another thread --

http://www.netchain.com/netcps/
hmmm.....maybe a brute force approach.  Force the switch ports to let only 100Mb clients attach?  It will become very obvious very quickly who is 10Mbs :)
>I know this can be done, because I saw a network guru at a fortune 100 Co using it, and he could finger each individual card for speed, thruput, packets, etc.

Probably had newer nics with SNMP management feature. Other than that your switches may let you monitor ports.
Yep, practically all hubs (with the exception of $100 home market hubs) are well instrumented.  The SNMP management features are typically very good at this kind of query.

The only API that's of any use is MultinetGetConnectionPerformance which must be run from the client PC over an existing connection (like a mapped drive).  Even then... it will only give you the speed, not the duplex settings.  The only way (from the client PC) to detect the duplex setting is from the device driver (not the NDIS "mini-port", but the *real* hardware device driver).
Hey... try this... see if it give correct results.  You'll have to do the math yourself on the Duplex (I can't figure out how to do a bit-wise OR in vbscript)

dim objs, obj, duplex

Set objs = GetObject("winmgmts:\\.\root\wmi").InstancesOf("MSNdis_LinkSpeed")
for each obj in objs
      if obj.Active = true then
            msgbox("Name=" & obj.InstanceName)
            msgbox("LinkSpeed=" & obj.NdisLinkSpeed * 100)
      end if
next
Set objs = GetObject("winmgmts:\\.\root\wmi").InstancesOf("MSNdis_MacOptions")
for each obj in objs
      if obj.Active = true then
            msgbox("Name=" & obj.InstanceName)
            msgbox("NdisMacOptions=" & obj.NdisMacOptions)
            ' vbscript doesn't have a bit-wise OR operator... but this
            ' is what it'd look like
            'if (obj.NdisMacOptions or 16) = 16 then
            '  msgbox("Duplex=Full")
            'else
            '  msgbox("Duplex=Half")
            'end if
      end if
next
Actually I wouldn't need the duplex settings just the speed the machines are connected at.  I don't know if I'm making any sense but basically, the machines that are running at the slower 10mbps are dramatically slowing down the entire network.  I need a way to identify,isolate and correct the slower 10mbps machines to run at 100mbps.
Ok.. then just use the top half of that script as an example to go on.

You could probably "tighten down" the listing of unwanted nework interfaces by something like:

      if left(obj.Name, 4) <> "WAN " and right(obj.Name, 8) <> "Miniport" then
I'm not too familiar with editing scripts could you show me the exact syntax and kinda explain what each part does.  Thanks.
ASKER CERTIFIED SOLUTION
Avatar of graye
graye
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Darn.. l made an error....

replace:
     Set objs = GetObject("winmgmts:\\.\root\wmi").InstancesOf("MSNdis_LinkSpeed")
with:
     Set objs = GetObject("winmgmts:\\" & ComputerName & "\root\wmi").InstancesOf("MSNdis_LinkSpeed")
This returned very good information  but could you explain to me what each prompt means and what it is doing.  Also I will be needing to find out the duplex of the connection.  Is there a way I can find it querrying the wmi logs?  Thanks alot for your help.  We're almost there.
Darn... another error  (I guess I should run this on my domain as a test, eh?)

replace this section:

     if left(buf, 2) = "\\" then
          i = instr(buf, " ")
          ComputerName = mid(buf, 3, i-3)
               DoIt computername
          end if
     end if

 with:
      if left(buf, 2) = "\\" then
            i = instr(buf, " ")
            ComputerName = mid(buf, 3, i-3)
            DoIt computername
      end if
One more error (the last one.. I promise!)   I'm running it on my domain now to test the results.

replace:
     set ts = fso.OpenTextFile("c:\LinkSpeed_Log.txt", 2)
with:
     set ts = fso.OpenTextFile("c:\LinkSpeed_Log.txt", 2, true)
OK... now that I *finally* got the silly script working... I'll answer your other questions.

The script is basically just in two parts... the first part create a text file on your PC to record all of the results.  Next it launches a command prompt with the "Net View" command in order to get a list of PCs in your domain. (actually, it's just the list that appears in the My Network Places).  The script then "reads" the lines in the output of that Net command.   Each line is read... and if the line looks like a PC (it starts with a "\\"), then parse the computer name from the line.

Up till this point, the script is rather generic... I use this technique on practically all of my scripts that are designed to poll the network.

OK... the second part of the script is when after it parse a computer name.   It then calls that subroutine that remotely attaches to that computer (which is why you need to be a Domain Administrator).  Using Windows Management Instrumentation (WMI), the script collects instrumentation data on the network drivers.  However, most PCs have more than one network driver (modem, ethernet, and the internal "miniport").  So we have to disregard the network drivers that we don't want.  Next we retrieve one of the things that is instrumented by WMI... namely the LinkSpeed and the MacOptions (er...well, this last version didn't include MacOptions...but follow along anyway).  So the script takes these values and records them in the log file.

That's about it.
This is some good stuff, but the script seems to be only showing the servers connected not the connection speed and duplex of the individual pc's.  Any thoughts?  BTW thanks alot for the explanation above, very helpful.
Hey I know this is off the subject but is there anyway to write a script to find which .pst files on a user's computer is over 500mb and log it into a local drive like the script we have above for the nic's?  I am trying to limit the mailbox sizes and want to identify which ones are over the 500mb limit.  Thanks a bunch!!!
Hummm... I just ran that script on my domain... and I got entries in the log file for all 300 PCs.  Do you guys have some sort of firewall (hardware or software) install that might limit the script to just the servers?

Pop open a command prompt and type "Net view /domain:whatever" to see what you get.

Yeah, it wouldn't be too difficult to modify that script to look for PST files.  But let's get this one working for you first.

BTW:  I've got a application called SOSOS that will gather over 180 pieces of information from each PC on your network.  You might wanna check it out at http://www.dpw.hood.army.mil/ftp/sosos
Ok it worked.  You are a genius I'm so glad I found you...or other way around.  Anyway, I ran the "Net view /domain:whatever" command and it listed a whole bunch of computers.  I ran the script at around 11:30am and its still running, listing the connected machines.  At first it was listing the servers only but now the list is getting longer, including pc's and is at around 750.  Anyway I think your script did the job, but is there a way we can find the duplex of the connection?  If not its ok.  You more than solved my problem.  THanks again!!!

ps.  could you help me with getting the script for the pst files when u get a chance.  Thanks.
I couldn't get the duplex thing to work (at least on my network... it showed every adpater as half-duplex)

Here is a chunk of VB.Net code that gets information about the PST files...  It is NOT a complete solution... it's just an chunk of code that you can use as an example to develop your own application to get PST file information.   Also, this code is from a working program, so it will contain a lot of stuff that you should safely ignore.  

Show this to a VB.Net programmer... he'll know what do to.

Imports Microsoft.Win32
Module Email
    Function DoEmail(ByVal RemotePC As String, ByVal ds As DataSet, ByRef fm As Form1) As Integer
        Dim reg, key, subkey, sub2 As RegistryKey
        Dim filename, keyname, subkeyname As String
        Dim fi As System.IO.FileInfo
        Dim msg, temp, user, CurKey As String
        Dim got_it As Boolean
        Dim dr As DataRow
        Dim ret As Integer

        Try
            reg = RegistryKey.OpenRemoteBaseKey(RegistryHive.Users, RemotePC)
        Catch ex As Exception
            ' ignore this common error
            If Err.Number = 57 Then
                Return vbOK
            End If
            ret = MsgBox("Yikes!, Can't connect to " & RemotePC & "'s registry" & vbCr & ex.message, MsgBoxStyle.Critical Or MsgBoxStyle.OKCancel, "Error!")
            Return ret
        End Try

        ' Find the User key that has "Volatile Environment"... that's either
        ' the current user or the last user logged in.
        For Each keyname In reg.GetSubKeyNames()
            Try
                key = reg.OpenSubKey(keyname, False)
            Catch ex As Exception
                ret = MsgBox("Yikes!, Can't open " & RemotePC & "'s registry" & vbCr & ex.message, MsgBoxStyle.Critical Or MsgBoxStyle.OKCancel, "Error!")
                Return ret
            End Try
            If Not IsNothing(key) Then
                For Each temp In key.GetSubKeyNames()
                    If temp = "Volatile Environment" Then
                        CurKey = keyname
                        Exit For
                    End If
                Next
                If CurKey <> "" Then
                    Exit For
                End If
                key.Close()
            End If
        Next
        user = "Nobody!"
        key = reg.OpenSubKey(CurKey & "\Software\Microsoft\Windows\CurrentVersion\Explorer", False)
        If Not IsNothing(key) Then
            user = key.GetValue("Logon User Name")
            key.Close()
        End If

        ' for Win2k, etc
        got_it = False
        key = reg.OpenSubKey(CurKey & "\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles", False)
        If Not IsNothing(key) Then
            For Each keyname In key.GetSubKeyNames()
                subkey = key.OpenSubKey(keyname, False)
                For Each subkeyname In subkey.GetSubKeyNames()
                    sub2 = subkey.OpenSubKey(subkeyname, False)
                    filename = sub2.GetValue("001e6700")
                    If Not IsNothing(filename) AndAlso System.IO.File.Exists(ConvUNC(RemotePC, filename)) Then
                        fi = New System.IO.FileInfo(ConvUNC(RemotePC, filename))
                        fm.count = fm.count + 1
                        dr = ds.Tables("Email").NewRow()
                        dr("PCName") = RemotePC
                        dr("CurDate") = Now()
                        dr("CurUser") = user
                        dr("Profile") = keyname
                        dr("FilePath") = filename
                        dr("FileType") = "PST"
                        dr("FileSize") = fi.Length / 1024
                        ds.Tables("Email").Rows.Add(dr)
                        got_it = True
                    End If
                    filename = sub2.GetValue("001e6600")
                    If Not IsNothing(filename) AndAlso System.IO.File.Exists(ConvUNC(RemotePC, filename)) Then
                        fi = New System.IO.FileInfo(ConvUNC(RemotePC, filename))
                        dr = ds.Tables("Email").NewRow()
                        fm.count = fm.count + 1
                        dr("PCName") = RemotePC
                        dr("CurDate") = Now()
                        dr("CurUser") = user
                        dr("Profile") = keyname
                        dr("FilePath") = filename
                        dr("FileType") = "PAB"
                        dr("FileSize") = fi.Length / 1024
                        ds.Tables("Email").Rows.Add(dr)
                        got_it = True
                    End If
                    sub2.Close()
                Next
                subkey.Close()
                ' no PST or PAB?  That's OK... I still want the profile
                ' name in the database
                If Not got_it Then
                    dr = ds.Tables("Email").NewRow()
                    fm.count = fm.count + 1
                    dr("PCName") = RemotePC
                    dr("CurDate") = Now()
                    dr("CurUser") = user
                    dr("Profile") = keyname
                    ds.Tables("Email").Rows.Add(dr)
                End If
            Next
            key.Close()
        End If

        ' for Win9x
        key = reg.OpenSubKey(CurKey & "\Software\Microsoft\Windows Messaging Subsystem\Profiles", False)
        If Not IsNothing(key) Then
            For Each keyname In key.GetSubKeyNames()
                dr = ds.Tables("Email").NewRow()
                fm.count = fm.count + 1
                dr("PCName") = RemotePC
                dr("Profile") = keyname
                dr("CurDate") = Now()
                dr("CurUser") = user
                ds.Tables("Email").Rows.Add(dr)
                subkey = key.OpenSubKey(keyname, False)
                For Each subkeyname In subkey.GetSubKeyNames()
                    sub2 = subkey.OpenSubKey(subkeyname, False)
                    filename = sub2.GetValue("001e6700")
                    If Not IsNothing(filename) AndAlso System.IO.File.Exists(ConvUNC(RemotePC, filename)) Then
                        fi = New System.IO.FileInfo(ConvUNC(RemotePC, filename))
                        dr = ds.Tables("Email").NewRow()
                        fm.count = fm.count + 1
                        dr("PCName") = RemotePC
                        dr("CurDate") = Now()
                        dr("CurUser") = user
                        dr("Profile") = keyname
                        dr("FilePath") = filename
                        dr("FileType") = "PST"
                        dr("FileSize") = fi.Length / 1024
                        ds.Tables("Email").Rows.Add(dr)
                        got_it = True
                    End If
                    filename = sub2.GetValue("001e6600")
                    If Not IsNothing(filename) AndAlso System.IO.File.Exists(ConvUNC(RemotePC, filename)) Then
                        fi = New System.IO.FileInfo(ConvUNC(RemotePC, filename))
                        dr = ds.Tables("Email").NewRow()
                        fm.count = fm.count + 1
                        dr("PCName") = RemotePC
                        dr("CurDate") = Now()
                        dr("CurUser") = user
                        dr("Profile") = keyname
                        dr("FilePath") = filename
                        dr("FileType") = "PAB"
                        dr("FileSize") = fi.Length / 1024
                        ds.Tables("Email").Rows.Add(dr)
                        got_it = True
                    End If
                    sub2.Close()
                Next
                subkey.Close()
            Next
            ' no PST or PAB?  That's OK... I still want the profile
            ' name in the database
            If Not got_it Then
                dr = ds.Tables("Email").NewRow()
                fm.count = fm.count + 1
                dr("PCName") = RemotePC
                dr("CurDate") = Now()
                dr("CurUser") = user
                dr("Profile") = keyname
                ds.Tables("Email").Rows.Add(dr)
            End If
            key.Close()
        End If
        reg.Close()

        Return vbOK
    End Function

    Public Function ConvUNC(ByVal RemotePC As String, ByVal Filename As String) As String
        Dim ans As String

        If Len(Filename) > 0 Then
            ans = "\\" & RemotePC & "\" & Filename.Substring(0, 1) & "$" & Filename.Substring(2)
        End If
        Return ans
    End Function
End Module


Hey thanks for the script but we don't have a programmer here so I don't know how I would get this running.  Any help would be appreciated.  thanks.
ok... but it will be next week some time

Perhaps somebody else is following this thread and will volunteer to help out in the mean time?
No, I haven't forgotten you...

I just finished program that will return information about PST files.  It is a "plug-in" for an application called Probe.  We use Probe for all sorts of quick-n-dirty requirements to get information from a few hundred PCs.

I've placed the VB.Net source code for the entire project... the Probe application and the PST plug-in on our web site.  For strange reasons that I won't go into, we don't release any executable code... only source code.  That means you'll have to find somebody that has Visual Studio .Net to compile it for you.

There is no install... just copy the program, it's DLL file and the PST DLL file into a directory somewhere and run it as a domain administrator.  Sorry, we don't do "tech support"... it's a take or leave it proposition!

http://www.dpw.hood.army.mil/ftp/Probe

BTW: I've probably mentioned this once or twice before, but if you've got several hundred PCs to manage, you need a to have a "System Programmer" on staff (or under contract).  Little tools like this (that take only an hour or so to punch out) can make the life of a system administrator soooooo much easier.
Thanks for all your help.  I will get together with some people around here and try to get it working.