PDA

View Full Version : Utilizzare un API in Visual Basic


leon84
16-05-2005, 16:48
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 ????

Massi91
16-05-2005, 17:03
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

leon84
16-05-2005, 21:14
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 ... ;)

guldo76
10-10-2005, 22:45
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

guldo76
10-10-2005, 23:33
Grazie mille!!! :eek:
Ho trovato quello che mi serve, costanti comprese.
Ora (domani!) devo solo capire come usarla...
:D

bye

cionci
11-10-2005, 10:39
Per le API in VB scaricate APIGuide da www.allapi.net

guldo76
12-10-2005, 09:52
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:

cionci
12-10-2005, 11:09
E se usi la funzione per leggere una stringa ?

guldo76
12-10-2005, 11:23
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

guldo76
12-10-2005, 17:56
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

guldo76
13-10-2005, 09:56
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

guldo76
13-10-2005, 17:55
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

guldo76
13-10-2005, 22:44
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: