Lista dei lettori di SmartCard

Salve dopo un anno mi ritrovo con un piccolo problema, un pezzo del mio software legge da un lettore di smartcard i dati di una cns e finqui tutto bene il problema sorto quando sul computer dove sono andato ad installare il software ci sono due lettori attaccati, tramite la chiamata alla DLL pensavo che avrei visto l’elenco dei lettori connessi e quindi avrei potuto scegliere quale usare invece mi da sempre e solo un lettore metre se provo con un tool che ho in elenco ci sono tutti e due i lettori, di seguito riporto la chiamato alla DLL

Declare Function SCardListReaders Lib “WinScard.dll” Alias “SCardListReadersA” ( _
ByVal hContext As Integer, _
ByVal mzGroup As Cstring, _
ByVal ReaderList As Cstring, _
ByRef pcchReaders As Uint32 _
) As Integer

Dim mzGroup As String
Dim Nullo As Cstring = Nil

//
// Mi ritorna la lunghezza del buffer da predisporre in readerlen
//
retval = SCardListReaders(hContext, mzGroup, Nullo, readerlen)

Dim r As New MemoryBlock(readerlen)
Dim ReaderList As Cstring = r

//
// Mi ritorna in ReaderList l’elenco dei lettori Multistringa Nomi separati da Null
//
retval = SCardListReaders(hContext, mzGroup, ReaderList, readerlen)

Con questa chiamata mi dovrebbe restituire i lettori connessi ma mentre la lunghezza del buffer giusta, nel mio caso 57 byte, nella string ReaderList mi ritrovo solo il primo lettore seguito da tutti Null.
Se avete qualche suggerimento ve ne sarei grato.

Hai provato la classe SmartCardMBS in MBS Xojo Plugins?

Did you try SmartCardMBS class in MBS Xojo Plugins?

Non posso utilizzare plugin di terze parti, mi spiace

Dalla documentazione SCardListReadersA function

retval = SCardListReaders(Nil, Nil, Nil, readerlen)

fornisce risultati diversi?

P.S.
Nella 2a chiamata di funzione usa r al posto di ReaderList

retval = SCardListReaders(hContext, mzGroup, r, readerlen)

modificando la dichiarazione in

Declare Function SCardListReaders Lib "WinScard.dll" Alias "SCardListReadersA" ( _ ByVal hContext As Integer, _ ByVal mzGroup As Cstring, _ ReaderList As Ptr, _ ByRef pcchReaders As Uint32 _ ) As Integer

Ciao grazie per la risposta la prima chiamata non pu avere il primo parametro Null perch deve essere quello che ti viene restituito da una chiamata precedente che si chiama SCardConnect comunque la prima chiamata volendo l si pu anche evitare perch serve solo per avere la lunghezza dei dati da leggere se tu prevedi un buffer di ricezione abbastanza grande es. 256 byte non hai la necessit di farla ma puoi passare direttamente alla seconda chiamata, ho provato a modificare la chiamata sia come ReaderList As Ptr sia come ByRef in tutti e due i casi il programma si chiude senza nessuna spiegazione ne errore, comunque grazie per la risposta

Scusa prima ho sbagliato la chiamata che precede SCardEstablishContext e non SCardConnect quella e subito successiva e la si fa in base al lettore scelto

Il programma che si chiude e’ l’indicazione di qualche problema nei parametri se questo si presenta alla chiamata di SCardListReadersA.
La documentazione riporta che il primo parametro puo’ anche essere NULL.

Personalmente utilizzo sempre Ptr e Memoryblock al posto di CString: e’ piu’ chiaro dove i dati transitano ed e’ migliore l’ispezione del contenuto delle aree di scambio.
Vista la scarsita’ degli strumenti di debug e’ necessario prestare particolare attenzione alla chiamata di funzioni nelle DLL.

Continua con il debug ed eventualmente riporta ulteriori informazioni.

Saluti.

Ciao mettendo 0 (zero) al primo parametro mi ritorna la lunghezza di lettura (pcchReaders) con valore 1, cio senza senso se invece metti il valore di hContext che hai ricevuto dalla precedente chiamata ti ritorna 57 che la lunghezza giusta del buffer.
La chiamata precedente

retval = SCardEstablishContext(&h0, &h0, &h0, hContext)

in uscita hContext assume un valore, retval se 0 tutto ok altrimenti errore di chiamata.

Ora prova a scrivere un programmino in c# chiamandolo da XoJo come COM Interop e vedo cosa mi ritorna.

Perfetto, vedo che puoi usare anche altri strumenti.

Crhistian ci riprovi sempre con i tuoi PLUGIN che non fanno nulla, proprio nulla … eppure ti abbiamo chiesto più di una volta di aiutarci. ma va beh…
Pietro non posso fisicamente aiutarti perchè il certificato da CARD OS non è una cosa statica ma viene autogenerato ogni volta che si accede alla card con il PIN .
però se lo devi usare per le FATTURE ELETTRONICHE dal sito dell’agenzia delle entrate ne puoi zippare quante ne vuoi fino a 5 mbyte non firmate ed inviarle tutte assieme

Ciao Massimiliano non ho problemi con il lettore perch non devo fare la fatturazione elettronica il mio problema che quando chiedo la lista dei lettori connessi al PC mi restituisce solo il nome del primo, mi spiego meglio ho un cliente che usa il mio programma che dalla tessera sanitaria legge i dati del socio, stiamo parlando di circoli per capirci, tutto questo funziona ho trovato anche dove registrato lindirizzo di residenza e come il tracciato del record il mio problema che uno di questi circoli ha unaltro lettore collegato al PC per cui devo leggere la lista dei lettori e salvare nei parametri il mio ed invece quando chiedo la lista mi ritorna una stringa con un solo nome anche se la lunghezza di lettura invece corretta ho provato in tutti i modi ma non cambia nulla, se ti interessa ti mando i tracciati dei chip della CNS e le routine in XoJo per leggerla e come riconoscerli, tornando a me se hai qualche idea mi faresti un grosso favore.
Tra laltro il programma va benissimo e dopo i primi tre/quattro mesi di piccole correzioni ora me lo chiedono in tanti e sono molto soddisfatto sto anche implementando altre funzioni che rilascer con la nuova release prevista per giugno. Ciao e grazie

E con C# che risultati hai ottenuto?

Mi spiace ma non ho ancora avuto il tempo di provare tutta la settimana che sono i giro dai clienti spero luned di avere un poco di tempo a disposizione

Un banalita’.
Nella tua dichiarazione del metodo presente nella dll di sistema utilizzi per il parametro mzGroup il tipo CString.
Attenzione che una CString e’ una singola stringa ovvero termina sul primo byte a 0.
Se il sistema ti ritorna piu di una stringa otterrai in Xojo sempre e comunque una sola stringa indipendentemente dall’ampiezza del buffer e dal numero di stringhe presenti nel buffer.
Usa un MemoryBlock e potenzialmente risolvi il problema.

Ciao ci avevo pensato ma nella dichiarazione originale le variabili mzGroup e ReaderList sono definite come CString, comunque se mi fai un esempio di chiamata con memoryblock ci posso provare ti chiedo se hai un esempio perch finora non ho ma dovuto usare memoryblock nelle chiamate alle dll, grazie

E’ l’esempio che ti avevo riportato sopra.

[quote=424564:@Maurizio Rossi]
Nella 2a chiamata di funzione usa r al posto di ReaderList

retval = SCardListReaders(hContext, mzGroup, r, readerlen)

modificando la dichiarazione in

Declare Function SCardListReaders Lib "WinScard.dll" Alias "SCardListReadersA" ( _ ByVal hContext As Integer, _ ByVal mzGroup As Cstring, _ ReaderList As Ptr, _ ByRef pcchReaders As Uint32 _ ) As Integer[/quote]

Un MemoryBlock e’ automaticamente convertito in Ptr nelle chiamate, devi solo sostituire nella dichiarazione della funzione CString con Ptr.
Nel debugger al ritorno della chiamata dovresti vedere piu’ stringhe separate da un byte a 0.

P.S.
Non ha mai programmato in C vero?

No anzi ho scritto delle DLL in C# per interfacciare alcune utility e periferiche ad XoJo che non ha le chiamate dirette ad alcune librerie .NET per cui lo conosco bene il C#, comunque nel frattempo che aspettavo la tua risposta ho provato a fare esattamente quello che mi hai suggerito tu e mi ha dato errore XoJo in compilazione allora ho dichiarato una variabli Ptr e l’ho passata alla chiamata, nella dichiarazione della chiamata ho dovuto mettere “ByRef p As Ptr” dove “p” dichiarato “Dim p As Ptr = r” “r” il memory block se lo passi direttamente XoJo da errore dicendo che si aspettava un Ptr e invece ha ricevuto un MemoryBlock

E comunque non funziona il pogramma dopo la chiamata esce come se tu avessi fatto Quit.

Scusami Pietro ma credo che vi siano alcuni fraintendimenti.

Come riportato nella documentazione MemoryBlock “A MemoryBlock can be passed in place of a Ptr when used in a Declare call”.

Declare Function SCardListReaders Lib "WinScard.dll" Alias "SCardListReadersA" ( _ ByVal hContext As Integer, _ ByVal mzGroup As Cstring, _ ReaderList As Ptr, _ ByRef pcchReaders As Uint32 _ ) As Integer retval = SCardListReaders(hContext, mzGroup, r, readerlen)

Nel codice che ti riporto sopra dove il compilatore segnala errore se “r” e’ un MemoryBlock?

Altra cosa a cui prestare attenzione nella dichiarazione delle funzioni:

ByVal p As Ptr p As Ptr
Indica puntatore e il sigbnificato delle due notazioni e’ equivalente.

ByRef p As Ptr

Indica un puntatore ad un puntatore.

Sono due cose completamente diverse.

P.S.
Intendevo “C” non “C#”.

Risolto era proprio la dichiarazione ByRef tolto il ByRef ora funziona tutto grazie per l’aiuto