Reading Remote Registy of many pc's

Hi all,

I need help. I could do this if I spend the time but I need to be on with something else.. Time so spend some points.

I need to connect for my pc to another pc and read out the following registry key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\CachePrimaryDomain

HKEY_LOCAL_MACHINE\SOFTWARE\MYCOMPANY\Computer\Build

HKEY_LOCAL_MACHINE\SOFTWARE\MYCOMPANY\Computer\BuildType

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\ComputerName\ComputerName\ComputerName

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet\Services\Netlogon\Parameters\DynamicSiteName

HKEY_LOCAL_MACHINE\SOFTWARE\MYCOMPANY\Country

HKEY_LOCAL_MACHINE\SOFTWARE\MYCOMPANY\SubRegionGHOSTBuild

HKEY_LOCAL_MACHINE\SOFTWARE\MYCOMPANY\Computer\HotFix                   (needs to read all the names of sub keys)

HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\DELL__\                         (read the name of next key)

HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\SystemBiosDate

HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0\ProcessorNameString

Once its read in all this info i need to have it output in to a format i can make use of it.. CSV or Excel or simmlar. All the pc will be in a set ip range. The program needs to ask for a start ip address and a finish IP address then attempt to connect to each IP in turn. Pulling out all the details it can. If it fail it should just show the ip and the resolved name, then move on.

I really hope that someone can help me with this. If you need any more details please let me know.



 
davesaundersnukAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jimbobmcgeeCommented:
You can read the registry, remotely, via the WMI.  You might want to read these, for more information:  

- http://support.microsoft.com/kb/314837
- http://support.microsoft.com/kb/290216
- http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/modifying_the_system_registry.asp

HTH

J.

0
davesaundersnukAuthor Commented:
I have read the registry.... I know it can be donw. I just dont have the time to write the code... so I thought I would post and ask..

0
jimbobmcgeeCommented:
The following should do mostly what your after.  Code is commented inline:

    ''''''STANDARD REGISTRY ENUMERATION'''''''''''''''''''''
    Private Enum regSubtrees
        HKEY_CLASSES_ROOT = &H80000000
        HKEY_CURRENT_USER = &H80000001
        HKEY_LOCAL_MACHINE = &H80000002
        HKEY_USERS = &H80000003
        HKEY_CURRENT_CONFIG = &H80000005
    End Enum
   
    Private Enum regDataTypes
        REG_SZ = 1
        REG_EXPAND_SZ = 2
        REG_BINARY = 3
        REG_DWORD = 4
        REG_MULTI_SZ = 7
    End Enum
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''
   
    ''''''STRUCTURE TO HOLD YOUR REGISTRY REQUIREMENTS''''''
    Private Type ExpReg
        ConnectOK           As Boolean
        DefaultUser         As Variant
        CachePrimaryDomain  As Variant
        Build               As Variant
        BuildType           As Variant
        Country             As Variant
        GHOSTBuild          As Variant
        ComputerHotFix      As Variant
        ComputerName        As Variant
        DynamicSiteName     As Variant
        FADT                As Variant
        SystemBiosDate      As Variant
        ProcessorNameString As Variant
    End Type
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''
       
    Private goReg           As Variant      'GLOBAL CONNECTION TO WMI/REGISTRY
   
   
   
    Sub ExportMyRegistryToTextFile()
   
        Dim sFileName As String
        Dim iFF As Integer
        Dim ipRange As New Collection
       
        GetIPRange InputBox("Start IP"), InputBox("End IP"), ipRange
                                            'GET ALL IPs IN RANGE
       
        ReDim xrRange(1 To ipRange.Count) As ExpReg
                                            'ARRAY TO HOLD REGISTRY FOR ALL IPs IN RANGE
       
        For i = 1 To ipRange.Count
       
            xrRange(i) = GetMyRegistry(ipRange.Item(i))
                                            'FOR EACH IP IN RANGE, GET REGISTRY DETAILS
           
        Next i
       
        sFileName = InputBox("Enter export filename")
                                            'GET FILENAME FROM USER
       
        iFF = FreeFile
       
        Open sFileName For Output As #iFF   'OPEN FILE FOR WRITING
       
            Print #iFF, "IP" & vbTab & "ConnectOK" & vbTab & "DefaultUser" & vbTab & _
                 "CachePrimaryDomain" & vbTab & "Build" & vbTab & "BuildType" & vbTab & _
                 "Country" & vbTab & "GHOSTBuild" & vbTab & "ComputerName" & vbTab & _
                 "DynamicSiteName" & vbTab & "FADT" & vbTab & "SystemBiosDate" & vbTab & _
                 "ProcessorNameString" & vbTab & "Hotfixes..."
                                            'WRITE HEADERS
                 
            For i = 1 To ipRange.Count
           
                Print #iFF, ipRange.Item(i) & vbTab & _
                    xrRange(i).ConnectOK & vbTab & xrRange(i).DefaultUser & vbTab & _
                    xrRange(i).CachePrimaryDomain & vbTab & xrRange(i).Build & vbTab & _
                    xrRange(i).BuildType & vbTab & xrRange(i).Country & vbTab & _
                    xrRange(i).GHOSTBuild & vbTab & xrRange(i).ComputerName & vbTab & _
                    xrRange(i).DynamicSiteName & vbTab & xrRange(i).FADT & vbTab & _
                    xrRange(i).SystemBiosDate & vbTab & xrRange(i).ProcessorNameString & _
                    vbTab;                  'WRITE ALL FIXED-SIZED DATA
                   
                If IsArray(xrRange(i).ComputerHotFix) Then
                                            'IF COMPUTERHOTFIX CONTAINS MORE THAN ONE...
                    For Each j In xrRange(i).ComputerHotFix
                        Print #iFF, j & vbTab;
                    Next j                  'WRITE EACH HOTFIX TO FILE
                Else                        'OTHERWISE
                    Print #iFF, xrRange(i).ComputerHotFix;
                                            'WRITE SINGLE ITEM OR ERROR MESSAGE
                End If
               
                Print #iFF, ""              'NEW LINE
               
            Next i
               
        Close #1                            'SAVE AND CLOSE FILE
   
    End Sub
   
   
   
    Sub GetIPRange(ByVal strStartIP As String, ByVal strEndIP As String, ByRef IPs As Collection)
       
        'USAGE: GetIPRange "aaa.bbb.ccc.ddd", "aaa.bbb.ccc.ddd", PointerToCollection
        'END IP MUST BE GREATER THAN START IP -- PROGRAM DOES NOT CHECK
       
        Dim ipCurrent As Variant
       
        Do Until IPs.Count = 0
            IPs.Remove 0
        Loop
       
        ipStart = Split(strStartIP, ".")
        ipEnd = Split(strEndIP, ".")
       
        ''''''BASIC VALIDITY CHECK FOR IP ADDRESSES''''''''''''''''''''''''''''''''''''
        For i = 0 To 2
            If ipStart(i) > 255 Or ipStart(i) < 0 Then Err.Raise 255, , "Invalid Start IP"
            If ipEnd(i) > 255 Or ipStart(i) < 0 Then Err.Raise 255, , "Invalid End IP"
        Next i
        If ipStart(3) > 254 Or ipStart(i) < 1 Then Err.Raise 255, , "Invalid Start IP"
        If ipEnd(3) > 254 Or ipStart(i) < 1 Then Err.Raise 255, , "Invalid End IP"
        '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
       
        ipCurrent = ipStart
       
        IPs.Add CStr(ipCurrent(0) & "." & _
                 ipCurrent(1) & "." & _
                 ipCurrent(2) & "." & _
                 ipCurrent(3))              'ADD START IP TO COLLECTION
       
        Do Until ipCurrent(0) = ipEnd(0) And ipCurrent(1) = ipEnd(1) And _
                 ipCurrent(2) = ipEnd(2) And ipCurrent(3) = ipEnd(3)
                                            'REPEAT UNTIL END IP IS REACHED
           
            ''''''ADD ONE TO IP ADDRESS''''''''''''''''''''''''''''''''''''''''''''''''
            ipCurrent(3) = ipCurrent(3) + 1
            If ipCurrent(3) = 255 Then
                ipCurrent(3) = 1
                ipCurrent(2) = ipCurrent(2) + 1
                If ipCurrent(2) = 256 Then
                    ipCurrent(2) = 0
                    ipCurrent(1) = ipCurrent(1) + 1
                    If ipCurrent(1) = 256 Then
                        ipCurrent(1) = 0
                        ipCurrent(0) = ipCurrent(0) + 1
                    End If
                End If
            End If
            '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
           
            IPs.Add CStr(ipCurrent(0) & "." & _
                 ipCurrent(1) & "." & _
                 ipCurrent(2) & "." & _
                 ipCurrent(3))              'ADD CURRENT IP TO COLLECTION
                 
        Loop
       
    End Sub
   
   
   
    Private Function GetMyRegistry(Optional ByVal strComputer As String = ".") As ExpReg
       
        On Error GoTo GetMyRegistry_Error:
       
        'GET THE FOLLOWING REGISTRY VALUES AND STORE THEN IN A VARIANT ARRAY:
            '*HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName
            '*HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\CachePrimaryDomain
            '*HKEY_LOCAL_MACHINE\SOFTWARE\MYCOMPANY\Computer\Build
            '*HKEY_LOCAL_MACHINE\SOFTWARE\MYCOMPANY\Computer\BuildType
            '*HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\ComputerName\ComputerName\ComputerName
            '*HKEY_LOCAL_MACHINE\SYSTEM\ControlSet\Services\Netlogon\Parameters\DynamicSiteName
            '*HKEY_LOCAL_MACHINE\SOFTWARE\MYCOMPANY\Country
            '*HKEY_LOCAL_MACHINE\SOFTWARE\MYCOMPANY\SubRegionGHOSTBuild
            '*HKEY_LOCAL_MACHINE\SOFTWARE\MYCOMPANY\Computer\HotFix  (needs to read all the names of sub keys)
            '*HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\DELL__\  (read the name of next key)
            '*HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\SystemBiosDate
            '*HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0\ProcessorNameString
           
        Dim XR          As ExpReg
        Dim tmpFADT     As Variant
        Dim sFADTPath   As String
        Dim tmpFADTPath As Variant
       
        Set goReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" _
            & strComputer & "\root\default:StdRegProv")
                                                'CONNECT TO WMI/REGISTRY FOR GIVEN COMPUTER
           
        ''''''GET REQUIRED REGISTRY ENTRIES'''''''''''''''''''''''''''''''''''''''''''''
        XR.ConnectOK = True
   
        XR.DefaultUser = GetRegistryValue(HKEY_LOCAL_MACHINE, _
                            "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", _
                            "DefaultUserName")
                           
        XR.CachePrimaryDomain = GetRegistryValue(HKEY_LOCAL_MACHINE, _
                            "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", _
                            "CachePrimaryDomain")
                           
        XR.Build = GetRegistryValue(HKEY_LOCAL_MACHINE, "SOFTWARE\MYCOMPANY\Computer", _
                            "Build")
       
        XR.BuildType = GetRegistryValue(HKEY_LOCAL_MACHINE, "SOFTWARE\MYCOMPANY\Computer", _
                            "BuildType")
                           
        XR.Country = GetRegistryValue(HKEY_LOCAL_MACHINE, "SOFTWARE\MYCOMPANY", _
                            "Country")
       
        XR.GHOSTBuild = GetRegistryValue(HKEY_LOCAL_MACHINE, "SOFTWARE\MYCOMPANY", _
                            "SubRegionGHOSTBuild")
                           
        XR.SystemBiosDate = GetRegistryValue(HKEY_LOCAL_MACHINE, "HARDWARE\DESCRIPTION\System", _
                            "SystemBiosDate")
       
        XR.ProcessorNameString = GetRegistryValue(HKEY_LOCAL_MACHINE, _
                            "HARDWARE\DESCRIPTION\System\CentralProcessor\0", _
                            "ProcessorNameString")
                           
        XR.ComputerName = GetRegistryValue(HKEY_LOCAL_MACHINE, _
                            "SYSTEM\ControlSet001\Control\ComputerName\ComputerName", _
                            "ComputerName")
                           
        XR.DynamicSiteName = GetRegistryValue(HKEY_LOCAL_MACHINE, _
                            "SYSTEM\ControlSet\Services\Netlogon\Parameters", _
                            "DynamicSiteName")
       
        goReg.EnumKey HKEY_LOCAL_MACHINE, "SOFTWARE\MYCOMPANY\Computer\HotFix", _
                            XR.ComputerHotFix
                           
        If IsNull(XR.ComputerHotFix) Then       'CHECK COMPUTERHOTFIX FOR ERROR
           XR.ComputerHotFix = "##ERROR: Hotfix subkey is empty/non-existant"
        End If
       
        sFADTPath = "HARDWARE\ACPI\FADT"
        tmpFADTPath = Empty
        Do Until IsNull(tmpFADT) = True
            sFADTPath = sFADTPath & tmpFADTPath
            goReg.EnumKey HKEY_LOCAL_MACHINE, sFADTPath, tmpFADT
            If IsNull(tmpFADT) = False Then tmpFADTPath = "\" & tmpFADT(0)
        Loop                                    'FULLY EXTEND FIRST FADT KEY BRANCH
        XR.FADT = sFADTPath
       
        GetMyRegistry = XR
       
        Exit Function
       
       
    GetMyRegistry_Error:
   
        XR.ConnectOK = False                    'IF FALSE ON REPORT, ERROR CONNECTING
        GetMyRegistry = XR
   
    End Function
   
   
   
    Private Function GetRegistryValue(ByVal lSubtree As regSubtrees, ByVal sPath As String, _
                                      ByVal sValue As String) As Variant
       
        'GETS THE VALUE OF A KEY ENTRY, BASED ON SUBTREE, PATH AND VALUE NAME
       
        On Error GoTo GetRegistryValue_Error:
       
        Dim aValueNames   As Variant
        Dim aValueTypes   As Variant
        Dim lDataType     As regDataTypes
        Dim vResult       As Variant
       
        goReg.EnumValues lSubtree, sPath, aValueNames, aValueTypes
                                                    'ENUMERATE ALL VALUES IN PATH
       
        For i = LBound(aValueNames) To UBound(aValueNames)
                                                    'LOOP THROUGH EACH VALUE
       
            If aValueNames(i) = sValue Then         'IF THE VALUE WE'RE LOOKING FOR...
           
                lDataType = aValueTypes(i)          'GET REGISTRY DATA TYPE
                Exit For
           
            End If
           
        Next i
       
        ''''''USE APPRPRIATE EXTRACT METHOD BASED ON REGISTRY DATA TYPE''''''''''''''''
        Select Case lDataType
       
            Case REG_BINARY:    goReg.GetBinaryValue lSubtree, sPath, sValue, vResult
            Case REG_DWORD:     goReg.GetDwordValue lSubtree, sPath, sValue, vResult
            Case REG_EXPAND_SZ: goReg.GetExpandedStringValue lSubtree, sPath, sValue, vResult
            Case REG_MULTI_SZ:  goReg.GetMultiStringValue lSubtree, sPath, sValue, vResult
            Case REG_SZ:        goReg.GetStringValue lSubtree, sPath, sValue, vResult
           
        End Select
        '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
       
        GetRegistryValue = vResult
        Exit Function
   
    GetRegistryValue_Error:
   
        Select Case Err.Number
           
            Case 13:    GetRegistryValue = "##ERROR: Key/Value not found"
                        Exit Function               'PARSE TYPE MISMATCH ERROR
                     
            Case Else:  GetRegistryValue = "##ERROR: " & Err.Description
                                                    'PARSE ALL OTHERS
           
        End Select
   
    End Function

HTH

J.
0
The Ultimate Tool Kit for Technolgy Solution Provi

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy for valuable how-to assets including sample agreements, checklists, flowcharts, and more!

davesaundersnukAuthor Commented:
thanks.. there is a lot there.... please give me a bit of time to look it over.
0
jimbobmcgeeCommented:
It should all be working, you just have to meddle with the format of your output file, to suit your needs.  I have used a tab-delimeted text format, in case there are any commas in the data that is pulled in.  
0
davesaundersnukAuthor Commented:
i have run it and nothing happends... it opens form1 but nothing else... the input boxes dont appear
0
davesaundersnukAuthor Commented:
right running it as a module... seems to be working ok however

Private Function GetMyRegistry(Optional ByVal strComputer As String = ".") As ExpReg

this line give me and error of: User defined type not define

0
jimbobmcgeeCommented:
ExpReg is a defined in the Private Type statement near the top of my code.  It's a simple variant structure that is used to hold each registry entry.  You may need to make it Public instead of Private but, if everything I typed above is in your module, it shouldn't matter.

To run the program you have to set the startup process to ExportMyRegistryToTextFile(), or call this sub from within your code.  You may prefer to change all declarations from Private to Public, just to be sure...

J.
0
davesaundersnukAuthor Commented:
hi,

got this running over the weekend.. bit of tweaking but seems to be ok... I have not really had the time to study it in detail.. Asked it to check the details for 10 pc..

Fed it the IP address range... it took 20mins to return with the export to file...

very strange.. doing one pc its fast... but any more than 2 or 3 and your looking at 10's of mins..

any idear why ?


all the pc's where on a 100mb link... did not try testing people on leased line or dsl connections
0
jimbobmcgeeCommented:
It may depend on your IP range.  The population of IPs into the collection is brute-force and a bit slow.  It is entirely possible that (for a large enough range) it could take 256^4 cycles -- that's 4294967296 different Collection.Add calls.

It was the best way I could think of at the time -- seeing as I put most of my effort into the registry stuff...

J.
0
jimbobmcgeeCommented:
And connection to some PCs can take ages.  We have one server at work that took 10 minutes just to tell us that the connection failed.  Check the output file to make sure the PCs are connecting -- if not, it could be a permissions thing...

J.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
davesaundersnukAuthor Commented:
might need a bit more help on this... but will accept your reply... its the best i have had.
0
jimbobmcgeeCommented:
No problem, just ask.

Thanks for the points.

J.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic Classic

From novice to tech pro — start learning today.