Scrivere dati nel Registro di Sistema (Regedit) e recuperarli quando servono. - pagina vista: volte PRIMA PARTE: Requisiti: buona conoscenza procedure VBA - Conoscenza accesso e struttura del Registro di Sistema (Registro di configurazione). Prima che qualcuno faccia dei danni al proprio o altrui registro di sistema, è opportuno che chi si accinge a leggere questo articolo, possieda i requisiti richiesti.
La prima istruzione che ci interessa è l'Istruzione SaveSetting che consente di salvare o creare una voce per un'applicazione nel registro di configurazione di Windows; questa istruzione richiede che vengano precisati quattro argomenti tutti obbligatori, e cioè
Quindi, tanto per fare un esempio, se con appname decidiamo di usare la voce "Excelmio", con Section impostiamo la parola "wbookopen", con key impostiamo la parola "passw", e come setting usiamo il valore "elios", i quattro argomenti creeranno queste 4 voci/valori nel registro: e l'istruzione vba che ha prodotto il risultato visto sopra, è questa:
come si nota è una istruzione semplice, veloce ed efficace, ed essendo tutti e quattro gli argomenti rappresentati da testo (sono stringhe), devono essere passati tra doppi apici; se al posto di "elios" come "valore" avessimo passato un numero, avremmo usato il numero così come scritto, senza doppi apici. Gli inserimenti registrati tramite il vba di Excel li troveremo nel seguente percorso del Registro di configurazione: HKEY_CURRENT_USER\Software\VB and VBA Program Settings\appname da voi scelto importante: gli argomenti devono necessariamente essere separati da una virgola, e se rilanciamo l'istruzione, le chiavi create non vengono riscritte ma sovrascritte alle stesse esistenti; ciò consente ad esempio di modificare un valore ("setting"), oppure di aggiungere nuove "key" con nuovi "setting", riscrivendoli nella stessa sezione (section) dello stesso nome programma (appname), dove pure sarà possibile aggiungere altre sezioni con relative chiavi e relativi valori. Bene, abbiamo visto come poter scrivere dei dati nel registro di configurazione, e mi sembrano evidenti le implicazioni di tale attività; la nostra utilità sarà quella di poter memorizzare valori e istruzioni in qualcosa che rimane "acceso" anche dopo che avremo "spento" Excel, cioè dopo che avremo chiuso il nostro programma xls. Potremo quindi evitare di "memorizzare" dati e valori in celle di nessun foglio, nascondendo meglio ad esempio una password di accesso (eventuali programmi di recupero password infatti le cercano nel file xls protetto), oppure ottenere dati che potranno essere richiamati alla riapertura della cartella con la quale abbiamo generato le nostre chiavi e che potremo "richiamare" quando vorremo. In pratica usiamo il Registro di Configurazione come una banca dati (occhio a non esagerare, rischiando di "intasare" il Registro con migliaia di voci che servono solo al nostro programma ....)
La seconda istruzione. L'istruzione che serve a recuperare i "valori" precedentemente scritti, è la funzione GetSetting , (esiste anche la funzione GetAllSettings di cui non parliamo in questo articolo) che restituisce un valore (il "setting" visto sopra) di impostazione di chiave da una voce del registro di configurazione di Windows. In pratica questa funzione restituirebbe, dall'esempio fatto sopra, solo il valore "elios" e non altro. La funzione GetSetting richiede quattro argomenti predefiniti di cui solo i primi tre sono obbligatori:
Se uno qualsiasi degli argomenti della funzione GetSetting non esiste, la funzione restituisce il valore di default. L'istruzione quindi per il recupero (o il confronto) con GetSetting sarebbe, per l'esempio fatto sopra:
e a conferma che se eliminiamo l'argomento default che è facoltativo, anche la sottostante istruzione restituirebbe il valore registrato che è "elios" :
Dal momento che la restituzione tramite GetSetting ci restituisce solo il "valore" assegnato ad una chiave (key), dovremo usare una variabile come contenitore di detto valore, e se detto valore dovrà essere numerico, potremo usare una "funzione di conversione del tipo" (vedi in questa sezione sul sito, "Variabili e Tipi di dati"). Proviamo a fare un esempio con una istruzione che valuti, all'apertura di una cartella, quindi con una routine richiamata nell'evento WorkBook_Open (o direttamente ivi scritta), la password precedentemente inserita nel Registro di configurazione tramite l'istruzione SaveSetting; potremo quindi far chiudere la cartella se la password è errata, oppure dare accesso alla cartella. Nella routine sotto faccio solo apparire due messaggi come esempio del funzionamento. Usiamo una InputBox come richiesta per l'inserimento della password per accedere
Qualcuno si chiederà: ma come faccio a far trovare le chiavi scritte nel Registro di configurazione per poterle controllare, se all'apertura della cartella pongo subito l'istruzione di controllo? Semplice, usiamo lo stesso evento, quello del WorkBook_Open per lanciare per prima l'istruzione SaveSetting (che se anche ripetuta sovrascrive i dati senza far danni), e subito dopo la routine per il controllo, esempio con il richiamo delle due macro, poste nel WorkBook_Open:
Come si nota il confronto avviene tra ciò che scriviamo in una inputbox ed un valore NON contenuto nella cartella, quindi dovremmo essere tranquilli che sarà difficile scoprire che la password è "elios"; invece è tutta un'illusione: infatti chiunque, disattivando l'esecuzione delle macro che Excel chiede (si/no) può andare a leggersi le istruzioni contenute nelle macro della cartella( compreso la macro Registra()), e neppure se avremo protetto con altra password l'accesso al VBAProject saremo tranquilli; anche quest'ultima password è facilmente valicabile. L'esempio con il controllo password è fatto SOLAMENTE come esempio per spiegare il funzionamento delle istruzioni. Oppure di aprire il Registro al percorso indicato (HTKEY_ ecc) e cercare qualcosa che assomigli ad un salvataggio "casereccio". Una parziale soluzione di mascheramento potrebbe essere quella di usare un appname tipo "PresenterSoftPowerVideoMaccher" con una section tipo "VisData69" una Key "NotAcceleration" ed un setting tipo "Euroview" (la vera password), insomma, tutti nomi difficilmente riconducibili ad una cartella xls o ad una password.
Registrare (e ricaricare) dati da componenti ActiveX di UserForm (TextBox, ListBox, etc) in due parti. Prima Parte. Ora facciamo un esercizio più consono alle possibilità che queste istruzioni possono offrire: salvare dei dati contenuti in una ListBox posta su una userform, in modo che alla riapertura della cartella, la stessa ListBox "ricarichi" la stessa lista dati. Condizione necessaria è che in una fase iniziale, prima del primo salvataggio, si sia caricata la ListBox con dati sfruttando uno dei metodi tradizionali (*Additem oppure assegnando un'intervallo dati al RowSource della ListBox). *Ricordo che col
metodo AddItem è possibile inserire dati in una ListBox in fase di
esecuzione, sfruttando ad esempio una InputBox. Si potrà obiettare: "ma non facciamo prima a salvare detta lista in un foglio di lavoro?", certo, ma supponendo che NON si voglia lasciare una lista dei dati salvata su fogli che altri utenti vedono, e però averla a disposizione in quanto "salvata" in una posizione esterna al file? Qualunque sia il motivo, esamineremo un esempio in tal senso. La prima considerazione da fare è che dovremo reperire tante chiavi (Key) quanti saranno i valori nella lista della ListBox; potremmo creare una matrice contenenti le chiavi, ma possiamo seguire una strada che ci farà risparmiare un bel pò di istruzioni: i dati in una ListBox sono riconoscibili dal numero di riga o di lista (List) oltre che dal valore (sia esso un nome, un numero o altro) stesso (e dal numero di colonna, che con una sola colonna sarà la colonna numero 0); dovremo quindi pensare ad associare tali valori al loro numero di lista, in modo da adoperare il numero di lista come chiave (Key) ed il valore come settaggio (setting) di quella chiave. Chiaro?? Per eseguire questa associazione useremo un ciclo For ..Next che "girerà" tante volte quanti sono i valori (e quindi le righe) della lista, e per ogni ciclo scriverà nel Registro di configurazione (d'ora in poi chiamato Registro) usando l'istruzione SaveSetting. La seconda considerazione da fare e che, per "recuperare", non è possibile "scorrere" oppure "contare" esattamente quanti sono i valori registrati nel Registro come chiavi del nostro programma, per poter determinare il ciclo di "ritorno dati", cioè il "recupero" dei valori per ricaricare la ListBox: per cui, nel momento in cui usiamo il SaveSetting, inseriremo una chiave "quanti" che porterà come valore di setting il numero dei valori salvati. Con GetSetting leggeremo quindi per primo il valore numerico della chiave "quanti" e lo useremo come limite superiore del ciclo di "recupero", meno 1; si, meno 1 perchè nel salvataggio noi siamo partiti a salvare dalla chiave 0 (zero) che è il numero della prima riga o lista di una ListBox. Vediamo due immagini che ci mostrano una ListBox con 6 nomi, e il Registro con le sei chiavi (key) salvate (i numeri di riga) e relativi valori (i nomi): Per automatizzare il richiamo dei dati nella ListBox, potremmo lanciare le due istruzioni (quella per salvare: SaveSetting e quella per ricaricare la listBox : GetSetting) sfruttando due eventi dell'UserForm su cui risiede la Listbox: l'evento Activate per caricare la ListBox e l'evento Terminate per salvare i dati presenti nella ListBox, ma si possono verificare le seguenti situazioni non gestibili:
Suggerisco quindi di creare due routine distinte Sub SalvaLista() e Sub RiCaricaLista() da lanciare con due CommandButton preposti appunto al salvataggio e al richiamo dei dati nel e dal Registro. Se poi il lettore è smaliziato troverà le giuste azioni da compiere per salvare e caricare, sfruttando eventi dell'userform e/o CommandButton, tenendo altresì presente che se l'applicativo gira sul proprio computer sarà possibile sfruttare un commandbutton una sola prima volta, per registrare dati della listbox, e modificare poi le istruzioni automatizzando con gli eventi Activate e Terminate il lancio delle istruzioni (infatti avremo già i dati memorizzati nel Registro) Queste le istruzioni:
E' nelle istruzioni di "recupero" che è più necessario istruire una gestione degli errori, in quanto se nel registro non vengono trovati i dati cercati si genera un errore; in questo esempio, se si genera un errore, io rimando alla routine SalvaLista, che provvede ad avvisare con un messaggio:
Sarà quindi ora possibile sfruttare il richiamo alle due macro negli eventi Activate (Sub RicaricaLista) e Terminate (Sub SalvaLista).
La terza istruzione. Se desideriamo
eliminare dal Registro le voci che abbiamo registrato possiamo utilizzare l'
Istruzione DeleteSetting che
consente appunto di eliminare un'impostazione di sezione (setting) o
di chiave (key) dalla voce del registro di configurazione di Windows
(quindi NON è consentita l'eliminazione della voce corrispondente all'
appname).
Quindi, proseguendo con il primo esempio dell'articolo, se volessimo cancellare il settaggio (o valore) "elios" dalla chiave (key) "passw" dovremmo scrivere:
Se invece usassimo la seguente istruzione elimineremo anche la sezione specificata oltre che chiavi e relativi settaggi:
Attenzione : Se si utilizza l'istruzione DeleteSetting in una impostazione di sezione o di chiave non esistente, verrà generato un errore di run-time, sarà quindi opportuno inserire anche una gestione degli errori.
Sempre per restare in tema di ListBox vediamo come cambiano le istruzioni se vogliamo salvare e poi recuperare i dati di una ListBox multicolonna; intanto sappiamo che per avere più di una sola colonna (di default, con indice 0) è necessario impostare la proprietà ColumnCount della ListBox al valore di colonne desiderato; farò un esempio con 4 colonne. Ci affideremo a due routine separate che potremo, in seguito al primo salvataggio, automatizzare con eventi della UserForm. Farei comunque una precisazione per aiutare a capire il "meccanismo" impiegato: ci troviamo, con una ListBox multicolonna, a dover gestire una situazione a due dimensioni , righe e colonne, quindi due serie di indici (indice riga e indice colonna) mentre nel Registro, questi indici che saranno le "chiavi", sono obbligatoriamente monodimensionali: solo una unica colonna di dati. Dovendo utilizzare sia per salvare, sia per ricaricare, doppi cicli For Next che scorrano le righe e le colonne, con relativi contatori di ciclo, diventa impossibile gestire il salvataggio ed il recupero che richiedono un solo contatore, altro problema è rappresentato dalla proprietà List(numeroriga, numerocolonna) della ListBox che appunto richiede due valori. Si risolve (senza matrici) con un terzo contatore incrementale, che ad ogni ciclo letto (riga e colonna), si incrementi di 1 unità, e adoperiamo quindi questo contatore come chiave (key) di registrazione e/o di lettura. Le istruzioni che leggeremo sotto, si riferiscono a questa situazione: una ListBox con 5 righe e 4 colonne, quindi 20 chiavi (key) da memorizzare, contando anche lo zero si memorizza fino al 19:
Per ricaricare la ListBox, useremo anche in questo caso un "contatore" che ci consentirà di "leggere" la giusta chiave e reperirne il settaggio (o valore di chiave che dir si voglia). Poichè dovremo anche in questo caso sfruttare la proprietà List per aggiungere i dati letti, e detta proprietà non può lavorare se non si aprono prima le righe necessarie, sfruttiamo un ciclo che usando Additem a vuoto, aprirà tante righe quante lette nella chiave "righe" del Registro.
E' ovvio che le istruzioni suggerite per le ListBox poste su UserForm sono valide anche per le ComboBox. Per ora è tutto, a breve presenterò un successivo articolo per spiegare come salvare nel registro dati e/o impostazioni contenute in TextBox, OptionButton, CommandButton, etc.
prelevato sul sito www.ennius.altervista.org |