Windows: Как канонизировать файл к специальной папке?

я хочу для сохранения некоторых имен файлов для пользователя (например, недавние файлы).

Давайте использовать шесть файлов в качестве примера:

  • 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

я - теперь путь жесткого кодирования к специальным папкам. Если пользователь перенаправит их папки, переместится к другому компьютеру или обновит их операционную систему, то пути будут повреждены:

я хочу быть хорошим разработчиком и преобразовать эти трудно кодированные полные пути в относительные пути от соответствующих специальных папок:

  • %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

Трудность идет с тем, что может быть несколько представлений для того же файла, например:

  • 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

Обратите внимание также, что в Windows XP Мои Изображения хранятся в My Documents:

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

Но на Vista/7 они являются отдельными:

%CSIDL_Profile%\Documents
%CSIDL_Profile%\Pictures

Примечание: я понимаю синтаксис %CSIDL_xxx%\filename.ext не допустимо; тот Windows не развернет те ключевые слова как, они - строки среды. я только использую его в качестве способа задать этот вопрос. Внутренне я, очевидно, сохранил бы объекты некоторый другой путь, возможно, как a CSIDL родитель и хвост пути, например:

 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

Вопрос становится, как использовать, как можно больше, пути относительно канонических специальных папок?


Я думаю:

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

См. также

6
задан Ian Boyd 5 July 2010 в 19:42
поделиться

2 ответа

Я полагаю, вы можете узнать, как CSIDL отображаются на пути (используя что-то вроде SHGetKnownFolderPath), построить обратный словарь из них, затем проверить, совпадает ли начало пути, который вы хотите сохранить, с любым из ключей в словаре, затем удалить начало и сохранить CSIDL, который совпал.

Не слишком элегантно, но это поможет выполнить работу.

2
ответ дан 17 December 2019 в 07:00
поделиться
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;

А еще есть функция, которая «расширяет» ключевые слова специальной среды:

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

, которая расширяет:

%CSIDL_PERSONAL%\4th quarter.xls

в

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

. Она делает это, ища% xx% в начале строку и растягивая ее.

2
ответ дан 17 December 2019 в 07:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: