Newsgroup: it.comp.lang.visual-basic
Titolo: [?] APIs RegQueryInfoKey e RegEnumKeyEx

Salve, ho implementatop una routine VB che determina se un'aplicazione
è installata e in caso affermativo restituisce la stringa di
disinstallazione.
La routine legge i valori dal registry usando le APIs di cui all'ogg.
La routine ha semnpre funzionato sotto Win95/98 per anni.
Provata sotto NT, la routine NON FUNZIONA!
Infatti le APIs RegEnumKeyEx e RegQueryInfoKey mi danno errore.
Qualcuno sa dirmi dov'è che sbaglio?
Posto in calce la routine per intero.
Ovvio che gli "a capo" sono forzati dal newsreader...
TIA
'************************
'sezione Declarations del modulo
'dichiarazioni API
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
Declare Function RegQueryInfoKey Lib "advapi32.dll" Alias
"RegQueryInfoKeyA" (ByVal hKey As Long, ByVal lpClass As String,
lpcbClass As Long, 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
Declare Function RegEnumKeyEx Lib "advapi32.dll" Alias "RegEnumKeyExA"
(ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpName As String,
lpcbName As Long, lpReserved As Long, ByVal lpClass As String,
lpcbClass As Long, lpftLastWriteTime As FILETIME) As Long
Declare Function RegQueryValueEx Lib "advapi32.dll" Alias
"RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String,
ByVal lpReserved As Long, lpType As Long, ByVal lpData As Any,
lpcbData As Long) As Long
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
Declare Function RegSetValueExString Lib "advapi32.dll" Alias
"RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String,
ByVal Reserved As Long, ByVal dwType As Long, ByVal lpData As String,
ByVal cbData As Long) As Long
Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long)
As Long
Declare Function RegLoadKey Lib "advapi32.dll" Alias "RegLoadKeyA"
(ByVal hKey As Long, ByVal lpSubKey As String, ByVal lpFile As String)
As Long
Declare Function RegUnLoadKey Lib "advapi32.dll" Alias "RegUnLoadKeyA"
(ByVal hKey As Long, ByVal lpSubKey As String) As Long
Declare Function RegSaveKey Lib "advapi32.dll" Alias "RegSaveKeyA"
(ByVal hKey As Long, ByVal lpFile As String, lpSecurityAttributes As
SECURITY_ATTRIBUTES) As Long
'costanti delle chiavi del registry (pubbliche, per essere utilizzate
da moduli esterni)
Public Const HKEY_CLASSES_ROOT = &H80000000
Public Const HKEY_CURRENT_USER = &H80000001
Public Const HKEY_LOCAL_MACHINE = &H80000002
Public Const HKEY_USERS = &H80000003
Public Const HKEY_PERFORMANCE_DATA = &H80000004
Public Const HKEY_CURRENT_CONFIG = &H80000005
Public Const HKEY_DYN_DATA = &H80000006
'costanti di alcune sottochiavi ricorrenti
Const UninstKey =
"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
Const ShellFoldersKey =
"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
'costanti di apertura chiavi
Const KEY_QUERY_VALUE = &H1
Const KEY_SET_VALUE = &H2
Const KEY_CREATE_SUB_KEY = &H4
Const KEY_ENUMERATE_SUB_KEYS = &H8
Const KEY_NOTIFY = &H10
Const KEY_CREATE_LINK = &H20
Const SYNCHRONIZE = &H100000
Const READ_CONTROL = &H20000
Const STANDARD_RIGHTS_READ = (READ_CONTROL)
Const STANDARD_RIGHTS_WRITE = (READ_CONTROL)
Const STANDARD_RIGHTS_ALL = &H1F0000
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_WRITE = ((STANDARD_RIGHTS_WRITE Or KEY_SET_VALUE Or
KEY_CREATE_SUB_KEY) 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))
'costanti tipo valori registro
Const REG_SZ = 1 'stringa
'tipi richiesti da alcune API
Type FILETIME
    dwLowDateTime As Long
    dwHighDateTime As Long
End Type
Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As Long
    bInheritHandle As Long
End Type
'costante risultato chiamate API con successo
Const ERROR_SUCCESS = 0&
'********************************************
'IMPLEMENTAZIONE DELLA ROUTINE "INCRIMINATA"
Public Function IsAppInstalled(ByVal AppName As String, Optional_
UninstStr As String = "-1") As Boolean
'restituisce True se l'applicazione indicata da AppName è installata
'nella macchina
'Se viene passato anche il secondo parametro, ne viene restituita
'UninstStr
 
    'costante del valore per ricerca applicazioni installate
    Const APP_NAME_VALUE = "DisplayName"
    Const UNINST_STRING_VALUE = "UninstallString"
 
    Dim hKey As Long, numSubkeys As Long, maxLenSubkey As Long
    Dim ft As FILETIME
    Dim i As Long
    Dim result As Long
 
    'apro la chiave del registry
    result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, UninstKey, 0, KEY_READ,_
hKey)
    GoSub eval
 
   'quante sottochiavi?
    With ft
        .dwHighDateTime = 0
        .dwLowDateTime = 0
    End With
    result = RegQueryInfoKey(hKey, vbNullString, 0, 0, numSubkeys,_
maxLenSubkey, 0, 0, 0, 0, 0, ft)
 
    GoSub eval
 
    'cerco in tutte le sottochiavi
    maxLenSubkey = maxLenSubkey + 1 'per includere il carattere null
 
    Dim hSubKeyName As String
    Dim lenKey As Long
    Dim hSubKey As Long
 
    Dim FoundAppName As String
    Dim lenAppName As Long, lenUninstStr As Long
 
    Dim typ As Long
 
    Dim Trovata As Boolean
 
    For i = 0 To numSubkeys - 1
        hSubKey = 0 'indica sottochiave non aperta; serve alla trap
	               ' per sapere se chiudere
        lenKey = maxLenSubkey
        hSubKeyName = String(lenKey, 0)
        result = RegEnumKeyEx(hKey, i, hSubKeyName, lenKey, 0,_
vbNullString, 0, ft)
        GoSub eval
 
        hSubKeyName = Left(hSubKeyName, lenKey)
        'apro la sottochiave
        result = RegOpenKeyEx(hKey, hSubKeyName, 0, KEY_QUERY_VALUE,_
hSubKey)
        If result = 2 Then result = ERROR_SUCCESS 'pezza
        GoSub eval
 
        'cerco la stringa dell'applicazione:
        lenAppName = 0
        FoundAppName = vbNullString
        '..ne determino la lunghezza...
        result = RegQueryValueEx(hSubKey, APP_NAME_VALUE, 0, typ,_
FoundAppName, lenAppName)
        If typ = REG_SZ Then '(DEVE essere una stringa, alrimenti
  		              'salto questo passaggio)
            FoundAppName = String(lenAppName, 0)
            '...e la leggo:
            result = RegQueryValueEx(hSubKey, APP_NAME_VALUE, 0, typ,_
FoundAppName, lenAppName)
            GoSub eval
            FoundAppName = Left(FoundAppName, lenAppName - 1)
	 'qui DEVO togliere il chr(0) finale
            'vedo se la stringa corrisponde all'app.
            Trovata = (UCase(FoundAppName) = UCase(AppName))
            If Trovata Then
                'trovata !
                If UninstStr <> "-1" Then
                    'leggo anche l'UninstallString:
                    lenUninstStr = 0
                    UninstStr = vbNullString
                    'la prima volta per sapere quanto è lunga...
                    result = RegQueryValueEx(hSubKey,_
UNINST_STRING_VALUE, 0, typ, UninstStr, lenUninstStr)
                    '...e quindi predimensionarne il buffer;...
                    UninstStr = String(lenUninstStr, 0)
                    '...la seconda, per leggerne il valore.
                    result = RegQueryValueEx(hSubKey,_
UNINST_STRING_VALUE, 0, typ, UninstStr, lenUninstStr)
                    UninstStr = Left(UninstStr, lenUninstStr - 1) 	
		'anche qui tolgo il chr(0) finale
                End If
            End If
            'chiudo la sottochiave
            result = RegCloseKey(hSubKey)
            'esco dal ciclo se l'ho trovata
            If Trovata Then Exit For
        Else
            'chiudo la sottochiave
            result = RegCloseKey(hSubKey)
        End If
    Next i
    'trovata?
    IsAppInstalled = Trovata '(i < numSubkeys)
 
    'chiudo la chiave del registro
    result = RegCloseKey(hKey)
 
    Exit Function
'***************************************************************
eval:
    If result = ERROR_SUCCESS Then
        'va avanti...
        Return
    Else
        '...altrimenti...
        IsAppInstalled = False
        '...chiude le chiavi aperte...
        If hSubKey <> 0 Then result = RegCloseKey(hSubKey)
        result = RegCloseKey(hKey) '...sicuramente aperta...
        '...ed esce
    End If
End Function
ale...@virgilio.it

Ciao, premetto che non ho letto attentamente il codice che hai
allegato al tuo argomento.
Mi era capitato qualcosa del genere e approfondendo avevo scoperto
che NT e Win95/98 gestiscono in modo diverso i valori stringa sul
registry. Più precisamente Win95 utilizza delle stringhe di tipo "Null
Terminate" mentre NT no.
Avevo poi trovato un esempio (del quale ti allego un estratto)
nel quale si gestiva tale diversità (If (Asc(Mid(tmpVal, KeyValSize,
1)) = 0) Then ........ Else .........).
Spero ti possa servire.
Bye Michele.
___________________________________________________________________________
    tmpVal = String$(1024, 0)                             ' Allocate
Variable Space
    KeyValSize = 1024                                       ' Mark
Variable Size
 
    '------------------------------------------------------------
    ' Retrieve Registry Key Value...
    '------------------------------------------------------------
    rc = RegQueryValueEx(hKey, SubKeyRef, 0, _
                         KeyValType, tmpVal, KeyValSize)    '
Get/Create Key Value
 
    If (rc <> ERROR_SUCCESS) Then GoTo GetKeyError          ' Handle
Errors
 
    If (Asc(Mid(tmpVal, KeyValSize, 1)) = 0) Then           ' Win95
Adds Null Terminated String...
        tmpVal = Left(tmpVal, KeyValSize - 1)               ' Null
Found, Extract From String
    Else                                                    ' WinNT
Does NOT Null Terminate String...
        tmpVal = Left(tmpVal, KeyValSize)                   ' Null Not
					Found, Extract String Only 	
    End If
__________________________________________________________________________

mi...@argentea.it
 ha scritto:

Forse quello che dici e' vero, comunque c'e' un'altro errore.
Quando si chiamano RegQueryValueEx e RegSetValueEx per leggere e scrivere
stringhe, la variabile stringa va passata byval.
    rc = RegQueryValueEx(hKey, SubKeyRef, 0, _
                         KeyValType, ByVal tmpVal, KeyValSize)
Se scarichi i sorgenti del mio newsreader (link nella firma)
ci trovi anche un modulo per la gestione delle chiavi del registro.
Se ci dai un'occhiata puoi vedere con esattezza quali sono tutti i
parametri esatti.
-- 
Samuele Battarra
mail server: 
libero.it
, indirizzo: battarsa@(mail server)
prova il mio newsreader:
http://digilander.iol.it/battarsa/programmi/leggiminews.html