Windows: cómo canonicalize un archivo en la carpeta especial?
-
02-10-2019 - |
Pregunta
quiero persistir algunos nombres de archivo para el usuario (por ejemplo, archivos recientes).
Vayamos de uso seis archivos de ejemplo:
-
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
Ahora estoy ruta a carpetas especiales y difíciles de codificación. Si el usuario vuelve a dirigir sus carpetas, esté conectado a otra computadora, o actualiza su sistema operativo, los caminos se pueden dividir:
quiero ser un desarrollador bueno, y convertir éstos no modificable absoluta ??em> rutas de acceso a relativa Trazados de la adecuada carpetas especiales :
-
%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 dificultad viene con el hecho de que no puede haber múltiples representaciones para el mismo archivo, por ejemplo:.
-
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
Tenga en cuenta también que en Windows XP Mis imágenes se almacenan My Documents
:
%CSIDL_Profile%\My Documents
%CSIDL_Profile%\My Documents\My Pictures
Pero en Vista / 7 están separadas:
%CSIDL_Profile%\Documents
%CSIDL_Profile%\Pictures
Nota: i cuenta de la sintaxis
%CSIDL_xxx%\filename.ext
no es válido; ese Windows no se expandirá las palabras clave como son cadenas de entorno. Solo soy usarlo como una manera de hacer esta pregunta. Internamente me gustaría, obviamente, almacenar los elementos de alguna otra manera, tal vez como unCSIDL
padres y la cola de la ruta, por ejemplo:.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 pregunta es, cómo utilizar, tanto como sea posible, caminos relativa a las carpetas especiales canónicos?
Estoy pensando en:
void CanonicalizeSpecialPath(String path, ref CSLID cslid, ref String relativePath)
{
return "todo";
}
Ver también
- MSDN: CSIDL Enumeración
- New Old cosa: Cuidado con los perfiles de usuario móviles
- New Old cosa: Cuidado con las carpetas redirigidas, también
- MSDN: PathCanonicalize Función
Solución
supongo que se podría averiguar cómo el mapa CSIDL de caminos (usando algo así como SHGetKnownFolderPath ), construir un diccionario inverso de ellos, a continuación, comprobar si el principio de la ruta que desea almacenar coincide con alguna de las teclas en el diccionario y luego retire el principio y almacenar el CSIDL que coincidía.
No abiertamente elegante, pero debe hacer el trabajo.
Otros consejos
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;
Y entonces hay una función que "se expande" las palabras clave de entorno especiales:
function ExpandSpecialPath(const path: string): string;
begin
...
end;
que se expande:
%CSIDL_PERSONAL%\4th quarter.xls
en
\\RoamingProfileServ\Users\ian\My Documents\4th quarter.xls
Lo hace mediante la búsqueda de% xx% al inicio de la cadena, y la ampliación de la misma.