 
View Full Version : Utilizzare un API in Visual Basic
Salve,
mi serve utilizzare la funzione di un'api in un mio programma .... 
Su internet ho trovato che la funzione è la seguente : 
Declare Function CreateDirectory Lib "kernel32.dll" Alias "CreateDirectoryA" _
(ByVal lpPathName As String, lpSecurityAttributes As SECURITY_ATTRIBUTES) _
As Long 
Dove devo dichiararla ??? In quale parte del programma ????
le api si dichiarano nella sezione "dichiarazioni" di una form o di un modulo oggetto, o in un modulo bas.
Da sola quella dichiarazione serve a poco perchè bisogna abbinare l'UDT (user defined type) SECURITY_ATTRIBUTES, dichiarato nel seguente modo:
Type SECURITY_ATTRIBUTES
  nLength As Long
  lpSecurityDescriptor As Long
  bInheritHandle As Boolean
End Type
Per richiamare la funzione si usa il seguente metodo:
Sub MakeDirectory(DirectoryPath As String)
Dim Attributes As SECURITY_ATTRIBUTES
Call CreateDirectory(DirectoryPath, Attributes)
End Sub
alla fine, il codice intero è questo:
Declare Function CreateDirectory Lib "kernel32.dll" Alias "CreateDirectoryA" _
(ByVal lpPathName As String, lpSecurityAttributes As SECURITY_ATTRIBUTES) _
As Long
Type SECURITY_ATTRIBUTES
  nLength As Long
  lpSecurityDescriptor As Long
  bInheritHandle As Boolean
End Type
Sub MakeDirectory(DirectoryPath As String)
Dim Attributes As SECURITY_ATTRIBUTES
Call CreateDirectory(DirectoryPath, Attributes)
End Sub
ma non deve essere riportato dopo una end sub, function etc...
La struttura  SECURITY_ATTRIBUTES definisce il livello ed il tipo di protezione da dare ad un oggetto. Le informazioni di sicurezza, sono usate più frequentemente sotto Windows NT/2000 che sotto Windows 95/98. 
i membri sono:
nLength ---> Dimensione in byte della struttura 
lpSecurityDescriptor ---> Il puntatore al descrittore per la sicurezza. Impostare a zero per il descrittore di default 
bInheritHandle ---> Specifica se l'handle all'oggetto, sarà ereditato dal nuovo processo 
ma sono opzionali, ti consiglio di impostarli tutti a zero, l'impostazione di partenza appena viene dicharata la variabile ma se ti servono, puoi modificare la funzione
le api si dichiarano nella sezione "dichiarazioni" di una form o di un modulo oggetto, o in un modulo bas.
Da sola quella dichiarazione serve a poco perchè bisogna abbinare l'UDT (user defined type) SECURITY_ATTRIBUTES, dichiarato nel seguente modo:
Type SECURITY_ATTRIBUTES
  nLength As Long
  lpSecurityDescriptor As Long
  bInheritHandle As Boolean
End Type
Per richiamare la funzione si usa il seguente metodo:
Sub MakeDirectory(DirectoryPath As String)
Dim Attributes As SECURITY_ATTRIBUTES
Call CreateDirectory(DirectoryPath, Attributes)
End Sub
alla fine, il codice intero è questo:
Declare Function CreateDirectory Lib "kernel32.dll" Alias "CreateDirectoryA" _
(ByVal lpPathName As String, lpSecurityAttributes As SECURITY_ATTRIBUTES) _
As Long
Type SECURITY_ATTRIBUTES
  nLength As Long
  lpSecurityDescriptor As Long
  bInheritHandle As Boolean
End Type
Sub MakeDirectory(DirectoryPath As String)
Dim Attributes As SECURITY_ATTRIBUTES
Call CreateDirectory(DirectoryPath, Attributes)
End Sub
ma non deve essere riportato dopo una end sub, function etc...
La struttura  SECURITY_ATTRIBUTES definisce il livello ed il tipo di protezione da dare ad un oggetto. Le informazioni di sicurezza, sono usate più frequentemente sotto Windows NT/2000 che sotto Windows 95/98. 
i membri sono:
nLength ---> Dimensione in byte della struttura 
lpSecurityDescriptor ---> Il puntatore al descrittore per la sicurezza. Impostare a zero per il descrittore di default 
bInheritHandle ---> Specifica se l'handle all'oggetto, sarà ereditato dal nuovo processo 
ma sono opzionali, ti consiglio di impostarli tutti a zero, l'impostazione di partenza appena viene dicharata la variabile ma se ti servono, puoi modificare la funzione
Si ti ringrazio .... in realtà non capivo dove andava la funzione per il resto cioè il tipo definito dall'utente e come richiamarla questo si ... grazie molte ...  ;)
Mi accodo per un problema analogo.
Qualcuno ha la bontà di spiegarmi come funziona?
Stavo cercando di usare questo:
LONG RegOpenKeyEx(
  HKEY hKey,
  LPCTSTR lpSubKey,
  DWORD ulOptions,
  REGSAM samDesired,
  PHKEY phkResult
);
ma non ho proprio idea di come fare con tutti quei tipi di dati...
Ah, poi, io sto usando visual basic, che come avrete notato ha una sintassi diversa; la funzione la potrò usare ugualmente, no?
Cmq, credo di aver capito come si dichiarano le funzioni riferite a dll esterne; il mio problema sono i parametri... :fagiano:
Grazie :)
bertoz85
10-10-2005, 23:00
x leon84: ti consiglio di impostare a Null il parametro security attributes se non lo usi.
Per farlo devi modificare la dichiarazione della funzione in questo modo:
Declare Function CreateDirectory Lib "kernel32.dll" Alias "CreateDirectoryA" (ByVal lpPathName As String, ByVal lpSecurityAttributes As Long) As Long
 
E poi ogni volta che richiami la fuzione passi zero come secondo parametro.
Mi accodo per un problema analogo.
Qualcuno ha la bontà di spiegarmi come funziona?
Stavo cercando di usare questo:
LONG RegOpenKeyEx(
  HKEY hKey,
  LPCTSTR lpSubKey,
  DWORD ulOptions,
  REGSAM samDesired,
  PHKEY phkResult
);
Grazie :)
In visual basic c'è un comodo tool che si chiama API Viewer nel menu add-ins. Se non è abilitato vai in add-ins, add-in manager  e attivalo. Dopo lo troverai sotto lo stesso menu.
Quando lo apri, fai File,apri e seleziona Win32api.txt ....avrai dihiarazioni di funzioni, costanti e tipi piu usati in windows, fatte per il vb.
Non è aggiornatissimo ma la maggior parte c'è (inclusa RegOpenKeyEx).
Comunque in linea di massima per convertirtele da te, hai bisogno della documentazione originale. Che tipo è REGSAM x esempio? Alla fine scopri che è un Long come la maggior parte d tipi strani, come anche HKEY.
ciao
Grazie mille!!! :eek:
Ho trovato quello che mi serve, costanti comprese.
Ora (domani!) devo solo capire come usarla...
:D
bye
Per le API in VB scaricate APIGuide da www.allapi.net
Grandioso, ragazzi! :eek:
Grazie MILLE a entrambi.
... però ho un piccolo problema...
Il valore binario che devo leggere dal registro contiene una data in formato esadecimale... Se uso la funzione di esempio per leggere un valore binario ottengo solo "2005" come risultato. E il resto della data? :muro:
Non ho idea di come recuperarlo...
Mi basterebbe anche avere la stringa contenente il valore esadecimale, che poi mi gestisco io; ma non ci riesco... :muro:
Un aiutino? :fagiano:
E se usi la funzione per leggere una stringa ?
Ottengo una serie di caratteri non stampabili, e non il valore, che è una cosa del tipo:
hex:d5,03,...
Grazie
bertoz85
12-10-2005, 17:00
dichiari un array dinamico di byte e ci butti dentro la stringa:
Dim bArray() As Byte
bArray = StrConv(stringahex, vbFromUnicode)
dopodichè avrai un array base zero di Byte (stesso tipo che in C)  con dentro i singoli valori interi che potrai tradurre in stringhe esadecimani con la funzione Hex$.
per trovare la prima e l'ultima cella di un array puoi utilizzare rispettivamente LBound e UBound
ciao
Grazie mille della risposta, ma non sono troppo convinto...
Il contenuto del valore binario che mi interessa è una stringa di 16 numeri esadecimali; ma se lo leggo come stringa e lo metto in un array di byte, quest'ultimo ha dimensione 6. Che fine han fatto gli altri 10 numeri?!?
Grazie :)
bertoz85
12-10-2005, 21:53
Grazie mille della risposta, ma non sono troppo convinto...
Il contenuto del valore binario che mi interessa è una stringa di 16 numeri esadecimali; ma se lo leggo come stringa e lo metto in un array di byte, quest'ultimo ha dimensione 6. Che fine han fatto gli altri 10 numeri?!?
Grazie :)
sei sicuro di aver fatto la stringa che conterrà i dati lunga a sufficienza? devi prima crearla lunga abbastanza (usa Space$ con un valore abbast. alto da contenere il possibile valore del registro) .... 
poi devi passargli la var con la lunghezza della stringa, che ti ritorna modificata...
di chie tipo sono i dati? a che scopo li leggi se posso saperlo (x aiutarti) ???
guarda bene la documentazione della funzione su msdn.microsoft.com
ciao
La documentazione ufficiale non è che mi aiuti un granché...
L'array continua a essere di dimensione 6, perché è così l'intero che viene valorizzato dalla funzione RegQueryValueEx.
Il codice è il seguente.
Sub Main()
Dim MyString As String
Dim bArray() As Byte
Dim Ret
'Set the string
MyString = Space$(1024)
'Open the key
RegOpenKey HKEY_LOCAL_MACHINE, "SOFTWARE\Symantec\Norton AntiVirus\LastScan", Ret
'Get the key's content
Dim lResult As Long, lValueType As Long, strBuf As String, lDataBufSize As Long
'retrieve nformation about the key
lResult = RegQueryValueEx(Ret, "SystemTime", 0, lValueType, ByVal 0, lDataBufSize)
If lResult = 0 Then
    If lValueType = REG_BINARY Then
        Dim strData As Long ' As Integer
        'retrieve the key's value
        lResult = RegQueryValueEx(Ret, "SystemTime", 0, 0, strData, lDataBufSize)
        If lResult = 0 Then
            MyString = strData
        End If
    End If
End If
'Close the key
RegCloseKey Ret
bArray = StrConv( _
    MyString, vbFromUnicode _
)
Debug.Print "Dimensione array = " & UBound(bArray) - LBound(bArray) + 1
For i = LBound(bArray) To UBound(bArray)
    Debug.Print CDec("&H" & bArray(i))
Next i
End Sub
Grazie :)
bertoz85
13-10-2005, 17:28
Sub Main()
Dim MyString As String
Dim bArray() As Byte
Dim Ret
'Set the string
MyString = Space$(1024)
'Open the key
RegOpenKey HKEY_LOCAL_MACHINE, "SOFTWARE\Symantec\Norton AntiVirus\LastScan", Ret
'Get the key's content
Dim lResult As Long, lValueType As Long, strBuf As String, lDataBufSize As Long
'retrieve nformation about the key
lResult = RegQueryValueEx(Ret, "SystemTime", 0, lValueType, ByVal 0, lDataBufSize)
If lResult = 0 Then
    If lValueType = REG_BINARY Then
        Dim strData As Long ' As Integer
        'retrieve the key's value
        lResult = RegQueryValueEx(Ret, "SystemTime", 0, 0, strData, lDataBufSize)
        If lResult = 0 Then
            MyString = strData
        End If
    End If
End If
'Close the key
RegCloseKey Ret
bArray = StrConv( _
    MyString, vbFromUnicode _
)
Debug.Print "Dimensione array = " & UBound(bArray) - LBound(bArray) + 1
For i = LBound(bArray) To UBound(bArray)
    Debug.Print CDec("&H" & bArray(i))
Next i
End Sub
Sarebbe meglio usassi RegOpenKeyEx visto che la versione non-Ex è vecchia, ma non fa differenza ;)
Poi non ho ben capito perchè dichiari strData di tipo long ... cosi son 4 byte e quando leggi dal reg i dati binari, viene fuori un numero casuale... poi facendo l'assegnazione diretta lui converte in stringa il numero e avrai una stringa tipo "489015" (ovviamete il numero non è quello). Nel tuo caso dev'essere un numero lungo 6 cifre, ed ecco perchè son 6 byte nell'array finale.
Devi farla di tipo String, devi inizializzarla ad u numer di spazi sufficientmenete grande (usa Space$(lDataBufSize)) e poi devi passarla come gia fai adesso.
Però devi modificare la dichiarazione della funzione RegQueryValueEx cosi:
al posto di "lpData As Any" metti "ByVal lpData As String"
Puoi anche togliere MyString, non serve.
Due consigli da seguire :D :
1) controlla nelle opzioni del vb (tools > options) e spunta la prima opzione "require variable declaration" ... questo farà si che VB metta Option Explicit come prima istruzione di ogni modulo e dovrai dichiarare esplicitamente ogni variabile. E' una questione di pulizia del codice e di prestazioni dato che le var non dichiarate vengono fatte Variant, e son lente.
2) sempre nelle opzioni, alla scheda Environment, seleziona l'opzinoe save changes in basso a sx. Questo perchè quando lavori con le API di windows e soprattuto con le stringhe e le dichiarazioni delle funzioni nelle API (o con funzioni non documentate, API oscure e potenzialmente incompatibili), c'è un grosso rischio che eseguendo il debug crashi tutto per un tuo errore (puntatori rulez) e VB viene chiuso brutalmente (è mono thread come tutto il linguaggio e ciò è uno dei due grossi svantaggi di vb!!!).
Se fai cosi ogni volta che avvii il progetto ti salva automaticamente le modifice e stai al sicuro.
ciao
Poi non ho ben capito perchè dichiari strData di tipo long ... cosi son 4 byte e quando leggi dal reg i dati binari, viene fuori un numero casuale... poi facendo l'assegnazione diretta lui converte in stringa il numero e avrai una stringa tipo "489015" (ovviamete il numero non è quello). Nel tuo caso dev'essere un numero lungo 6 cifre, ed ecco perchè son 6 byte nell'array finale.
Devi farla di tipo String, devi inizializzarla ad u numer di spazi sufficientmenete grande (usa Space$(lDataBufSize)) e poi devi passarla come gia fai adesso.
Però devi modificare la dichiarazione della funzione RegQueryValueEx cosi:
al posto di "lpData As Any" metti "ByVal lpData As String"
:ave:
Ora funziona!
Avevo anche pensato di passargli una stringa, quello che mi mancava era che dovevo (e potevo!) cambiare la dichiarazione della funzione...
GRAZIE! :D
Due consigli da seguire :D :
1) controlla nelle opzioni del vb (tools > options)
Oh oh...
Lo farei volentieri, ma non ho nessuna voce "options" da nessuna parte... né nel menù tools né negli altri... né niente di simile, tipo "preferences"... :boh:
Hai idea del perché?!?
Nel menù tools ho tre voci:
Add procedure
Procedure attributes
Menu editor
Cmq, GRAZIE! :ave:
bertoz85
13-10-2005, 18:15
Oh oh...
Lo farei volentieri, ma non ho nessuna voce "options" da nessuna parte... né nel menù tools né negli altri... né niente di simile, tipo "preferences"... :boh:
Hai idea del perché?!?
Nel menù tools ho tre voci:
Add procedure
Procedure attributes
Menu editor
Cmq, GRAZIE! :ave:
ma che versione di vb hai?
posso chiederti a che serviva il programma ? :D
ciao
E' per lavoro.
Sono costretto a usare VB6.
In realtà ho già risolto con regedit e un file temporaneo; però ero curioso di capire come funziona con le API. Immagino sia più efficiente... :stordita:
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.