vba 7 - retrieving values from RegQueryValueEx returns unicode string
Question
I cant figure out why i get back a unicode string with extra character per letter
Private Declare PtrSafe Function RegQueryValueEx Lib "advapi32.dll"
Alias "RegQueryValueExA" (ByVal hKey As LongPtr, ByVal lpValueName As String,
ByVal lpReserved As LongPtr, lpType As LongPtr,
lpData As Any, lpcbData As LongPtr) As LongPtr
If RegQueryValueEx(hKey, strValueName, 0, dwType,
ByVal RegData, lDataBufSize) = ERROR_SUCCESS Then
End If
RegData has the following value "Mobile Address Book" but if you paste that in notepad you will see all the extra characters. Do i need to convert the string to ascii?
Solution
VBA uses Unicode strings, but you are calling the Ansi version of RegQueryValueEx()
(RegQueryValueExA
) instead of the Unicode version (RegQueryValueExW
). But in both cases, the 5th parameter will receive raw Ansi/Unicode data (depending on version called) and the 6th parameter is expressed in bytes, not in characters. So you have to account for that. You also have to account for the fact that Declare
in VBA always converts String
values to Ansi, never to Unicode. To work with Unicode APIs using Unicode strings in VBA, have a look at the following article for hints:
VBA: Unicode Strings and the Windows API
For example:
Private Declare PtrSafe Function RegQueryValueEx Lib "advapi32.dll"
Alias "RegQueryValueExW" (ByVal hKey As LongPtr, ByVal lpValueName As LongPtr,
ByVal lpReserved As LongPtr, lpType As LongPtr,
ByVal lpData As LongPtr, lpcbData As LongPtr) As LongPtr
If RegQueryValueEx(hKey, StrPtr(strValueName), 0, dwType,
StrPtr(RegData), lDataBufSize) = ERROR_SUCCESS Then
End If
Just make sure that RegData
is pre-allocated to the required number of Unicode characters needed to receive the Unicode text, and that lDataBufSize
is initialized with the number of bytes allocated in RegData
so RegQueryValueExW()
knows how many characters it can write into RegData
.
Update: to read binary data:
Private Declare PtrSafe Function RegQueryValueEx Lib "advapi32.dll"
Alias "RegQueryValueExW" (ByVal hKey As LongPtr, ByVal lpValueName As LongPtr,
ByVal lpReserved As LongPtr, lpType As LongPtr,
lpData As Byte, lpcbData As LongPtr) As LongPtr
Dim RegData() As Byte
...
If RegQueryValueEx(hKey, StrPtr(strValueName), 0, dwType,
RegData(0), lDataBufSize) = ERROR_SUCCESS Then
End If