Link to home
Start Free TrialLog in
Avatar of technotommy
technotommy

asked on

Read/Write registry values for all Windows OS with VB6

Hello.

We have some difficulty in reading and writing registry values using a VB6 project.  Target machines are all Windows based OS.  Everything was fine for us until Windows 7 came along.

What is a good API or other method that is fool-proof that you have used?

Thanks!
Avatar of Paolo Santiangeli
Paolo Santiangeli
Flag of Italy image

hi,
did you try to "Run as Administrator"?
Avatar of technotommy
technotommy

ASKER

No.  We sell a program to people to install on their own computers.  We would rather not have to instruct them to 'Run as Admin'.  I would prefer a double-click-and-go type operation.
Basically, we compile an exe with VB6.  The exe gets sold to users with XP, Vista, and 7.  The exe reads and writes reg values, and everything has been fine and quite strait forward until 7.  Now, our programs on peoples 7 machines do not read or write.  There must be a good process for doing this for all OS that is fool-proof.

thank you!
So, is the only way to successfully read/write registry keys is to use manifest files?
In the second link there are other options but i don't think they work smooth with vb6
I would be of the opinion that there is an easy way of reading and writing reg values for all OS without a manifest file.  It seems like it would be a simple/basic procedure. Are there any other solutions you know of?
If UAC is enabled you can refer to the second link which cover all options. Alernatively you can disable UAC but i dont think is a good choice.
Actually, something like this would be absolutely perfect for us:

http://www.topshareware.com/Virtual-Registry-download-66067.htm

I do not want to use this particular software, as there is no REAL company that makes it, supports it, no one to contact with questions, etc.

Something like this made by a real company that provides real support would be nice.  I have searched high and low, but haven't found.  Anyone with a comparable solution like the example above?

Thanks!
I have not checked with windows 7 and WMI but I would look into using WMI to read / write registry values
you should be able to read almost everything in the registry.  You are limited in which sections you can write.  During application installation, the user is required to have admin rights in order to alter the registry (for obvious reasons).

What registry keys are being altered by your application?
Hello Aikimark:

We are writing to HKLM and HKCU.  In both cases, we write to /software/VB and VBA settings.

This application here http://www.topshareware.com/Virtual-Registry-download-66067.htm  is a great concept, since you write to registry, but it actually doesn't go there.  No changes in the code, just simply the keys go into a file instead of the registry itself.  A better accredited company would be better, but if this is the only option we can give it a try.

In testing this morning, I have found that if the Package and Deploy program creates the key initially, then our software can modify the keys.  I am finding that our software cannot directly create the key and then modify it, so our solution might be simply to use our Package and Deploy software to execute a .bat file that runs a .reg file to initially create the keys.  Then, when the user launches our application, then the app can modify and store various variables.

I hope this makes sense.

Also, thermoduric, thank you for calming me down.  It has been a rough morning.  Didn't mean to take it out on EE.
@technotommy

1. Your observation is in line with my earlier statement.  Creating system (non-user) keys requires admin rights, which are required for all installation processes (both VB PDW and MSI).  I do this in my commercial application.

2. If you are going to do some coding, I recommend that you alter your installation process, moving the key-creation code to the setup process.  This would be preferred to a third party product that intercepts your registry calls (from what I understand from your description).

3. Welcome to the least-privileged (authentication) world.

=====
Alternatives:
* Replace registry with INI file
* Replace registry with XML file
ASKER CERTIFIED SOLUTION
Avatar of VBClassicGuy
VBClassicGuy
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
very similar to VBClassicGuy, but I use a class from vbaccelerator.com

Works fine in my XP/Vista64/ W7-64 clients but we do turnoff UAC via GPO for all boxes so that other software runs.

' Class:    cRegistry
' Author:   Steve McMahon
' Date  :   21 Feb 1997; upd Jan 2004
'
' A nice class wrapper around the registry functions
' Allows searching,deletion,modification and addition
' of Keys or Values.
'
' http://www.vbaccelerator.com/home/VB/Code/Libraries/Registry_and_Ini_Files/Complete_Registry_Control/article.asp

'The cRegistry class is an easy, self-contained way to get complete access to the Windows registry. Simple methods allow you to create, enumerate and delete keys and values in the registry, without restriction. You can even read/write binary data to the registry. To see how powerful this library is, download the demonstration Registry Editor, written entirely in VB. Its not far off RegEdit shipped with Windows (although note in my version not all the features are finished!)
Dear technotommy,

why not you try with VB default codes add-ins > Add-ins manager?
I will have a look at this and get back to you shortly.
Hello Guys:

Thanks for all your input.  What we have found is that we can successfully write any key we want with package and deploy doing the work.  Our VB6 app cannot make the keys.

So, we write some basic keys as a 'foundation', and then our VB6 app can then successfully modify the keys after-the-fact with no problem.

This is a nice process since a manifest file is not needed nor is UAC manipulation required.

So, step 1:  Create the keys with your package and deploy software (P&D runs a script that runs a .bat which runs a .reg file).

Step 2:  Use your VB app to modify the keys and put in specific values.

Voola!!  You have just created/modified keys in your desired location without manifest or UAC coding.

So, in conclusion, your VB project cannot CREATE the keys.  Use P&D to create them.  THEN, use your VB project to MODIFY keys and/or create values.

Does the above all sound correctly to all of you?  Are you able to confirm these findings?  If so, I would think that this is huge for programmers so that they don't have to make .manifest files or manipulate UAC.
It depends on the complexity and dynamic nature of the registry keys.  For instance, I create key values during setup that are based on the user's system profile (hard drive serial number and the like).  Consequently, I had to customize the installation code.
SOLUTION
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
Thank you guys for your assistance!!  My question is satisfied!!
Sorry to put a dampener on your parade, but I successfully created an application on an XP machine using VB6 which writes values to the registry and then retrieves them as well.

When I installed it on a Windows 7 (Home Premium) machine it worked perfectly!
I tried it both under administrator and as "Guest" (with no administrative rights).
I even thought the keys might be case-sensitive (they were not) so all values written and retrieved worked.

The code is along that used by VBClassicGuy and is shown below. The small application is available through the following link:

   
See if it works then you don't have to worry about any changes to anything. Just use the code as shown to save/retrieve settings

It will be interesting to see what happens. If it does not work and you are using a different version of Windows 7 then perhaps that is the reason. Please try it and let me know.

Cheers
Chris (craisin)
'Code to be placed in module "modMain.bas"
Option Explicit
Public Const HKEY_CLASSES_ROOT = &H80000000
Public Const HKEY_CURRENT_CONFIG = &H80000005
Public Const HKEY_CURRENT_USER = &H80000001
Public Const HKEY_LOCAL_MACHINE = &H80000002
Public Const HKEY_USERS = &H80000003

Public Const ERROR_SUCCESS = 0&
Public Const ERROR_FILE_NOT_FOUND = 2&          ' Registry path does not exist
Public Const ERROR_ACCESS_DENIED = 5&           ' Requested permissions not available
Public Const ERROR_INVALID_HANDLE = 6&          ' Invalid handle or top-level key
Public Const ERROR_BAD_NETPATH = 53             ' Network path not found
Public Const ERROR_INVALID_PARAMETER = 87       ' Bad parameter to a Win32 API function
Public Const ERROR_CALL_NOT_IMPLEMENTED = 120&  ' Function valid only in WinNT/2000?XP
Public Const ERROR_INSUFFICIENT_BUFFER = 122    ' Buffer too small to hold data
Public Const ERROR_BAD_PATHNAME = 161           ' Registry path does not exist
Public Const ERROR_NO_MORE_ITEMS = 259&         ' Invalid enumerated value
Public Const ERROR_BADDB = 1009                 ' Corrupted registry
Public Const ERROR_BADKEY = 1010                ' Invalid registry key
Public Const ERROR_CANTOPEN = 1011&             ' Cannot open registry key
Public Const ERROR_CANTREAD = 1012&             ' Cannot read from registry key
Public Const ERROR_CANTWRITE = 1013&            ' Cannot write to registry key
Public Const ERROR_REGISTRY_RECOVERED = 1014&   ' Recovery of part of registry successful
Public Const ERROR_REGISTRY_CORRUPT = 1015&     ' Corrupted registry
Public Const ERROR_REGISTRY_IO_FAILED = 1016&   ' Input/output operation failed
Public Const ERROR_NOT_REGISTRY_FILE = 1017&    ' Input file not in registry file format
Public Const ERROR_KEY_DELETED = 1018&          ' Key already deleted
Public Const ERROR_KEY_HAS_CHILDREN = 1020&     ' Key has subkeys & cannot be deleted

Public Const REG_SZ = 1
Public Const REG_BINARY = 3
Public Const REG_DWORD = 4

Public Const REG_CREATED_NEW_KEY = &H1          ' A new key was created
Public Const REG_OPENED_EXISTING_KEY = &H2      ' An existing key was opened

Public Const REG_OPTION_BACKUP_RESTORE = 4
Public Const REG_OPTION_NON_VOLATILE = 0
Public Const REG_OPTION_VOLATILE = 1

Public Const KEY_CREATE_LINK = &H20
Public Const KEY_CREATE_SUB_KEY = &H4
Public Const KEY_ENUMERATE_SUB_KEYS = &H8
Public Const KEY_NOTIFY = &H10
Public Const KEY_QUERY_VALUE = &H1

Public Const STANDARD_RIGHTS_ALL = &H1F0000
Public Const STANDARD_RIGHTS_READ = &H20000
Public Const STANDARD_RIGHTS_WRITE = &H20000

Public Const SYNCHRONIZE = &H100000

Public Const KEY_READ = ((STANDARD_RIGHTS_READ Or KEY_QUERY_VALUE Or KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY) And (Not SYNCHRONIZE))
Public Const KEY_SET_VALUE = &H2
Public Const KEY_WRITE = ((STANDARD_RIGHTS_WRITE Or KEY_SET_VALUE Or KEY_CREATE_SUB_KEY) And (Not SYNCHRONIZE))
Public Const KEY_EXECUTE = ((KEY_READ) And (Not SYNCHRONIZE))
Public Const KEY_ALL_ACCESS = ((STANDARD_RIGHTS_ALL Or KEY_QUERY_VALUE Or KEY_SET_VALUE Or KEY_CREATE_SUB_KEY Or KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY Or KEY_CREATE_LINK) And (Not SYNCHRONIZE))

Public Type SECURITY_ATTRIBUTES

  nLength As Long
  lpSecurityDescriptor As Long
  bInheritHandle As Long

End Type

Public Type FILETIME

  dwLowDateTime As Long
  dwHighDateTime As Long

End Type

Public 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
Public Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Public Declare Function RegCreateKeyEx _
               Lib "advapi32.dll" _
               Alias "RegCreateKeyExA" (ByVal hKey As Long, _
                                        ByVal lpSubKey As String, _
                                        ByVal Reserved As Long, _
                                        ByVal lpClass As String, _
                                        ByVal dwOptions As Long, _
                                        ByVal samDesired As Long, _
                                        lpSecurityAttributes As SECURITY_ATTRIBUTES, _
                                        phkResult As Long, _
                                        lpdwDisposition As Long) As Long
Public Declare Function RegSetValueEx _
               Lib "advapi32.dll" _
               Alias "RegSetValueExA" (ByVal hKey As Long, _
                                       ByVal lpValueName As String, _
                                       ByVal Reserved As Long, _
                                       ByVal dwType As Long, _
                                       lpData As Any, _
                                       ByVal cbData As Long) As Long
Public Declare Function RegQueryInfoKey _
               Lib "advapi32.dll" _
               Alias "RegQueryInfoKeyA" (ByVal hKey As Long, _
                                         ByVal lpClass As String, _
                                         lpcbClass As Long, _
                                         ByVal lpReserved As Long, _
                                         lpcSubKeys As Long, _
                                         lpcbMaxSubKeyLen As Long, _
                                         lpcbMaxClassLen As Long, _
                                         lpcValues As Long, _
                                         lpcbMaxValueNameLen As Long, _
                                         lpcbMaxValueLen As Long, _
                                         lpcbSecurityDescriptor As Long, _
                                         lpftLastWriteTime As FILETIME) As Long
Public Declare Function RegEnumKeyEx _
               Lib "advapi32.dll" _
               Alias "RegEnumKeyExA" (ByVal hKey As Long, _
                                      ByVal dwIndex As Long, _
                                      ByVal lpName As String, _
                                      lpcbName As Long, _
                                      ByVal lpReserved As Long, _
                                      ByVal lpClass As String, _
                                      lpcbClass As Long, _
                                      lpftLastWriteTime As FILETIME) As Long
Public Declare Function RegDeleteKey _
               Lib "advapi32.dll" _
               Alias "RegDeleteKeyA" (ByVal hKey As Long, _
                                      ByVal lpSubKey As String) As Long
Rem *** The function above will fail if the key to be deleted contains any subkeys. Use the following function in that case ***
Public Declare Function SHDeleteKey _
               Lib "shlwapi.dll" _
               Alias "SHDeleteKeyA" (ByVal hKey As Long, _
                                     ByVal pszSubKey As String) As Long

'--------------------------------------------------------------------------------
' Project    :       RegistrySaveGet
' Procedure  :       Main
' Description:       Start up module to call the form
' Parameters :       None
'--------------------------------------------------------------------------------
Private Sub Main()
  
  frmMain.Show

End Sub

Open in new window

Oops! left the link out.

The link to the application is:

    https://filedb.experts-exchange.com/incoming/ee-stuff/8045-Registry-SaveGet-Tester.zip 


'Code to be placed in frmMain.frm (form)
Option Explicit

'--------------------------------------------------------------------------------
' Project    :       RegistrySaveGet
' Procedure  :       cmdGetSetting_Click
' Description:       Click the Get Setting button to retrieve key values from Registry
'
' Parameters :       None
'--------------------------------------------------------------------------------
Private Sub cmdGetSetting_Click()
  Dim lResult   As Long
  Dim retVal    As Long
  Dim hTopKey   As Long, hKey As Long, lDisposition As Long
  Dim sRegPath  As String
  Dim sa        As SECURITY_ATTRIBUTES
  Dim bContinue As Boolean
  Dim x         As Integer
  bContinue = True

  For x = 0 To 2

    If Len(Me.txtGet(x).Text) = 0 Then
      Me.txtGet(x).SetFocus
      bContinue = False
      Beep
      Exit For

    End If

  Next

  If bContinue Then
    hTopKey = HKEY_CURRENT_USER
    sRegPath = Me.txtGet(0).Text
    sa.nLength = Len(sa)
    sa.bInheritHandle = CLng(True)
   
    lResult = RegCreateKeyEx(hTopKey, sRegPath, 0, vbNullString, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, sa, hKey, lDisposition)
  
    Me.lblGet.Caption = GetSetting(Me.txtGet(0), Me.txtGet(1).Text, Me.txtGet(2).Text, "*** Not Found ***")

  End If

  Me.txtSection(0).SetFocus

End Sub

'--------------------------------------------------------------------------------
' Project    :       RegistrySaveGet
' Procedure  :       cmdSaveSetting_Click
' Description:       Click Savesettings button to store key values in Registry
' Parameters :       None
'--------------------------------------------------------------------------------
Private Sub cmdSaveSetting_Click()
  Dim lResult  As Long
  Dim retVal   As Long
  Dim hTopKey  As Long, hKey As Long, lDisposition As Long
  Dim sRegPath As String
  Dim sa       As SECURITY_ATTRIBUTES
  Dim x        As Integer
   
  hTopKey = HKEY_CURRENT_USER
  sRegPath = Me.txtSection(0).Text
      
  sa.nLength = Len(sa)
  sa.bInheritHandle = CLng(True)
   
  lResult = RegCreateKeyEx(hTopKey, sRegPath, 0, vbNullString, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, sa, hKey, lDisposition)
   
  Call SaveSetting(Me.txtSection(0), Me.txtSection(1).Text, Me.txtSection(2).Text, Me.txtSection(3).Text)

  If GetSetting(Me.txtSection(0), Me.txtSection(1).Text, Me.txtSection(2).Text) = Me.txtSection(3).Text Then
    MsgBox "Setting Saved"
    For x = 0 To 2
      Me.txtGet(x).Text = Me.txtSection(x).Text
    Next
    Me.lblGet.Caption = ""
  Else
    Rem *** Failure ***
    MsgBox "Error Saving Values!"
  End If
  'set focus back on "GetSetting" Button ready to test if values were stored
  Me.cmdGetSetting.SetFocus
End Sub

Private Sub Form_Load()

End Sub

'--------------------------------------------------------------------------------
' Project    :       RegistrySaveGet
' Procedure  :       mnuClearAll_Click
' Description:       Clear all values from fields on Form
' Parameters :       None
'--------------------------------------------------------------------------------
Private Sub mnuClearAll_Click()
  Dim x As Integer
  Me.lblGet.Caption = ""

  For x = 0 To 2
    Me.txtGet(x).Text = ""
    Me.txtSection(x) = ""
  Next
  Me.txtSection(3).Text = ""
  Me.txtSection(0).SetFocus

End Sub

'--------------------------------------------------------------------------------
' Project    :       RegistrySaveGet
' Procedure  :       txtSection_Change
' Description:       Any change to the keys to be saved will clear "get" fields
'                    (keeping input form clear of previous values from "get")
' Parameters :       Index (Integer)
'--------------------------------------------------------------------------------
Private Sub txtSection_Change(Index As Integer)
  Dim x As Integer

  For x = 0 To 2
    Me.txtGet(x).Text = ""
  Next
  Me.lblGet.Caption = ""

End Sub

Open in new window

Very nice.....I will give it a try and test on a Vista and 7 machine.