Search the registry

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • PhilOfWalton
    Recognized Expert Top Contributor
    • Mar 2016
    • 1430

    Search the registry

    I am truing to search the registry to find which proofing languages are available for MS Office

    Here are what appear to be the Registry entries. The bit after the 3 dots is the Default Value. The second entry translates as Georgian.

    In addition to those languages, I have Mongolian installed, but there is no proofing available for this language


    So I'm guessing that the only fixed bits we know are
    "HKEY_LOCAL_MAC HINE\SOFTWARE\M icrosoft\Office \ "
    and
    "Installed Packages"
    "Microsoft Office Proofing Tools"
    and a language either in brackets or after a dash

    I have no idea if the registry can be searched on so little information as I have a feeling that you need to supply the complete key, which obviously will vary depending on the version of Office.

    Is it possible?

    Thanks

    Phil
  • NeoPa
    Recognized Expert Moderator MVP
    • Oct 2006
    • 32656

    #2
    Hi Phil.

    Exactly what you need to do regarding this particular part of the Registry I can't really help with. However, I do have some code that reads the Registry.

    Now I look at it, the code I was thinking of was actually code to traverse through the local domain's Active Directory. Not so much use :-(

    Nevertheless, having almost promised you something I've looked at what I have and will see if I can knock something up for you that traverses through the keys from a specified start point and lists all the key and value names within. That should be enough to build on to include your own particular logic.

    Comment

    • PhilOfWalton
      Recognized Expert Top Contributor
      • Mar 2016
      • 1430

      #3
      That sounds brilliant. I look forward to seeing what you come up with.

      Please don't go to too much trouble though as time is valuable to you.

      Phil

      Comment

      • NeoPa
        Recognized Expert Moderator MVP
        • Oct 2006
        • 32656

        #4
        Hi Phil.

        This took a while and a number of failures and complete crashes of Excel before I could get it right. I chose to use Excel as I didn't want to risk crashing or corrupting any existing databases and new spreadsheets are much easier to get started with ;-)

        It returns a list of all Subkeys of a specified Registry Key. The returned value is a string including all the values separated by "\" characters. Why those? Because they can hardly be used within a name as they're used for specifying the structure itself of a Key.

        You can be sure I'll be adding this to my existing modOS modules in all of my projects from now on.
        Code:
        Option Explicit
        
        'Windows API Variable Prefixes
        'cb = Count of Bytes (32-bit)
        'w  = Word (16-bit)
        'dw = Double Word (32-bit)
        'lp = Long Pointer (32-bit)
        'b  = Boolean (32-bit)
        'h  = Handle (32-bit)
        'ul = Unsigned Long (32-bit)
        
        Public Const conHKCR = &H80000000
        Public Const conHKCU = &H80000001
        Public Const conHKLM = &H80000002
        Public Const conHKU = &H80000003
        Public Const conStandardRightsAll = &H1F0000
        Public Const conReadControl = &H20000
        Public Const conStandardRightsRead = (conReadControl)
        Public Const conRegSz = 1
        Public Const conOK = 0&
        Public Const conKeyQueryValue = &H1
        Public Const conKeySetValue = &H2
        Public Const conKeyCreateLink = &H20
        Public Const conKeyCreateSubKey = &H4
        Public Const conKeyEnumerateSubKeys = &H8
        Public Const conKeyNotify = &H10
        Public Const conSynchronise = &H100000
        Public Const conRegOptionNonVolatile = 0
        Public Const conKeyAllAccess = ((conStandardRightsAll _
                                      Or conKeyQueryValue _
                                      Or conKeyCreateSubKey _
                                      Or conKeyEnumerateSubKeys _
                                      Or conKeyNotify _
                                      Or conKeyCreateLink) _
                                    And (Not conSynchronise))
        Public Const conKeyRead = ((conReadControl _
                                 Or conKeyQueryValue _
                                 Or conKeyEnumerateSubKeys _
                                 Or conKeyNotify) _
                               And (Not conSynchronise))
        
        Private Type typFileTime
            lngLoDT As Long
            lngHiDT As Long
        End Type
        
        Private Declare Function RegOpenKeyEx Lib "advapi32.dll" _
            Alias "RegOpenKeyExA" (ByVal hKey As Long, _
                                   ByVal lpSubKey As String, _
                                   ByVal ulOptions As Long, _
                                   ByVal samDesired As Long, _
                                   phkResult As Long) As Long
        Private Declare Function RegCloseKey Lib "advapi32.dll" _
                                     (ByVal hKey As Long) As Long
        Private Declare Function RegQueryValueExStr Lib "advapi32.dll" _
            Alias "RegQueryValueExA" (ByVal hKey As Long, _
                                      ByVal lpValueName As String, _
                                      ByVal lpReserved As Long, _
                                      lpType As Long, _
                                      ByVal lpData As String, _
                                      lpcbData As Long) As Long
        Private Declare Function RegEnumKeyEx Lib "advapi32.dll" _
            Alias "RegEnumKeyExA" (ByVal hKey As Long, _
                                   ByVal dwIndex As Long, _
                                   ByVal lpName As String, _
                                   ByRef lpcName As Long, _
                                   ByVal lpReserved As Long, _
                                   ByVal lpClass As String, _
                                   ByRef lpcClass As Long, _
                                   ByRef lpftLastWriteTime As typFileTime) As Long
        
        Public Function RegEnum(ByVal lngHive As Long, ByVal strKey As String) As String
            Dim strName As String, strClass As String, strList As String
            Dim lngRet As Long, lngName As Long, lngClass As Long, lngHKey As Long
            Dim lngType As Long, lngIdx As Long
            Dim ftLastWrite As typFileTime
        
            RegEnum = ""
            strKey = strKey & Chr(0)
            lngRet = RegOpenKeyEx(lngHive, strKey, 0, conKeyRead, lngHKey)
            If lngRet <> conOK Then Exit Function
            'Create buffer to store value
            strName = Space(255)
            strClass = Space(255)
            Do While lngRet = 0
                lngName = 255
                lngClass = 255
                lngRet = RegEnumKeyEx(hKey:=lngHKey _
                                    , dwIndex:=lngIdx _
                                    , lpName:=strName _
                                    , lpcName:=lngName _
                                    , lpReserved:=ByVal 0& _
                                    , lpClass:=strClass _
                                    , lpcClass:=lngClass _
                                    , lpftLastWriteTime:=ftLastWrite)
                If lngName < 255 _
                And lngClass < 255 Then _
                    strList = strList & "\" & Left(strName, lngName)
                lngIdx = lngIdx + 1
            Loop
            'Close key
            Call RegCloseKey(lngHKey)
            RegEnum = Mid(strList, 2)
        End Function
        
        Public Function RegRead(ByVal lngHive As Long, _
                                ByVal strKey As String, _
                                ByVal strValue As String) As Variant
            Dim intIdx As Integer
            Dim strWork As String
            Dim lngRet As Long, cbLen As Long, lngHKey As Long, lngType As Long
        
            RegRead = Null
            strKey = strKey & Chr(0)
            lngRet = RegOpenKeyEx(lngHive, strKey, 0, conKeyRead, lngHKey)
            If lngRet = conOK Then
                'Create buffer to store value
                strWork = Space(255)
                cbLen = 255
                lngRet = RegQueryValueExStr(lngHKey, _
                                            strValue, _
                                            0&, _
                                            lngType, _
                                            strWork, _
                                            cbLen)
                RegRead = Left(strWork, cbLen - 1)
                If Len(RegRead) = 254 Then RegRead = Null
                'Close key
                Call RegCloseKey(lngHKey)
            End If
        End Function

        Comment

        • PhilOfWalton
          Recognized Expert Top Contributor
          • Mar 2016
          • 1430

          #5
          That looks interesting, but never having heard of hives, I am as a complete loss to know what values to feed in.

          I would be very grateful for a few examples.

          Phil

          Comment

          • PhilOfWalton
            Recognized Expert Top Contributor
            • Mar 2016
            • 1430

            #6
            The text file in the earlier post gives all the information I have.
            The search routine needs to run on any computer, so I'm guessing that the beginning of the key will start with
            Code:
            Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\
            Then presumably the version of Office will appear somewhere in the string.

            Again a guess that
            Code:
            Common\InstalledPackages
            will appear somewhere and the default value we are looking for could be any of these
            Code:
            Microsoft Office Proofing Tools 2016 - English
            Microsoft Office Proofing Tools 2016 - ქართული
            Microsoft Office Proofing Tools (German) 2016
            Microsoft Office Proofing Tools (English) 2016
            Microsoft Office Proofing Tools (Russian) 2016
            So it just adds to the fun that on my PC anyway, there are 2 different output formats

            Actually, I have just looked again, and instead of finding the Default Value, the "ProductLanguag e" is consistent and what is much better ties up with the language codes I am using
            seehttps://msdn.microsoft.com/en-us/lib...ffice.12).aspx

            So we just want the value of "ProductLanguag e"

            Interestingly, the English dictionary appears to spell check French & Spanish as well, but not German.

            Thanks

            Phil

            Comment

            • NeoPa
              Recognized Expert Moderator MVP
              • Oct 2006
              • 32656

              #7
              If you've ever opened your Registry Editor (Generally RegEdit.Exe) you'll have seen that the registry, as a whole, is broken up into separate starting sections called hives. You may be familiar with their names; I've included with each, where I have one, the constant defined in the module to use for it :
              1. conHKCR(0) - HKEY_CLASSES_RO OT
              2. conHKCU(1) - HKEY_CURRENT_US ER
              3. conHKLM(2) - HKEY_LOCAL_MACH INE
              4. conHKU (3) - HKEY_USERS
              5. - HKEY_CURRENT_CO NFIG

              HKEY stands for Hive Key.

              These all start in different places; some are stored in different files entirely. As far as the Registry is concerned though, they present simply as separate Hives within it. Within each Hive is a structure of Keys. All Subkeys are also Keys. Keys hold no information per se; they only hold other Keys and Values. Values are where, in the Registry, all actual information is stored. Their position within the Hive and Key structure is obviously critical but they are the only places where actual data is found. Values come in various shapes and sizes. Zero-terminated strings; Binarys; DWORD(32-bit); QWORD(64-bit); Multi-Strings & Expandable Strings. This is important as the code provided only handles Zero-terminated String Values.

              NB. Enumerating the Keys does just that. It enumerates the Keys. Only. Values are not included in this code. You have to know which Values are expected and that they match the type we've coded for. Most simple text does, but always beware of strings being saved as Unicode as opposed to ANSI ASCII.

              In my earlier code you'll notice there are constants that can be used to represent these Hives. These are used when calling the procedure as illustrated below. I understand from your latest post that the Hive you're interested in is HKEY_LOCAL_MACH INE so we can use the constant conHKLM. I also noticed that the Key you refer to isn't even present on my machine. It goes as far as HKEY_LOCAL_MACH INE\SOFTWARE\Mi crosoft\Office\ Common but doesn't include a Key called InstalledPackag es within that. That's a problem for another day.

              So, assuming you have a machine that includes HKEY_LOCAL_MACH INE\SOFTWARE\Mi crosoft\Office\ Common\Installe dPackages, the following code will show the Subkeys within that Key. Bear in mind it won't show Values; only Keys.

              I can't tell from your post, and obviously am unable to check on my own machine, whether what you're looking for are Keys or Values. So, I'll show how to list the Keys and you can tell me how you get on with it when you try on your system.
              Code:
              Dim strVal As String
              Dim varItem As Variant
              
              strVal = "SOFTWARE\Microsoft\Office\Common\InstalledPackages")
              For Each varItem In Split(RegEnum(conHKLM, strVal), "\")
                  Debug.Print varItem
              Next varItem
              If there Key doesn't exist, or it has no Subkeys (regardless of Values), then it will simply show nothing.

              Comment

              • PhilOfWalton
                Recognized Expert Top Contributor
                • Mar 2016
                • 1430

                #8
                Thanks for the explanation, it is a little clearer now.

                Obviously you have no language packs installed hence your failure to find "InstalledPacka ges" on your machine.

                The only portion of the initial key we have in common is
                "SOFTWARE\Micro soft\Office\"
                Your Machine then goes on to "Common\" whilst my machine goes on yo
                "ClickToRun\REG ISTRY\MACHINE\S oftware\Wow6432 Node\Microsoft\ Office\16.0\Com mon\"

                However, suppose you were looking for Access\Report Formats and you wanted to find the value of "Rich Text Format" - I'm guessing we both have these in our registry, how would you do that?

                The problem being that we both have the same initial key
                "SOFTWARE\Micro soft\Office\", and we both probably have the same end Key
                "Access\Rep ort Formats"
                and both of us definitely have totally different intermediate keys.

                Thanks as ever

                Phil

                Comment

                • NeoPa
                  Recognized Expert Moderator MVP
                  • Oct 2006
                  • 32656

                  #9
                  Hi Phil.

                  Originally posted by PhilOfWalton
                  PhilOfWalton:
                  However, suppose you were looking for Access\Report Formats and you wanted to find the value of "Rich Text Format" - I'm guessing we both have these in our registry, how would you do that?
                  That really depends on whether we're talking about a value or a Value. Can you specify exactly where it's found on your machine? At least one of them.

                  Comment

                  • PhilOfWalton
                    Recognized Expert Top Contributor
                    • Mar 2016
                    • 1430

                    #10
                    Hi

                    The key is
                    "Computer\HKEY_ LOCAL_MACHINE\S OFTWARE\Microso ft\Office\Click ToRun\REGISTRY\ MACHINE\Softwar e\Wow6432Node\M icrosoft\Office \16.0\Access\Re port Formats"

                    Name: Rich Text Format

                    Type: REG_SZ

                    Data: rtf,SOA_RptToRT F,Rich Text Format,Rich Text Format (*.rtf),0

                    Cheers

                    Phil

                    Comment

                    • NeoPa
                      Recognized Expert Moderator MVP
                      • Oct 2006
                      • 32656

                      #11
                      That's a Value then, clearly. Let me see what I can do to create a routine for returning a list of Values within a specified Key.

                      Remember, terminology is critical for clarity. Without clarity we end up going off on tangents similar to the earlier work. That said - I suspect that would have been necessary at some point anyway. Now we all know that we are dealing only with Hives, Keys and Values we should be able to keep everything clear going forwards.

                      I'll see what I can find to allow us to enumerate the Values in a Key.

                      Comment

                      • PhilOfWalton
                        Recognized Expert Top Contributor
                        • Mar 2016
                        • 1430

                        #12
                        Sorry about lake of clarity. Although I have looked at the registry from time to time, and very rarely modified Value, as you can see I am a complete amateur in this field (and, judging by the number of recent questions posed, also in the subject of Access databases)

                        Incidentally, I don't understand your comment about Value & value

                        Phil

                        Comment

                        • NeoPa
                          Recognized Expert Moderator MVP
                          • Oct 2006
                          • 32656

                          #13
                          Ah. I guessed not. Let me try to clarify.
                          value - Standard word in the Enlish language which means exactly what you take it to mean.
                          Value - With a capital V in the context of the Registry, is a container called a Value that the Registry stores data within.
                          Almost all of the Values contain values.

                          It may be most easily understood by using a picture of my own Registry and saying all the items on the left are Hives, Keys and Subkeys (which are themselves also Keys), while all the items on the right are Values.
                          [IMGNOTHUMB]https://bytes.com/attachment.php? attachmentid=93 55&stc=1&d=1517 694840[/IMGNOTHUMB]
                          The Hives are those directly under Computer in the picture and everything else on the left is a Key. Keys (and Hives) are shown with a yellow folder icon.
                          The Values are the only items that can contain data as such. Some Values here are of type REG_SZ (Registry String Zero terminated) while others are REG_DWORD (Registry Double Word).

                          Just to be absolutely clear the Value called iTunesDefault has a value of 0. The Value called InstallDir has a value of "C:\Program Files\iTunes\".

                          By the way, in case it helps, and also because I want as many people as possible to be aware of it, I've just written an article (VBA to C Crossover) that explains how to work with the sort of procedures such as are found in ADVAPI32.DLL - which are designed to be used by c-type languages - even from a VB type language such as VBA.
                          Attached Files

                          Comment

                          Working...