cómo obtener el nombre de archivo largo a partir de uno corto
DESCRIPTION
nombre archivoTRANSCRIPT
Cómo obtener el nombre de archivo largo a partir de uno corto
Este artículo ha sido posible gracias a la colaboración de Pere Llaveria.
Con la aparición de Windows 95 surgió el formato largo en los nombres de archivos. Hay
aplicaciones, sin embargo, que por una u otra razón necesitan trabajar con nombres de archivo
en formato corto, es decir, con un nombre de archivo limitado a 8 caracteres más 3 de
extensión. Por suerte se añadió en el API de Windows la función GetShortPathName, la cual
nos permite obtener un nombre de archivo en formato corto a partir de su formato largo.
Sin embargo, en Windows 95 no existe ninguna función que nos permita realizar el proceso
contrario. Recientemente se ha incluido la función GetLongPathName en el API, pero se
requiere Windows 98.
Podemos olvidarnos de utilizar la función GetFullPathName. A pesar de su nombre, no se
obtiene un nombre de archivo en formato largo a partir de uno corto. Su cometido es el de
generar un nombre completo de archivo a partir de la unidad y directorio actuales. Si le
pasamos como primer parámetro la ruta completa de un archivo en formato corto, nos
devolverá lo mismo en su tercer parámetro como se muestra en el ejemplo 1.
Ejemplo 1
char lpszShortPath[_MAX_PATH];
char lpszLongPath[_MAX_PATH];
char* filepart;
lstrcpy(lpszShortPath, "C:\\ARCHIV~1\\ACCESO~1\\MSPAINT.EXE");
GetFullPathName(lpszShortPath, _MAX_PATH, lpszLongPath, &filepart);
// lpszLongPath contiene "C:\\ARCHIV~1\\ACCESO~1\\MSPAINT.EXE"
Por otro lado, si sólo le pasamos un nombre de archivo sin especificar la ruta completa,
GetFullPathName generará una ruta a partir de la unidad y directorio en el que nos
encontremos actualmente como se muestra en el ejemplo 2.
Ejemplo 2
lstrcpy(lpszShortPath, "MSPAINT.EXE");
// cambiamos de directorio
SetCurrentDirectory("C:\\WINDOWS\\ESCRIT~1");
GetFullPathName(lpszShortPath, _MAX_PATH, lpszLongPath, &filepart);
// lpszLongPath contiene "C:\\WINDOWS\\ESCRIT~1\\MSPAINT.EXE"
// cambiamos de nuevo de directorio
SetCurrentDirectory("C:\\WINDOWS");
GetFullPathName(lpszShortPath, _MAX_PATH, lpszLongPath, &filepart);
// ahora lpszLongPath contiene "C:\\WINDOWS\\MSPAINT.EXE"
Hay sin embargo una manera de obtener el nombre de un archivo en formato largo y es
utilizando la función del shell SHGetFileInfo. Para ello hay que especificar
SHGFI_DISPLAYNAME en su quinto parámetro. Pero hay un pequeño problema, sólo convierte
la última parte de la ruta completa, es decir, en el caso de tener por ejemplo la ruta
C:\WINDOWS\ESCRIT~1\MIPRIM~1.EXE únicamente podríamos obtener
MiPrimerPrograma.exe correspondiente a MIPRIM~1.EXE como se muestra en el ejemplo 3.
Ejemplo 3
SHFILEINFO sfi;
lstrcpy(lpszShortPath, "C:\WINDOWS\ESCRIT~1\MIPRIM~1.EXE");
SHGetFileInfo(lpszShortPath, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME);
strcat(lpszLongPath, sfi.szDisplayName);
// lpszLongPath contiene "MiPrimerPrograma.exe"
Debido a esto es necesario llamar a la función SHGetFileInfo para cada subdirectorio
especificado en la ruta del nombre completo empezando desde el primer nivel de
subdirectorio. Seguidamente se muestra la función definitiva:
Función definitiva
DWORD GetLongPathName2(LPCSTR lpszShortPath, LPSTR lpszLongPath, DWORD cchBuffer)
{
DWORD ret;
char shortPath[_MAX_PATH];
char longPath[_MAX_PATH];
char tempPath[_MAX_PATH];
char* backslash = "\\"; // carácter donde debemos detenernos cada vez
char* token;
SHFILEINFO sfi;
ret = 0;
// comprobamos que se trata de un nombre de archivo o ruta existente
if (GetFileAttributes(lpszShortPath) != -1)
{
lstrcpy(shortPath, lpszShortPath);
token = strtok(shortPath, backslash);
ZeroMemory(tempPath, sizeof(tempPath));
strcat(tempPath, token); // ej. "C:"
strcat(tempPath, backslash); // ej. "C:\"
// empezamos a generar el nombre en formato largo
lstrcpy(longPath, token);
// leemos el primer directorio o nombre de archivo
token = strtok(NULL, backslash);
while (token != NULL)
{
// añadimos el siguiente subdirectorio o nombre de archivo
strcat(tempPath, token);
// añadimos la barra "\" al final,
// no importa si se añade al final de un nombre de archivo
strcat(tempPath, backslash);
// obtenemos el nombre en formato largo en el campo sfi.szDisplayName
SHGetFileInfo(tempPath, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME);
// vamos añadiendo lo último convertido a la cadena en formato largo
strcat(longPath, backslash);
strcat(longPath, sfi.szDisplayName);
// leemos el siguiente directorio o nombre de archivo,
// si ya se han leído todos, devolverá un puntero nulo
token = strtok(NULL, backslash);
}
// obtenemos el número de caracteres que forman el nombre completo
ret = strlen(longPath);
if (cchBuffer >= ret)
{
// copiamos el nombre obtenido en el primer parámetro de la función
lstrcpy(lpszLongPath, longPath);
}
}
return ret;
}