Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
Windows - Ricavare il percorso del Desktop
Forum - Windows - Ricavare il percorso del Desktop

Avatar
()
Newbie


Messaggi:
Iscritto:

Segnala al moderatore
Postato alle 1:00
Giovedì, 01/01/1970
Una cosa di cui mi capita spesso d'aver bisogno è il percorso della cartella del Desktop di Windows. Ho provato a elaborare una via per ricavarla "leggendo" il registro di sistema che vorrei proporre alla vostra attenzione.

Codice sorgente - presumibilmente C#

  1. // le variabili globali nelle quali immazzino il percorso del Desktop
  2. DWORD gDPd = MAX_PATH;    // [g]lobale [D]imensioni [P]ercorso [d]esktop
  3. BYTE gPd[MAX_PATH] = "";  // [g]lobale [P]ercorso [d]esktop
  4.  
  5. // il prototipo della funzione che "legge" il registro di sistema
  6. LONG RicavaPercorsoShell( const char *nomeEl, HKEY chiave = HKEY_CURRENT_USER, int nLiv = 0 );
  7.  
  8. // una funzione per segnalare gli eventuali errori
  9. void DescriviErroreRegistro( LONG id ) {
  10.     char msg[128];
  11.     FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, id, 0, msg, 127, NULL );
  12.     MessageBox( NULL, msg, "Errore", MB_OK );
  13. }
  14.  
  15. // l'implementazione delle funzione che "legge" il registro di sistema
  16. LONG RicavaPercorsoShell( const char *nomeEl, HKEY chiave, int nLiv ) {
  17.     static const int kTotLiv = 6;
  18.     static const char *kNomiLiv[kTotLiv] = { "Software", "Microsoft",
  19.         "Windows", "CurrentVersion", "Explorer", "Shell Folders" };
  20.  
  21.     static char buff[MAX_PATH];
  22.     static DWORD dimBuff;
  23.     LONG esito = ERROR_SUCCESS;
  24.     int i;
  25.  
  26.     for( i=0; esito!=ERROR_NO_MORE_ITEMS && esito!=-1; ++i ) {
  27.         dimBuff = MAX_PATH;
  28.  
  29.         esito = RegEnumKeyEx( chiave, i, buff, &dimBuff, 0, NULL, NULL, NULL );
  30.  
  31.         if( esito!=ERROR_SUCCESS && esito!=ERROR_NO_MORE_ITEMS ) goto uscita;
  32.  
  33.         if( lstrcmp(buff,kNomiLiv[nLiv]) == 0 ) {
  34.             esito = RegOpenKeyEx( chiave, buff, 0, KEY_EXECUTE, &chiave );
  35.             if( esito != ERROR_SUCCESS ) goto uscita;
  36.  
  37.             if( ++nLiv < kTotLiv ) { // chiama ricorsivamente se stessa
  38.                 esito = RicavaPercorsoShell( nomeEl, chiave, nLiv );
  39.             }
  40.             else { // ora e' aperta la chiave che contiene il percorso richiesto
  41.                 for( i=0, dimBuff=MAX_PATH;
  42.                     esito!=ERROR_NO_MORE_ITEMS && esito!=-1;
  43.                     ++i, dimBuff=MAX_PATH ) {
  44.  
  45.                     esito = RegEnumValue(
  46.                         chiave, i, buff, &dimBuff, 0, NULL, gPd, &gDPd );
  47.  
  48.                     if( esito != ERROR_SUCCESS &&
  49.                         esito != ERROR_MORE_DATA &&
  50.                         esito != ERROR_NO_MORE_ITEMS ) {
  51.                         *gPd = '\0';
  52.                         goto uscita;
  53.                     }
  54.  
  55.                     if( lstrcmp(buff,nomeEl)==0 ) esito = -1;
  56.                 }
  57.             }
  58.         }
  59.     }
  60.  
  61.     uscita:
  62.  
  63.     if( chiave != 0 ) {
  64.         RegCloseKey( chiave );
  65.         chiave = 0;
  66.     }
  67.  
  68.     return esito;
  69. }



Sul Windows 7 sul quale ho testato il metodo la soluzione funziona, ma mi chiedo se sia un metodo affidabile o se possa essere fonte di disguidi. Chi volesse darci un'occhiata tenga presente che son solito chiamare la funzione una sola volta al momento dell'avvio del programma e memorizzare il percorso del Desktop in una variabile globale per usi futuri.

Posso migliorare qualcosa? Conviene cambiare completamente approccio? Che ne dite?

P.S. xPiero: E' abbastanza spaghettico? :)

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6328
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 17:40
Giovedì, 02/10/2014
Mah ... a parte il fatto che al posto dei tre

goto uscita

avrei scritto semplicemente

break;

la questione è un'altra ... perché leggi da registro per ottenere la cartella del desktop?
Personalmente farei con queste 3 righe

Codice sorgente - presumibilmente Windows

  1. #include <Shlobj.h>
  2.  
  3. TCHAR desk[MAX_PATH];
  4. SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, desk);



Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti (uno dei padri fondatori del moderno Calcolo delle probabilità) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
()
Newbie


Messaggi:
Iscritto:

Segnala al moderatore
Postato alle 18:45
Giovedì, 02/10/2014
Ci sono delle ragioni (magari sciocche, non so) almeno per l'ultimo dei goto. Se uso un break al posto dell'ultimo goto esco dal ciclo for più interno ma non da quello più esterno. Siccome il for interno reinizializza i su 0, se torno al for esterno entro in un ciclo infinito (è ben vero che avrei potuto usare un contatore diverso, con una variabile apposita). Questo se ho seguito ragionamenti sensati, e non è detta...

In merito all'usare o non usare SHGetFolderPath(), devo ammettere che ci ho provato, ma probabilmente non sono riuscito a capire bene la documentazione, perché il compilatore continuava a lamentarsi per l'impossibilità di usare quella funzione; un po' piccato, per questo ho di malavoglia elaborato la mia soluzione schizofrenica.

Vedo che hai incluso un "misterioso" header Shlobj.h... magari quello rende il compilatore un po' più "collaborativo", ci proverò. Devo anche collegare qualche libreria? Tipo quando includi gdiplus.h, intendo, e devi dare istruzione al linker di collegare gdiplus.lib.

Certo è che se mi funziona SHGetFolderPath() butto via alla velocità della luce la mia funzione "barocca"! Tre righe di codice sono effettivamente meglio di settanta, e poi c'è il rischio affidabilità che adombravo.

EDIT (qualche minuto dopo):

Uàaaaaa!!! Includendo shlobj.h funziona alla grande. Certo è che se quei buontemponi che han scritto la documentazione nascondono le informazioni sotto al tappeto non è che uno se le può sognare. Grazie mille, da solo avrei continuato a seguire una strada inutilmente tortuosa e probabilmente inaffidabile. SHGetFolderPath() mi sarà senz'altro utile in mille circostanze (anche se su msdn l'hanno etichettata come "deprecated"). Nel cestino la mia funzione "barocca" e spaghettosa.

Ultima modifica effettuata da il 02/10/2014 alle 19:07
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6328
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 20:29
Giovedì, 02/10/2014
Testo quotato

Postato originariamente da AldoBaldo:
Ci sono delle ragioni (magari sciocche, non so) almeno per l'ultimo dei goto.



Sì, non avevo notato il secondo for e quindi per l'ultimo goto non basta un break ma è necessario una seconda if dopo la for che esegua un altro break. E' comunque meglio del goto.

Per la SHGetFolderPath() è deprecata perché praticamente usata fino ad XP (anche se funzionante).

Da Vista in poi dovresti usare la nuova funzione SHGetKnownFolderPath() in modo simile

Codice sorgente - presumibilmente Plain Text

  1. LPWSTR szPath;
  2.         SHGetKnownFolderPath(FOLDERID_Desktop, 0, 0, &szPath);






Ultima modifica effettuata da nessuno il 02/10/2014 alle 21:56


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti (uno dei padri fondatori del moderno Calcolo delle probabilità) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
()
Newbie


Messaggi:
Iscritto:

Segnala al moderatore
Postato alle 21:17
Giovedì, 02/10/2014
Testo quotato

Postato originariamente da nessuno:
Da Vista in poi dovresti usare la nuova funzione SHGetKnownFolderPath() in modo simile

Codice sorgente - presumibilmente Windows

  1. TCHAR desk[MAX_PATH];
  2.         SHGetKnownFolderPath(FOLDERID_Desktop, 0, NULL, desk);






Per qualche ragione questa versione non funziona sul mio Code::Blocks. La lamentela è questa:

Codice sorgente - presumibilmente Delphi

  1. ||=== Build: Debug in Esperimento (compiler: GNU GCC Compiler) ===|
  2. C:\...\main.cpp||In function 'int WinMain(HINSTANCE, HINSTANCE, LPSTR, int)':|
  3. C:\...\main.cpp|48|error: 'FOLDERID_Desktop' was not declared in this scope|
  4. C:\...\main.cpp|48|error: 'SHGetKnownFolderPath' was not declared in this scope|
  5. ||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 2 second(s)) ===|



E' come se il file di intestazione non facesse a modo il suo dovere.

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6328
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 21:19
Giovedì, 02/10/2014
Quale sistema operativo usi? Quale versione di compilatore?


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti (uno dei padri fondatori del moderno Calcolo delle probabilità) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
()
Newbie


Messaggi:
Iscritto:

Segnala al moderatore
Postato alle 22:00
Giovedì, 02/10/2014
Il sistema operativo è Windows 7 Starter.
Il compilatore è il GNU GCC che veniva distribuito nell'installatore di Code::Blocks quando è uscita la versione 13.12 del programma. Il file "leggimi" contenuto nella cartella MinGW dice così:

=== TDM-GCC Compiler Suite for Windows ===
---        GCC 4.6 & 4.7 Series        ---
***   Standard MinGW 32-bit Edition    ***

Spero che siano dati esatti e sufficienti.

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6328
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 22:08
Giovedì, 02/10/2014
Non so quale sdk hai installato ma devi aggiornarlo.

Ad esempio, con VS2010 c'è già installato il 7.0A che va bene, ma puoi scaricarne anche uno più recente ed installarlo per il gcc e c::b ...


Ultima modifica effettuata da nessuno il 02/10/2014 alle 22:09


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti (uno dei padri fondatori del moderno Calcolo delle probabilità) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
()
Newbie


Messaggi:
Iscritto:

Segnala al moderatore
Postato alle 22:16
Giovedì, 02/10/2014
Ti ringrazio davvero tanto per le dritte. Già indicandomi l'inclusione di shlobj.h mi hai aiutato un sacco (giammai mi sarebbe venuto in mente). Prendo senz'altro in considerazione il tuo suggerimento di cercare versioni più aggiornate di compilatore e sdk windows, anche se sono piuttosto impedito in questo genere di cose (s'era capito?).

Tra l'altro, ho già rimosso la mia funzione spaghettosa dal programma che sto giocando a realizzare e l'ho sostituita secondo le tue indicazioni. Funziona tutto alla grande. Nei prossimi giorni integrerò SHGetFolderPath() anche in un altro paio di progettini coi quali mi sto divertendo.

PM Quote