我想为用户保留一些文件名(例如最近的文件)。
我们使用六个示例文件:
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
我现在硬编码path到特殊文件夹。 如果用户redirect他们的文件夹,漫游到另一台计算机,或升级他们的操作系统,path将被打破:
我想成为一名优秀的开发人员,并将这些硬编码的绝对path从适当的特殊文件夹转换为相对path:
%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不会像环境string那样扩展这些关键字。 我只是用它来问这个问题。 在内部,我会明显地将项目以其他方式存储,也许作为CSIDL
父项和path的尾部,例如: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
问题在于,如何尽可能地使用相对于规范化特殊文件夹的path?
我在想:
void CanonicalizeSpecialPath(String path, ref CSLID cslid, ref String relativePath) { return "todo"; }
我想你可以找出CSIDL如何映射到路径(使用类似SHGetKnownFolderPath的东西),建立它们的反向字典,然后检查你想存储的路径的开始是否与字典中的任何键匹配,然后删除开始并存储匹配的CSIDL。
不公然优雅,但它应该完成工作。
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, eg: %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%并将其展开来实现。