Solved

Formatting the values returned from RegEnumValue

Posted on 2000-03-30
8
361 Views
Last Modified: 2008-03-10
I've been putting together a nice little class for reading and writing to the registry, copying or deleteing registry keys and all of their sub keys and/or values.  


My problem is that after running RegEnumValue, I'm displaying the contents of the values in a grid. This works fine for values of type string, but I'm not formatting the DWORD or BINARY return values correctly for display.  

What I'd like to do, is translate DWORD values so that they display exactly as they do in RegEdit.  So, a DWORD with a hex value of 20000, decimal value of 131072 will display as:

0x00020000 (131072)

and a BINARY value will display as:
9A 01 00 00 34 00 00 00
84 00 00 00 FC 02 00 00

and so on ....

(extra points if you can display it as:)
9A 01 00 00 34 00 00 00  ....4...
84 00 00 00 FC 02 00 00  .....u..

with the character representation on the right.

These are the two main types I need help displaying, but extra points for a more complete answer that formats all of the possible Registry value types.

Here is the kind of function I was trying to write:
(but it's not working properly)

Public Function FormatValue(vValue As Variant, nType As Long) As String
Dim Temp As String
Dim J As Long

 Select Case nType
     Case REG_DWORD
         For J = 1 To Len(vValue)
             Temp = Temp & CStr(CDec(Asc(Mid(vValue, J, 1))))
         Next J
         Temp = "0x0" & Temp & IIf(7 - Len(Temp) > 0, String(7 - Len(Temp), "0"), "")
         FormatValue = Temp
     Case REG_BINARY
         For J = 1 To Len(vValue)
             Temp = Temp & IIf(Len(CStr(Hex(Asc(Mid(vValue, J, 1))))) > 1, "", "0") & CStr(CDec(Asc(Mid(vValue, J, 1)))) & IIf(J Mod 8 = 0, vbCrLf, Space(1))
         Next J
         FormatValue = Temp
     Case Else
         FormatValue = vValue
End Select

End Function
0
Comment
Question by:mdougan
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
8 Comments
 
LVL 3

Accepted Solution

by:
Gordonp earned 200 total points
ID: 2672515
Public Function FormatValue(byData() As Byte, nType As Integer) As String

    Select Case nType
        Case REG_DWORD
            Dim dwValue As Long
            CopyMemory dwValue, byData(0), LenB(dwValue)
            FormatValue = Format(dwValue, "0x00000000") & " (" & dwValue & ")"
                       
        Case REG_SZ
            FormatValue = byData

        Case REG_BINARY
            'Coming Soon

    End Select
       
End Function

Heres the DWORD part of your question.

this assumes you copied the data into a byte array from the pointer returned by RegEnumValue.

I'll have the bit for the REG_BINARY just shortly

Gordon
0
 
LVL 3

Expert Comment

by:Gordonp
ID: 2672651
       Case REG_BINARY
            Dim sLine As String
            Dim sLine2 As String
       
            Dim I As Integer
            For I = 0 To UBound(byData)
                sLine = sLine & Format(byData(I), "00") & " "
                sLine2 = sLine2 & Chr(byData(I))
                               
                If (I Mod 8) = 0 Then
                    FormatValue = FormatValue & vbCrLf & sLine & vbTab & sLine2
                    sLine = ""
                    sLine2 = ""
                End If
            Next

Here the bit for the Binary formatting

Hope this helps

Gordon
0
 
LVL 18

Author Comment

by:mdougan
ID: 2673199
So far, this looks great, but I hadn't been copying the data to a byte array.  When I tried to do it in your routine I got a type missmatch, so, I'm not sure how to load the byte array.  

Here is the code I use in the enum function, which puts the value into a variant/string.  This type of variable works fine for the routine that copies one tree to another, but if you can suggest how to put the value into a byte array instead of a string/variant then the points are yours:

            nRet = RegEnumValue(hKey, nIndex, ValueName, nValueNameLen, ByVal 0&, nType, ByVal Value, nValueLen)
            If nRet = ERROR_SUCCESS Then
                ReDim Preserve Values(0 To 2, 0 To nStrings) As Variant
                Values(0, nStrings) = Left$(ValueName, nValueNameLen)
                Values(1, nStrings) = Left$(Value, nValueLen - 1)
                Values(2, nStrings) = nType


Or, if you can modify your routine to use a variant/string is the input parm, and then copy to a byte array in the routine, even better.
0
Salesforce Made Easy to Use

On-screen guidance at the moment of need enables you & your employees to focus on the core, you can now boost your adoption rates swiftly and simply with one easy tool.

 
LVL 18

Author Comment

by:mdougan
ID: 2684351
GordonP's answer looks good, but it only takes me half way.  I'm currently getting the value out of RegEnumValue as a variant/string.  To use GordonP's function, I'd need it to be in a byte array.  

So, I'd either need a way to put the value in a Byte Array from RegEnumValue or, better for me, to have GordonP's function accept a variant/string and then do whatever it has to do to format it for display.

I'm opening this back up since GordonP hasn't replied in a couple of days.
0
 
LVL 3

Expert Comment

by:Gordonp
ID: 2692442
Ok, I'm back.

I was on holiday.

Have you tried passing a byte array to RegEnumValue instead of a string

Other option is to convert your string

Dim byData() as byte
byData = strconv(Value,vbFromUnicode)

Hope these help

Gordon
0
 
LVL 18

Author Comment

by:mdougan
ID: 2700695
Adjusted points from 150 to 200
0
 
LVL 18

Author Comment

by:mdougan
ID: 2700696
Thanks!  I was finally able to get it to display as I wanted it to.  I did have to make a few adjustments to your original routine, so I'll post the final version below for the benefit of others that might buy this question.  

Putting the values returned from RegEnumValue into a variant/string type variable worked for me, as I created a two dimensional variant array that would hold the name of the key, the value, and the type of the key.  In all of the code for copying the values or otherwise manipulating the registry, I didn't have to do anything to the value, it was only in displaying it that I had to muck around with it.  So, I was happy to convert it to the byte array in the display routine.  Thanks for the strconv using vbFromUnicode, I don't think I ever would have figured that out on my own.

Some of the things that I had to change to get it to display the binary like RegEdit, I had to pad a line that was less than 8 characters, so that the last line's char rep would line up with the others.  I also changed certain ascii codes to "." in the char rep to match what RegEdit displays.  Also, I added the HEX function to get the hex rep of the decimal values.  This was necessary for both the DWORD and BINARY displays.  I also put in code to keep the very first line of the binary display from being prefaced by a tab.

Thanks again!

Public Function FormatValues(vValue As Variant, nType As Integer) As String
Dim sLine As String
Dim sLine2 As String
Dim i As Integer
Dim byData() As Byte
Dim sTemp As String
   
    byData = StrConv(vValue, vbFromUnicode)
                       
    Select Case nType
        Case REG_DWORD
            Dim dwValue As Long
            CopyMemory dwValue, byData(0), LenB(dwValue)
            sTemp = Hex(dwValue)
            FormatValues = "0x" & IIf(Len(sTemp) < 8, String(8 - Len(sTemp), "0"), "") & sTemp & " (" & dwValue & ")"
                         
        Case REG_SZ
            FormatValues = vValue

        Case REG_BINARY
        For i = 0 To UBound(byData)
            sTemp = Trim(Format(Hex(byData(i)), "@@"))
            sLine = sLine & IIf(Len(sTemp) < 2, "0", "") & sTemp & " "
            sLine2 = sLine2 & IIf((byData(i) < 32 Or _
                                  byData(i) = 127 Or _
                                 (byData(i) >= 129 And byData(i) <= 144) Or _
                                 (byData(i) >= 147 And byData(i) <= 159)), _
                                 ".", Chr(byData(i)))
            If ((i + 1) Mod 8) = 0 Then
                FormatValues = FormatValues & IIf(Len(FormatValues) > 0, vbCrLf, "") & sLine & vbTab & sLine2
                sLine = ""
                sLine2 = ""
            End If
        Next
        FormatValues = FormatValues & IIf(Len(FormatValues) > 0, vbCrLf, "") & sLine & IIf(Len(sLine) < 24, Space(24 - Len(sLine)), "") & vbTab & sLine2
    End Select
         
End Function
0
 
LVL 18

Author Comment

by:mdougan
ID: 2700705
Thanks again.
0

Featured Post

Enroll in June's Course of the Month

June’s Course of the Month is now available! Experts Exchange’s Premium Members, Team Accounts, and Qualified Experts have access to a complimentary course each month as part of their membership—an extra way to sharpen your skills and increase training.

Question has a verified solution.

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

There are many ways to remove duplicate entries in an SQL or Access database. Most make you temporarily insert an ID field, make a temp table and copy data back and forth, and/or are slow. Here is an easy way in VB6 using ADO to remove duplicate row…
Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…

691 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