Domanda

voglio a persistere alcuni nomi di file per l'utente (ad esempio file recenti).

Facciamo uso sei file di esempio:

  • c:\Documents & Settings\Ian\My Documents\Budget.xls
  • c:\Documents & Settings\Ian\My Documents\My Pictures\Daughter's Winning Goal.jpg
  • c:\Documents & Settings\Ian\Application Data\uTorrent
  • c:\Documents & Settings\All Users\Application Data\Consonto\SpellcheckDictionary.dat
  • c:\Develop\readme.txt
  • c:\Program Files\Adobe\Reader\WhatsNew.txt

Ora sto percorso alle cartelle speciali hard-codifica. Se l'utente reindirizza le loro cartelle, si aggira su un altro computer, o aggiorna il proprio sistema operativo, saranno rotti i percorsi:

Voglio essere un buon sviluppatore, e convertire questi hard-coded assoluto percorsi per relativa percorsi dal appropriata cartelle speciali :

  • %CSIDL_Personal%\Budget.xls
  • %CSIDL_MyPictures%\Daughter's Winning Goal.jpg
  • %CSIDL_AppData%\uTorrent
  • %CSIDL_Common_AppData%\Consonto\SpellcheckDictionary.dat
  • c:\Develop\readme.txt
  • %CSIDL_Program_Files%\Adobe\Reader\WhatsNew.txt

La difficoltà viene fornito con il fatto che non ci può essere rappresentazioni multiple per lo stesso file, per esempio:.

  • c:\Documents & Settings\Ian\My Documents\My Pictures\Daughter's Winning Goal.jpg
  • %CSIDL_Profile%\My Documents\My Pictures\Daughter's Winning Goal.jpg
  • %CSIDL_Personal%\My Pictures\Daughter's Winning Goal.jpg
  • %CSIDL_MyPictures%\Daughter's Winning Goal.jpg

Si noti inoltre che in Windows XP My Pictures sono memorizzate My Documents:

%CSIDL_Profile%\My Documents
%CSIDL_Profile%\My Documents\My Pictures

Ma su Vista / 7 sono separati:

%CSIDL_Profile%\Documents
%CSIDL_Profile%\Pictures
  

Nota: mi rendo conto la sintassi   %CSIDL_xxx%\filename.ext non è valido; quello   Windows non espandere le parole chiave   come sono stringhe di ambiente. Sono solo   usarlo come un modo per chiedere questo   domanda. Internamente lo farei, ovviamente,   memorizzare gli elementi in qualche altro modo, forse come CSIDL genitori   e la coda del percorso, per esempio:.

 CSIDL_Personal         \Budget.xls
 CSIDL_MyPictures       \Daughter's Winning Goal.jpg
 CSIDL_AppData          \uTorrent
 CSIDL_Common_AppData   \Consonto\SpellcheckDictionary.dat
 -1                     c:\Develop\readme.txt   (-1, since 0 is a valid csidl)
 CSIDL_Program_Files    \Adobe\Reader\WhatsNew.txt

La questione diventa, come utilizzare, per quanto possibile, i percorsi relativi alle cartelle speciali canoniche?


Sto pensando:

void CanonicalizeSpecialPath(String path, ref CSLID cslid, ref String relativePath)
{
   return "todo";
}

Vedi anche

È stato utile?

Soluzione

Immagino che si potrebbe scoprire come la mappa CSIDL ai percorsi (usando qualcosa come SHGetKnownFolderPath ), costruire un dizionario inverso di loro, quindi verificare se l'inizio del percorso che si desidera memorizzare corrisponde a uno dei tasti nel dizionario e quindi rimuovere l'inizio e conservare il CSIDL che ha trovato.

Non apertamente elegante, ma dovrebbe ottenere il lavoro svolto.

Altri suggerimenti

function CanonicalizeSpecialPath(const path: string): string;
var
    s: string;
    BestPrefix: string;
    BestCSIDL: Integer;
    i: Integer;
begin
    BestPrefix := ''; //Start with no csidl being the one
    BestCSIDL := 0;

    //Iterate over the csidls i know about today for Windows XP.    
    for i := Low(csidls) to High(csidls) do
    begin
       //Get the path of this csidl. If the OS doesn't understand it, it returns blank
       s := GetSpecialFolderPath(0, i, False);
       if s = '' then
          Continue;

       //Don't do a string search unless this candidate is larger than what we have
       if (BestPrefix='') or (Length(s) > Length(BestPrefix)) then
       begin
          //The special path must be at the start of our string
          if Pos(s, Path) = 1 then //1=start
          begin
             //This is the best csidl we have so far
             BestPrefix := s;
             BestCSIDL := i;
          end;
       end;
    end;

    //If we found nothing useful, then return the original string
    if BestPrefix = '' then
    begin
       Result := Path;
       Exit;
    end;

    {
       Return the canonicalized path as pseudo-environment string, e.g.:

           %CSIDL_PERSONAL%\4th quarter.xls
    }
    Result := '%'+CsidlToStr(BestCSIDL)+'%'+Copy(Path, Length(BestPrefix)+1, MaxInt);
end;

E poi c'è una funzione che "espande" i particolari parole chiave ambiente:

function ExpandSpecialPath(const path: string): string;
begin
   ...
end;

che si espande:

%CSIDL_PERSONAL%\4th quarter.xls

in

\\RoamingProfileServ\Users\ian\My Documents\4th quarter.xls

Lo fa con la ricerca di% xx% di inizio della stringa, ed espandendolo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top