Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Read/Write/Modify a Registry Key

Status
Not open for further replies.

dsi

Programmer
Mar 13, 2000
964
US
I want to change the file association for VBS files so that they are opened with Notepad.exe rather than WScript.exe. A user decided to run one of these files that turned out to be a virus, wiping out his laptop. I know how to do this manually but would like to incorporate a startup procedure to continually reset its association, in case a future program installation decides to correct the key.

regpic.jpg


Here is what I need to do:
1. If this key exists, I need to read and possibly modify its current value.
2. If it does not exist, I need to create it and set its value.

I used the FAQ from MikeLacey ( faq222-92 ) to get started, but ran into troubles.
I used this code to call the QueryValue function from the FAQ:
Code:
Sub Main()
    Dim sKey As String
    Dim sValue As String
    Dim vSetting As Variant
    
    'Call QueryValue function - read current Key value
    sKey = "VBSFile\Shell\Open\Command"
    sValue = "(Default)"
    vSetting = QueryValue(HKEY_CLASSES_ROOT, sKey, sValue)
    
    Debug.Print "Current Setting is " & vSetting
    
End Sub

'(Functions from FAQ)
Public Function QueryValue(ByVal lpParentKey As Long, sKeyName As String, sValueName As String) As Variant
    Dim lRetVal As Long 'result of the API functions
    Dim hKey As Long 'handle of opened key
    Dim vValue As Variant 'setting of queried value
    ' open the key
    lRetVal = RegOpenKeyEx(lpParentKey, sKeyName, 0, KEY_ALL_ACCESS, hKey)
    ' get the value
    lRetVal = QueryValueEx(hKey, sValueName, vValue)
    ' close the key
    RegCloseKey (hKey)
    QueryValue = vValue
End Function

Private Function QueryValueEx(ByVal lhKey As Long, ByVal szValueName As String, vValue As Variant) As Long
    Dim cch As Long
    Dim lrc As Long
    Dim lType As Long
    Dim lValue As Long
    Dim sValue As String

    On Error GoTo QueryValueExError

    ' Determine the size and type of data to be read
    lrc = RegQueryValueExNULL(lhKey, szValueName, 0&, lType, 0&, cch)

'    If lrc <> ERROR_NONE Then Error 5 (error handling procedure in FAQ)
    If lrc <> ERROR_NONE Then
        Debug.Print &quot;Error No: &quot; &amp; CStr(lrc)
'******* Here is where I get Error lrc = 6 - ERROR_OUTOFMEMORY ******
        Error 5
    End If
    
    Select Case lType
        ' For strings
        Case REG_SZ:
            sValue = String(cch, 0)
            lrc = RegQueryValueExString(lhKey, szValueName, 0&amp;, lType, sValue, cch)
            If lrc = ERROR_NONE Then
                If Mid(sValue, cch, 1) = Chr(0) Then
                vValue = Left$(sValue, cch - 1) ' get rid of trailing AsciiZ
            Else
                vValue = Left$(sValue, cch)
            End If
            Else
                vValue = Empty
            End If
            ' For DWORDS
        Case REG_DWORD:
            lrc = RegQueryValueExLong(lhKey, szValueName, 0&amp;, lType, lValue, cch)
            If lrc = ERROR_NONE Then vValue = lValue
        Case Else
            'all other data types not supported
            lrc = -1
    End Select

QueryValueExExit:
QueryValueEx = lrc

Exit Function

QueryValueExError:
    Resume QueryValueExExit ' Hmmmm
End Function
I get ERROR_OUTOFMEMORY in the QueryValueEX function, where lrc = 6.

Can anyone help me? I could sure use it, and, of course, would greatly appreciate it.
 
Sorry, as complete as your post may be, I can't determine if you are passing all of the &quot;proper&quot; (I think that's what Mike Lacey would say) parameters to RegQueryValueExNULL. In the QueryValueEX function, for instance... it's hard to say which data type szValueName might be. :)

BTW, I admire the effort and hope you catch your mistake. Few programmers dare to venture into the registry. It isn't for the faint-at-heart.
VCA.gif

Alt255@Vorpalcom.Intranets.com

&quot;What this country needs is more free speech worth listening to.&quot;[tt]
Hansell B. Duckett[/tt]​
 
dsi,

THe FAQ is basically taken from MSDN help, which you can view on line at
I have just tried the above code and I got Error 2, which means bad key - ie I do not have that entry in my registry - but I did not get any memory errors. This is the exact code that I ran:

Option Explicit

'API Function and Constant Declarations
'--------------------------------------


'***Declare the value data types
Global Const REG_SZ As Long = 1 '***Registry string
Global Const REG_DWORD As Long = 4 '***Registry number (32-bit number)

'***Declare the keys that should exist.
'***Typically applications will put information under HKEY_CURRENT_USER
Global Const HKEY_CLASSES_ROOT = &amp;H80000000
Global Const HKEY_CURRENT_USER = &amp;H80000001
Global Const HKEY_LOCAL_MACHINE = &amp;H80000002
Global Const HKEY_USERS = &amp;H80000003

'***Errors
Global Const ERROR_NONE = 0
Global Const ERROR_BADDB = 1
Global Const ERROR_BADKEY = 2
Global Const ERROR_CANTOPEN = 3
Global Const ERROR_CANTREAD = 4
Global Const ERROR_CANTWRITE = 5
Global Const ERROR_OUTOFMEMORY = 6
Global Const ERROR_INVALID_PARAMETER = 7
Global Const ERROR_ACCESS_DENIED = 8
Global Const ERROR_INVALID_PARAMETERS = 87
Global Const ERROR_NO_MORE_ITEMS = 259

'***Gives all users full access to the key
Global Const KEY_ALL_ACCESS = &amp;H3F

'***Creates a key that is persistent
Global Const REG_OPTION_NON_VOLATILE = 0

Global gstrAppVersion As String

'***Registry API declarations
Declare Function RegCloseKey Lib &quot;advapi32.dll&quot; ( _
ByVal hKey As Long _
) As Long

Declare Function RegCreateKeyEx Lib &quot;advapi32.dll&quot; Alias &quot;RegCreateKeyExA&quot; ( _
ByVal hKey As Long, _
ByVal lpSubKey As String, _
ByVal Reserved As Long, _
ByVal lpClass As String, _
ByVal dwOptions As Long, _
ByVal samDesired As Long, _
ByVal lpSecurityAttributes As Long, _
phkResult As Long, _
lpdwDisposition As Long _
) As Long

Declare Function RegOpenKeyEx Lib &quot;advapi32.dll&quot; Alias &quot;RegOpenKeyExA&quot; ( _
ByVal hKey As Long, _
ByVal lpSubKey As String, _
ByVal ulOptions As Long, _
ByVal samDesired As Long, _
phkResult As Long _
) As Long

Declare Function RegQueryValueExString Lib &quot;advapi32.dll&quot; Alias &quot;RegQueryValueExA&quot; ( _
ByVal hKey As Long, _
ByVal lpValueName As String, _
ByVal lpReserved As Long, _
lpType As Long, _
ByVal lpData As String, _
lpcbData As Long _
) As Long

Declare Function RegQueryValueExLong Lib &quot;advapi32.dll&quot; Alias _
&quot;RegQueryValueExA&quot; (ByVal hKey As Long, ByVal lpValueName As _
String, ByVal lpReserved As Long, lpType As Long, lpData As _
Long, lpcbData As Long) As Long

Declare Function RegQueryValueExNULL Lib &quot;advapi32.dll&quot; Alias _
&quot;RegQueryValueExA&quot; (ByVal hKey As Long, ByVal lpValueName As _
String, ByVal lpReserved As Long, lpType As Long, ByVal lpData _
As Long, lpcbData As Long) As Long

Declare Function RegSetValueExString Lib &quot;advapi32.dll&quot; Alias _
&quot;RegSetValueExA&quot; (ByVal hKey As Long, ByVal lpValueName As String, _
ByVal Reserved As Long, ByVal dwType As Long, ByVal lpValue As _
String, ByVal cbData As Long) As Long

Declare Function RegSetValueExLong Lib &quot;advapi32.dll&quot; Alias _
&quot;RegSetValueExA&quot; (ByVal hKey As Long, ByVal lpValueName As String, _
ByVal Reserved As Long, ByVal dwType As Long, lpValue As Long, _
ByVal cbData As Long) As Long

Sub Main()
Dim sKey As String
Dim sValue As String
Dim vSetting As Variant

'Call QueryValue function - read current Key value
sKey = &quot;VBSFile\Shell\Open\Command&quot;
sValue = &quot;(Default)&quot;
vSetting = QueryValue(HKEY_CLASSES_ROOT, sKey, sValue)

Debug.Print &quot;Current Setting is &quot; &amp; vSetting

End Sub

'(Functions from FAQ)
Public Function QueryValue(ByVal lpParentKey As Long, sKeyName As String, sValueName As String) As Variant
Dim lRetVal As Long 'result of the API functions
Dim hKey As Long 'handle of opened key
Dim vValue As Variant 'setting of queried value
' open the key
lRetVal = RegOpenKeyEx(lpParentKey, sKeyName, 0, KEY_ALL_ACCESS, hKey)
' get the value
lRetVal = QueryValueEx(hKey, sValueName, vValue)
' close the key
RegCloseKey (hKey)
QueryValue = vValue
End Function

Private Function QueryValueEx(ByVal lhKey As Long, ByVal szValueName As String, vValue As Variant) As Long
Dim cch As Long
Dim lrc As Long
Dim lType As Long
Dim lValue As Long
Dim sValue As String

On Error GoTo QueryValueExError

' Determine the size and type of data to be read
lrc = RegQueryValueExNULL(lhKey, szValueName, 0&amp;, lType, 0&amp;, cch)

' If lrc <> ERROR_NONE Then Error 5 (error handling procedure in FAQ)
If lrc <> ERROR_NONE Then
Debug.Print &quot;Error No: &quot; &amp; CStr(lrc)
'******* Here is where I get Error lrc = 6 - ERROR_OUTOFMEMORY ******
Error 5
End If

Select Case lType
' For strings
Case REG_SZ:
sValue = String(cch, 0)
lrc = RegQueryValueExString(lhKey, szValueName, 0&amp;, lType, sValue, cch)
If lrc = ERROR_NONE Then
If Mid(sValue, cch, 1) = Chr(0) Then
vValue = Left$(sValue, cch - 1) ' get rid of trailing AsciiZ
Else
vValue = Left$(sValue, cch)
End If
Else
vValue = Empty
End If
' For DWORDS
Case REG_DWORD:
lrc = RegQueryValueExLong(lhKey, szValueName, 0&amp;, lType, lValue, cch)
If lrc = ERROR_NONE Then vValue = lValue
Case Else
'all other data types not supported
lrc = -1
End Select

QueryValueExExit:
QueryValueEx = lrc

Exit Function

QueryValueExError:
Resume QueryValueExExit ' Hmmmm
End Function

Simon
 
Simon: I appreaciate the effort!

Unfortunately, I get the same error with that procedure. I think the problem lies in the fact that the value is neither a string nor a number. The value for this key contains quotation marks for the line item arguments. It seems at though the above procedures can not handle this type of entry. The problem may also lie in the fact that this is a (Default) key. This is so easy to change manually, there has to be a way to do it programmatically. X-)

While you may not have this key registered, it is similar to more prevalent keys such as GIFFile.
 
Replace Sub Main with this:

Sub Main()
Dim sKey As String
Dim sValue As String
Dim vSetting As Variant

'Call QueryValue function - read current Key value
' sKey = &quot;GIFFile\Shell\Open\Command&quot;
sKey = &quot;Control Panel\Colors&quot;
' sValue = &quot;(Default)&quot;
sValue = &quot;InfoWindow&quot;
' vSetting = QueryValue(HKEY_CLASSES_ROOT, sKey, sValue)
vSetting = QueryValue(HKEY_CURRENT_USER, sKey, sValue)

Debug.Print &quot;Current Setting is &quot; &amp; vSetting

End Sub

and see if it works. It did for me. This was the first value I found (with random looking) that did not use a (Default) entry.
Simon
 
Yup! That one works fine.

Current Setting is 255 255 225

I have a feeling that I need a different API call for this type of regisrty entry. I will keep poking around and post the solution, if and when I find it.

Thanks again!
 
Not a VB guy, so I cant comment on the code. But I can offer you an alternative.

See the following KB article:

Saving and Restoring Keys

You distribute a .reg file and then import it whenever your app loads.
The code method is the way to go, but this offers you an alternative in the interim until you get the code working. Jon Hawkins
jonscott8@yahoo.com

The World Is Headed For Mutiny,
When All We Want Is Unity. - Creed
 
dsi,

Did you also try the one that was commented out in Sub Main in my last post??
Although that registry entry exists in my registry, I still got error 2 - bad key - when I tried it. On the face of it, there is nothing much different to the two cases. It may well be - as you guessed before - something to do with the (Default) reg key entry - but I am guessing also????
Simon
 
Simon: I get the same error message you did on that example.

I think that I found the solution. Several of my applications produce a .chk file. When I opened it on my machine, I chose to &quot;Always use this applicaiton to open this type of file&quot;.

I am able to get the value of this key, without any errors.
Code:
    sKey = &quot;chk_auto_file\shell\open\command&quot;
    sValue = &quot;&quot;
    vSetting = QueryValue(HKEY_CLASSES_ROOT, sKey, sValue)
Result:    
    Current Setting is C:\WINNT\System32\NOTEPAD.EXE %1
I had to specify an empty string to retrieve the (Default) value. This value is slightly different from the one in the VBSFIle key, which contians quotation marks and an additional argument.

C:\WINNT\System32\WScript.exe &quot;%1&quot; %*

I think that it is failing because the functions only get string and double values. Unfortunately, even if I change the VBSFile key so it is identical to that of the .chk file, I still get errors. I will continue to work on it and update this thread with my results.

Thanks again!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top