Page 1 of 1
COMatePLus and request on remote host
Posted: Thu Nov 26, 2020 1:20 pm
by tatanas
Hi,
I would like to get the installed program list from HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall registry key on remote computers.
I'm trying with COMatePlus and the StdRegProv class with its EnumKey method but I can' connect to the remote computer.
Code: Select all
XIncludeFile "COMatePLUS.pbi"
hostname.s = "host"
login.s = "administrator"
password.s = "adminpass"
HKEY_LOCAL_MACHINE = $80000002
strKeyPath.s = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
objLocator.COMateObject
objService.COMateObject
objLocator = COMate_CreateObject("WbemScripting.SWbemLocator")
If objLocator
Debug "objLocator ok"
objLocator\ConnectServer(hostname, "root\CIMV2", login, password)
; objLocator\Invoke("ConnectServer(" + "'" + hostname + "', '" + "root\CIMV2" + "', '" + login + "', '" + password + "')")
objService = COMate_GetObject("winmgmts:\\.\root\default:StdRegProv", "")
If objService
Debug "objService ok"
objService\Invoke("EnumKey(" + Str(HKEY_LOCAL_MACHINE) + ", '" + strKeyPath + "', '" + Str(@dwValue))
Debug PeekS(dwValue, -1, #PB_Unicode)
SysFreeString_(dwValue)
objService\Release()
EndIf
objLocator\Release()
EndIf
The error : "Interface method not found: ConnectServer."
However "ConnectServer" is a method of SWbemLocator object. Should I proceed in a different way ?
Re: COMatePLus and request on remote host
Posted: Thu Nov 26, 2020 1:24 pm
by infratec
Use
Code: Select all
objLocator\Invoke("ConnectServer(" + "'" + hostname + "', '" + "root\CIMV2" + "', '" + login + "', '" + password + "')")
Debug COMate_GetLastErrorDescription()
To see what's the reason.
Re: COMatePLus and request on remote host
Posted: Thu Nov 26, 2020 1:37 pm
by infratec
Code: Select all
EnableExplicit
XIncludeFile "COMatePLUS.pbi"
Define.l dwValue
Define.i HKEY_LOCAL_MACHINE
Define Hostname$, login$, password$, strKeyPath$
Define.COMateObject objLocator, objService
Hostname$ = "192.168.0.1"
login$ = "Administrator"
password$ = "XXXXXX"
HKEY_LOCAL_MACHINE = $80000002
strKeyPath$ = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
objLocator = COMate_CreateObject("WbemScripting.SWbemLocator")
If objLocator
Debug "objLocator ok"
If objLocator\Invoke("ConnectServer(" + "'" + Hostname$ + "', '" + "root\CIMV2" + "', '" + login$ + "', '" + password$ + "')") = #S_OK
Debug COMate_GetLastErrorDescription()
objService = COMate_GetObject("winmgmts:\\.\root\default:StdRegProv", "")
If objService
Debug "objService ok"
objService\Invoke("EnumKey(" + Str(HKEY_LOCAL_MACHINE) + ", '" + strKeyPath$ + "', '" + Str(@dwValue))
If COMate_GetLastErrorCode() = 0
Debug PeekS(dwValue, -1, #PB_Unicode)
SysFreeString_(dwValue)
Else
Debug COMate_GetLastErrorDescription()
EndIf
objService\Release()
EndIf
Else
Debug COMate_GetLastErrorDescription()
EndIf
objLocator\Release()
EndIf
Re: COMatePLus and request on remote host
Posted: Thu Nov 26, 2020 2:09 pm
by tatanas
Ok, so I should use Invoke method.
Using your code, I replaced the EnumKey method by GetStringValue :
Code: Select all
EnableExplicit
XIncludeFile "COMatePLUS.pbi"
Define.l dwValue
Define.i HKEY_LOCAL_MACHINE
Define Hostname$, login$, password$, strKeyPath$
Define.COMateObject objLocator, objService
Hostname$ = "x.x.x.x"
login$ = "Administrator"
password$ = "adminpass"
HKEY_LOCAL_MACHINE = $80000002
strKeyPath$ = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
objLocator = COMate_CreateObject("WbemScripting.SWbemLocator")
If objLocator
Debug "objLocator ok"
If objLocator\Invoke("ConnectServer(" + "'" + Hostname$ + "', '" + "root\CIMV2" + "', '" + login$ + "', '" + password$ + "')") = #S_OK
Debug COMate_GetLastErrorDescription()
objService = COMate_GetObject("winmgmts:\\.\root\default:StdRegProv", "")
If objService
Debug "objService ok"
objService\Invoke("GetStringValue(" + Str(HKEY_LOCAL_MACHINE) + ", '" + strKeyPath$ + "\VLC media player" + "', '" + "InstallLocation" + "', " + Str(@dwValue) + " BYREF)")
If COMate_GetLastErrorCode() = 0
Debug PeekS(dwValue, -1, #PB_Unicode)
SysFreeString_(dwValue)
Else
Debug COMate_GetLastErrorDescription()
EndIf
objService\Release()
EndIf
Else
Debug COMate_GetLastErrorDescription()
EndIf
objLocator\Release()
EndIf
Error message : "Type mismatch occurred" from objService\Invoke("GetStringValue...
EDIT : I found this post
viewtopic.php?p=312528#p312528 from SFSxOI. His code seemed to work in 2010 but I have the same error now.
EDIT2 : I just realize that I should replace the '.' after "winmgmts:\\" with the hostname/@ip, but if I do that i've got an denied access error...
Re: COMatePLus and request on remote host
Posted: Fri Nov 27, 2020 8:22 am
by tatanas
I modified the ConnectServer part because I have to connect to "root\default:StdRegProv" not "root\CIMv2".
The second problem is the return of ConnectServer. It should be a SWbemServices object, how can I get it through "Invoke" ?
Code: Select all
XIncludeFile "COMatePLUS.pbi"
Define.l dwValue
Define.l HKEY_LOCAL_MACHINE
Define Hostname$, login$, password$, strKeyPath$
Define.COMateObject objLocator, objService
Hostname$ = "x.x.x.x"
login$ = "Administrator"
password$ = "adminpass"
HKEY_LOCAL_MACHINE = $80000002
strKeyPath$ = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
objLocator = COMate_CreateObject("WbemScripting.SWbemLocator")
If objLocator
Debug "objLocator ok"
If objLocator\Invoke("ConnectServer(" + "'" + Hostname$ + "', '" + "root\default:StdRegProv" + "', '" + login$ + "', '" + password$ + "')") = #S_OK
Debug COMate_GetLastErrorDescription()
; If objService
; Debug "objService ok"
objService\Invoke("GetStringValue(" + Str(#HKEY_LOCAL_MACHINE) + ", '" + strKeyPath$ + "\VLC media player" + "', '" + "InstallLocation" + "', " + Str(@dwValue) + " BYREF)")
If COMate_GetLastErrorCode() = 0
Debug PeekS(dwValue, -1, #PB_Unicode)
SysFreeString_(dwValue)
Else
Debug COMate_GetLastErrorDescription()
EndIf
objService\Release()
; Else
; Debug COMate_GetLastErrorDescription()
; EndIf
Else
Debug COMate_GetLastErrorDescription()
EndIf
objLocator\Release()
EndIf
Re: COMatePLus and request on remote host
Posted: Wed Dec 09, 2020 12:48 pm
by tatanas
Finally get it to work in 32bits... (got an error in 64bits) :
Code: Select all
XIncludeFile "COMatePLUS.pbi"
Define.s Hostname, login, password, strKeyPath, strValueName
Define.COMateObject objLocator, objService, objReg
Hostname = "PCNAME"
login = "Administrator"
password = "password"
hkey = #HKEY_LOCAL_MACHINE
strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\VLC media player"
strValueName = "InstallLocation"
objLocator = COMate_CreateObject("WbemScripting.SWbemLocator")
If objLocator
Debug "objLocator ok"
objService = objLocator\GetObjectProperty("ConnectServer(" + "'" + Hostname + "', '" + "root\default" + "', '" + login + "', '" + password + "')")
If objService
objReg = objService\GetObjectProperty("Get('StdRegProv')")
If objReg
If objReg\Invoke("GetStringValue(" + Str(hkey) + ", '" + strKeyPath + "', '" + strValueName + "', " + Str(@dwValue) + " BYREF)") = #S_OK
Debug PeekS(dwValue, -1, #PB_Unicode)
SysFreeString_(dwValue)
Else
Debug "invoke error : " + COMate_GetLastErrorDescription()
EndIf
objReg\Release()
Else
Debug "objReg erreur"
EndIf
objService\Release()
Else
Debug "objService erreur"
EndIf
objLocator\Release()
EndIf
Re: COMatePLus and request on remote host
Posted: Wed Dec 09, 2020 3:57 pm
by infratec
Your code still returns 0 for dwValue
And VLC is installed on the target PC.
Re: COMatePLus and request on remote host
Posted: Thu Dec 10, 2020 8:07 am
by tatanas
You get 0 even if vlc is installed ? It may be a problem with "SOFTWARE\WOW6432Node" path.
Try with another key like this one "SYSTEM\CurrentControlSet\services\NetBT\Parameters" and this value "NbProvider".
For me, it returns "_tcp" if compiled in 32bits.
Re: COMatePLus and request on remote host
Posted: Thu Dec 10, 2020 8:12 am
by infratec
You are right, this works.
So I will double check the path.
Re: COMatePLus and request on remote host
Posted: Thu Dec 10, 2020 9:25 am
by tatanas
New difficulty :
It's great to be able to read a key but I would like to enumerate the subkeys.
There is a method named Enumkey (
https://docs.microsoft.com/en-us/previo ... stdregprov) but the last parameter is an array of strings passed by reference. I don't know how to declare and what kind of variable I have to pass to this method.
Any idea ?
Code: Select all
objReg\Invoke("EnumKey(" + Str(hkey) + ", '" + strKeyPath + "', " + Str(@myarr(0)) + " BYREF)")
EDIT : I found a snippet in VB where variables are declared as variant type. I know it is possible in Purebasic but I don't know how to use it.
Code: Select all
Option Explicit
Private Sub Form_Load()
Dim Registry As Object, varKey As Variant, varKeys As Variant
Set Registry = GetObject("winmgmts:\\.\root\default:StdRegProv")
Registry.EnumKey &H80000001, "software\microsoft\windows\currentversion\unreadmail", varKeys
For Each varKey In varKeys
Debug.Print varKey
Next
End Sub
Re: COMatePLus and request on remote host
Posted: Fri Dec 11, 2020 8:26 am
by tatanas
Another unsuccessful attempt (E_INVALIDARG error) :
Code: Select all
XIncludeFile "COMatePLUS.pbi"
Define.COMateObject oReg
hkey.i = #HKEY_LOCAL_MACHINE
strKeyPath.s = "SYSTEM\CurrentControlSet\Services"
oReg = COMate_GetObject("winmgmts:\\.\root\default:StdRegProv", "")
If oReg
If oReg\Invoke("EnumKey(" + Str(hkey) + ", '" + strKeyPath + "', " + Str(@safeArray) + " BYREF)") = #S_OK
; Retrieve the strings from the safearray
SafeArrayGetLBound_(safeArray, 1, @lBound)
SafeArrayGetUBound_(safeArray, 1, @uBound)
For i = lBound To uBound
ret = SafeArrayGetElement_(safeArray, @i, @temp)
If ret = #S_OK
Debug temp
If temp
Debug PeekS(temp, -1, #PB_Unicode)
EndIf
Else
If ret = #DISP_E_BADINDEX : Debug "erreur #DISP_E_BADINDEX" : EndIf
If ret = #E_INVALIDARG : Debug "erreur #E_INVALIDARG" : EndIf
If ret = #E_OUTOFMEMORY : Debug "erreur #E_OUTOFMEMORY" : EndIf
EndIf
Next
;Destroy the array.
SafeArrayDestroy_(safeArray)
Else
Debug "invoke EnumKey error"
Debug COMate_GetLastErrorDescription()
EndIf
; If oReg\Invoke("GetStringValue(" + Str(hkey) + ", '" + strKeyPath + "', '" + strValueName + "', " + Str(@dwValue) + " BYREF)") = #S_OK
; sValue$ = PeekS(dwValue, -1, #PB_Unicode)
; SysFreeString_(dwValue)
; Debug "registry value = " + sValue$
; Else
; Debug "GetStringValue error : " + COMate_GetLastErrorDescription()
; EndIf
oReg\Release()
Else
Debug "objet error"
EndIf
uBound variable seems to get the exact number of sub keys but I can't get the text associated.
Re: COMatePLus and request on remote host
Posted: Sat Dec 12, 2020 4:21 pm
by Justin
You have to pass the array as variant by reference, the array elements are variants too, this worked:
Code: Select all
XIncludeFile "COMatePLUS\COMatePLUS.pbi"
Define.COMateObject oReg
Define.i safeArray
Define.i hst
Define.s command
Define.VARIANT varNamesArr, varName
hkey.l = #HKEY_LOCAL_MACHINE
strKeyPath.s = "SYSTEM\CurrentControlSet\Services"
oReg = COMate_GetObject("winmgmts:\\.\root\default:StdRegProv", "")
If oReg
command = "EnumKey(" + Str(hkey) + ", '" + strKeyPath + "', " + Str(@varNamesArr) + " AS variant BYREF)"
If oReg\Invoke(command) = #S_OK
safeArray = varNamesArr\parray
; Retrieve the strings from the safearray
SafeArrayGetLBound_(safeArray, 1, @lBound)
SafeArrayGetUBound_(safeArray, 1, @uBound)
For i = lBound To uBound
ret = SafeArrayGetElement_(safeArray, @i, @varName)
If ret = #S_OK
If varName\bstrVal
Debug PeekS(varName\bstrVal, -1, #PB_Unicode)
SysFreeString_(varName\bstrVal)
varName\bstrVal = 0
EndIf
Else
If ret = #DISP_E_BADINDEX : Debug "erreur #DISP_E_BADINDEX" : EndIf
If ret = #E_INVALIDARG : Debug "erreur #E_INVALIDARG" : EndIf
If ret = #E_OUTOFMEMORY : Debug "erreur #E_OUTOFMEMORY" : EndIf
EndIf
Next
;Destroy the array.
SafeArrayDestroy_(safeArray)
Else
Debug "invoke EnumKey error"
Debug COMate_GetLastErrorDescription()
EndIf
; If oReg\Invoke("GetStringValue(" + Str(hkey) + ", '" + strKeyPath + "', '" + strValueName + "', " + Str(@dwValue) + " BYREF)") = #S_OK
; sValue$ = PeekS(dwValue, -1, #PB_Unicode)
; SysFreeString_(dwValue)
; Debug "registry value = " + sValue$
; Else
; Debug "GetStringValue error : " + COMate_GetLastErrorDescription()
; EndIf
oReg\Release()
Else
Debug "objet error"
EndIf
Re: COMatePLus and request on remote host
Posted: Mon Dec 14, 2020 8:12 am
by tatanas
Many thanks Justin !
I had tried with "As variant BYREF" too but didn't use "safeArray = varNamesArr\parray". I guess it was the problem.
Do you have an idea why it is not working when compiled in 64 bits ?
EDIT :
Ok, I'm able to list installed softwares but the automatic redirection 32/64bits always redirects my request to WOW6432Node because it's (for now) a 32bits compiled program.
I read this article
https://docs.microsoft.com/en-us/window ... t-platform but I don't know how to apply to my code...
Code: Select all
XIncludeFile "COMatePlus\COMatePLUS.pbi"
Define.s Hostname, login, password, strKeyPath, strKeyPath32, strValueName
Define.COMateObject objLocator, objService, objReg, objCtx
hkey = #HKEY_LOCAL_MACHINE
strKeyPath = "Software\Microsoft\Windows\CurrentVersion\Uninstall\"
strKeyPath32 = "Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
strValueName = "DisplayName"
Define.COMateObject objReg
Define.i safeArray
Define.VARIANT varNamesArr, varName
Define.s subkeyname
objReg = COMate_GetObject("winmgmts:\\.\root\default:StdRegProv", "")
If objReg
; first list from "Software\Microsoft\Windows\CurrentVersion\Uninstall\"
If objReg\Invoke("EnumKey(" + Str(hkey) + ", '" + strKeyPath + "', " + Str(@varNamesArr) + " AS variant BYREF)") = #S_OK
safeArray = varNamesArr\parray
SafeArrayGetLBound_(safeArray, 1, @lBound)
SafeArrayGetUBound_(safeArray, 1, @uBound)
For i = lBound To uBound
ret = SafeArrayGetElement_(safeArray, @i, @varName)
If ret = #S_OK
If varName\bstrVal
subkeyname = PeekS(varName\bstrVal, -1, #PB_Unicode)
SysFreeString_(varName\bstrVal)
varName\bstrVal = 0
If objReg\Invoke("GetStringValue(" + Str(hkey) + ", '" + strKeyPath + subkeyname + "', '" + strValueName + "', " + Str(@dwValue) + " BYREF)") = #S_OK
If dwValue <> 1 ; NOT SURE ABOUT THAT TEST (if the key is not present, the pointer should be null but it seems its value is 1
sValue$ = PeekS(dwValue, -1, #PB_Unicode)
SysFreeString_(dwValue)
Debug "registry value = " + sValue$
Else
; Debug "no key"
EndIf
dwValue = 0
Else
Debug "GetStringValue error : " + COMate_GetLastErrorDescription()
EndIf
EndIf
Else
If ret = #DISP_E_BADINDEX : Debug "erreur #DISP_E_BADINDEX" : EndIf
If ret = #E_INVALIDARG : Debug "erreur #E_INVALIDARG" : EndIf
If ret = #E_OUTOFMEMORY : Debug "erreur #E_OUTOFMEMORY" : EndIf
EndIf
Next
SafeArrayDestroy_(safeArray)
Else
Debug "invoke EnumKey error"
Debug COMate_GetLastErrorDescription()
EndIf
Debug "-----------------------------------------------------------------------------"
; second list from "Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
If objReg\Invoke("EnumKey(" + Str(hkey) + ", '" + strKeyPath32 + "', " + Str(@varNamesArr) + " AS variant BYREF)") = #S_OK
safeArray = varNamesArr\parray
SafeArrayGetLBound_(safeArray, 1, @lBound)
SafeArrayGetUBound_(safeArray, 1, @uBound)
For i = lBound To uBound
ret = SafeArrayGetElement_(safeArray, @i, @varName)
If ret = #S_OK
If varName\bstrVal
subkeyname = PeekS(varName\bstrVal, -1, #PB_Unicode)
SysFreeString_(varName\bstrVal)
varName\bstrVal = 0
If objReg\Invoke("GetStringValue(" + Str(hkey) + ", '" + strKeyPath32 + subkeyname + "', '" + strValueName + "', " + Str(@dwValue) + " BYREF)") = #S_OK
If dwValue <> 1 ; NOT SURE ABOUT THAT TEST (if the key is not present, the pointer should be null but it seems its value is 1
sValue$ = PeekS(dwValue, -1, #PB_Unicode)
SysFreeString_(dwValue)
Debug "registry value = " + sValue$
Else
; Debug "no key"
EndIf
dwValue = 0
Else
Debug "GetStringValue error : " + COMate_GetLastErrorDescription()
EndIf
EndIf
Else
If ret = #DISP_E_BADINDEX : Debug "erreur #DISP_E_BADINDEX" : EndIf
If ret = #E_INVALIDARG : Debug "erreur #E_INVALIDARG" : EndIf
If ret = #E_OUTOFMEMORY : Debug "erreur #E_OUTOFMEMORY" : EndIf
EndIf
Next
SafeArrayDestroy_(safeArray)
Else
Debug "invoke EnumKey error"
Debug COMate_GetLastErrorDescription()
EndIf
objReg\Release()
Else
Debug "objet error"
EndIf
Re: COMatePLus and request on remote host
Posted: Mon Dec 14, 2020 11:21 am
by Justin
hkey is a long(4 bytes), you did not declare it and it defaults to integer wich is 8 bytes in 64 bit so it was wrong, also use variant by ref as the return type.
It is better to use always enableexplicit and declare all the correct types.
This worked in 64 bit, i removed the hostname, user, pwd to use the local machine:
Code: Select all
XIncludeFile "COMatePLUS\COMatePLUS.pbi"
EnableExplicit
Define.s Hostname, login, password, strKeyPath, strValueName
Define.COMateObject objLocator, objService, objReg
Define.VARIANT varValue
Define.i value
Define.l hkey
Hostname = ""
login = ""
password = ""
hkey = #HKEY_LOCAL_MACHINE
strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\VLC media player"
strValueName = "InstallLocation"
objLocator = COMate_CreateObject("WbemScripting.SWbemLocator")
If objLocator
Debug "objLocator ok"
objService = objLocator\GetObjectProperty("ConnectServer(" + "'" + Hostname + "', '" + "root\default" + "', '" + login + "', '" + password + "')")
If objService
objReg = objService\GetObjectProperty("Get('StdRegProv')")
If objReg
If objReg\Invoke("GetStringValue(" + Str(hkey) + ", '" + strKeyPath + "', '" + strValueName + "', " + Str(@varValue) + " AS variant BYREF)") = #S_OK
If varValue\vt = #VT_BSTR And varValue\bstrVal
Debug PeekS(varValue\bstrVal, -1, #PB_Unicode)
SysFreeString_(varValue\bstrVal)
EndIf
Else
Debug "invoke error : " + COMate_GetLastErrorDescription()
EndIf
objReg\Release()
Else
Debug "objReg erreur"
EndIf
objService\Release()
Else
Debug "objService erreur"
EndIf
objLocator\Release()
EndIf
Re: COMatePLus and request on remote host
Posted: Mon Dec 14, 2020 12:54 pm
by tatanas
Thank you very much. It works like a charm !
Here is the code to list all installed sofwares from a remote computer :
Code: Select all
EnableExplicit
XIncludeFile "COMatePlus\COMatePLUS.pbi"
Define.s Hostname, login, password, strKeyPath, strKeyPath32, strValueName
Define.COMateObject objLocator, objService, objReg
Define hkey.l
Define.i lBound, uBound, i, ret
Hostname = "RemotePC"
login = "Administrator"
password = "password"
hkey = #HKEY_LOCAL_MACHINE
strKeyPath = "Software\Microsoft\Windows\CurrentVersion\Uninstall\"
strKeyPath32 = "Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
strValueName = "DisplayName"
; "UninstallString", QuietUninstallString
Define.COMateObject oReg
Define.i safeArray
Define.VARIANT varNamesArr, varName, dwValue
Define.s subkeyname
objLocator = COMate_CreateObject("WbemScripting.SWbemLocator")
If objLocator
objService = objLocator\GetObjectProperty("ConnectServer(" + "'" + Hostname + "', '" + "root\default" + "', '" + login + "', '" + password + "')")
If objService
objReg = objService\GetObjectProperty("Get('StdRegProv')")
If objReg
If objReg\Invoke("EnumKey(" + Str(hkey) + ", '" + strKeyPath + "', " + Str(@varNamesArr) + " AS variant BYREF)") = #S_OK
safeArray = varNamesArr\parray
SafeArrayGetLBound_(safeArray, 1, @lBound)
SafeArrayGetUBound_(safeArray, 1, @uBound)
For i = lBound To uBound
ret = SafeArrayGetElement_(safeArray, @i, @varName)
If ret = #S_OK
If varName\bstrVal
subkeyname = PeekS(varName\bstrVal, -1, #PB_Unicode)
SysFreeString_(varName\bstrVal)
varName\bstrVal = 0
If objReg\Invoke("GetStringValue(" + Str(hkey) + ", '" + strKeyPath + subkeyname + "', '" + strValueName + "', " + Str(@dwValue) + " AS variant BYREF)") = #S_OK
If dwValue\vt = #VT_BSTR And dwValue\bstrVal ; 8 = #VT_BSTR, 1 = #VT_NULL
Debug PeekS(dwValue\bstrVal, -1, #PB_Unicode)
SysFreeString_(dwValue\bstrVal)
EndIf
Else
Debug "GetStringValue error : " + COMate_GetLastErrorDescription()
EndIf
EndIf
Else
If ret = #DISP_E_BADINDEX : Debug "error #DISP_E_BADINDEX" : EndIf
If ret = #E_INVALIDARG : Debug "error #E_INVALIDARG" : EndIf
If ret = #E_OUTOFMEMORY : Debug "error #E_OUTOFMEMORY" : EndIf
EndIf
Next
SafeArrayDestroy_(safeArray)
Else
Debug "invoke EnumKey error"
Debug COMate_GetLastErrorDescription()
EndIf
Debug "-----------------------------------------------------------------------------"
If objReg\Invoke("EnumKey(" + Str(hkey) + ", '" + strKeyPath32 + "', " + Str(@varNamesArr) + " AS variant BYREF)") = #S_OK
safeArray = varNamesArr\parray
SafeArrayGetLBound_(safeArray, 1, @lBound)
SafeArrayGetUBound_(safeArray, 1, @uBound)
For i = lBound To uBound
ret = SafeArrayGetElement_(safeArray, @i, @varName)
If ret = #S_OK
If varName\bstrVal
subkeyname = PeekS(varName\bstrVal, -1, #PB_Unicode)
SysFreeString_(varName\bstrVal)
varName\bstrVal = 0
If objReg\Invoke("GetStringValue(" + Str(hkey) + ", '" + strKeyPath32 + subkeyname + "', '" + strValueName + "', " + Str(@dwValue) + " AS variant BYREF)") = #S_OK
If dwValue\vt = #VT_BSTR And dwValue\bstrVal ; 8 = #VT_BSTR, 1 = #VT_NULL
Debug PeekS(dwValue\bstrVal, -1, #PB_Unicode)
SysFreeString_(dwValue\bstrVal)
EndIf
Else
Debug "GetStringValue error : " + COMate_GetLastErrorDescription()
EndIf
EndIf
Else
If ret = #DISP_E_BADINDEX : Debug "error #DISP_E_BADINDEX" : EndIf
If ret = #E_INVALIDARG : Debug "error #E_INVALIDARG" : EndIf
If ret = #E_OUTOFMEMORY : Debug "error #E_OUTOFMEMORY" : EndIf
EndIf
Next
SafeArrayDestroy_(safeArray)
Else
Debug "invoke EnumKey error"
Debug COMate_GetLastErrorDescription()
EndIf
objReg\Release()
Else
Debug "objReg error"
EndIf
Else
Debug "objService error"
EndIf
Else
Debug "objLocator error"
EndIf