Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > API de Windows
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 23-03-2008
jhonalone jhonalone is offline
Miembro
 
Registrado: sep 2007
Ubicación: Madrid
Posts: 547
Poder: 17
jhonalone Va por buen camino
¿Cómo obtener nombres Ficheros MS-DOS?

Necesito un método fiable, para obtener los nombres de fichero abreviados, es decir (8.3).
He desarrollado una utilidad con FindFirst que lo consigue, pero (siempre tiene que haber algun pero) aunque, aparentemente funciona bien, la he probado en mi antiguo sistema Windows ME, cuyo MS-DOS todavía los edita en este formato y en general muy bien.
El "pero" es el siguiente: cuando existen más de un fichero que tienen el comienzo del nombre igual, por ejemplo: si tenemos dos directorios tales como "Pepito Perez" y "Pepito Perez Lopez" los listaria de este modo
  • PEPITO~1 (correspondería a "Pepito Perez Lopez" P.Ej)
  • PEPITO~2 (Correspondería a "Pepito Perez" P.Ej)
Pues cuando los edito con mi utilidad, pueden no corresponder, es decir
    • PEPITO~2 (correspondería a "Pepito Perez Lopez" P.Ej)
    • PEPITO~1 (Correspondería a "Pepito Perez" P.Ej)
Pensaba que tendría que ver con el orden de creación, pero he comprobado que ficheros que se crearon con fecha posterior tienen una numeración más baja.

Estoy un poquito, mejor un MUCHITO, liado y no sé como resolverlo.

Pensaba que lo había hecho bien, pero al no coincidirme los ficheros, me he quedado muy desilusionado.

Espero que alguien me eche una mano. No me vale GetShortPathName, pues empecé por ahí y me da problemas cuando hay mas de 4 directorios o ficheros que comienzan con las mismas letras. Hasta el cuarto fichero funciona, pero si le pides el path desde el quinto se descontrola. Curioso, pero verdad.

Si consigo resolverlo lo pondré como truco por si le interesa a alguien.

Perdonad la parrafada, pero quería dejar claro el problema.

Espero vuestra ayuda.

Un saludo.
Responder Con Cita
  #2  
Antiguo 24-03-2008
Avatar de cHackAll
[cHackAll] cHackAll is offline
Baneado?
 
Registrado: oct 2006
Posts: 2.159
Poder: 20
cHackAll Va por buen camino
Justamente te iba a responder que utilices la API GetShortPathName, (que a proposito yo no le encuentro fallas), pero dadas las circunstancias creo que te aconsejaré que utilices la API misma utilizada en FindFirst y FindNext; las APIs son FindFirstFile, FindNextFile, y FindClose; las cuales utilizan la estructura TWIN32FindData que tiene dos cadenas en su definición; la primera es cFileName que utiliza los 260 caracteres de Güindos; y la segunda cAlternateFileName que contiene los nombres de los archivos en formato 8.3

Saludos
Responder Con Cita
  #3  
Antiguo 24-03-2008
jhonalone jhonalone is offline
Miembro
 
Registrado: sep 2007
Ubicación: Madrid
Posts: 547
Poder: 17
jhonalone Va por buen camino
ChakAll, gracias por tu interés, lo primero.
La situación está así con GetShortPathName:
en XP Pro y en Vista64 da error cuando le pides la ruta desde un subdirectorio que hace el número 5 ó más con las mismas 9 ó más letras iniciales iguales.
en ME no da ningún problema, he comprobado hasta con 12 subdirectorios, uno a uno.

Para mi caso particular está resuelto el problema desde el principio, pues en la instalación del programa, no permito cambiar la ruta y no es muy probable que haya 5 subdirectorios parecidos al mío, pero no me deja satisfecho el "gusanillo" ése que nos obliga a ser perfeccionistas...

Aunque pierda un poco de mi tiempo, intentaré con FindFirstFile del API y ya te conteré.

Te pego a continuación la función que utilizo en un proyecto de prueba para que la revises o la pruebes con otro sistema para ver lo de los 5 directorios.

Function Ruta:string;
var
RutaCorta:String;
DirActual:String;
corto:array [0..MAX_PATH] of char;
longitud:Cardinal;
begin
GetDir(0,DirActual);
Longitud:= Sizeof(Corto) -1;
GetShortPathName(PChar(DirActual),@corto,Longitud);
RutaCorta:=String(Pchar(@corto));
if Length(RutaCorta)>3 then Ruta:=RutaCorta+'\'
else Ruta:=RutaCorta; // si es el Dir Raiz C:\ ó A:\ la barra la pone sola
end;


y después la llamo desde un botón y lo escribo en un Edit

procedure TForm1.Button1Click(Sender: TObject);
begin
Edit1.text:=Ruta;
end;
Responder Con Cita
  #4  
Antiguo 25-03-2008
jhonalone jhonalone is offline
Miembro
 
Registrado: sep 2007
Ubicación: Madrid
Posts: 547
Poder: 17
jhonalone Va por buen camino
Lo siento. Me rindo. Creo que Microsoft nos toma el pelo con el API. Son casi las 2 de la mañana y no puedo más. Llevo toda la tarde con esto y estoy bloqueado. Me devuelve vacia la cadena RegFich.cAlternateFilename, y sin embargo me devuelve correcta la de RegFich.cFilename.

Que alquien me lo explique. Yo desisto. A lo mejor tengo un error en el código y no me doy cuenta...

De todas formas creo que el tema no interesa mucho (Solo 27 visitas en dos dias)

function RutaDOS(NomFich:String): String;
label Salir;
var
RegFich: TWin32FindData;
Control: String;
DirActual: String;
RutaLarga: string;
NombreCorto: String;
RutaCorta: String;
xx: integer;
ControlBusqueda:THandle;
AlgoFalla:Boolean;
begin

//////////////////////////////////////////////////////////////////////////////
// Primero Transformamos la ruta de Directorios hasta el Actual a nombres cortos
// 1.- Obtenemos la ruta en que estamos
AlgoFalla:=False; //Control del resultado
GetDir(0,RutaLarga);
RutaLarga:=RutaLarga+'\'+NomFich;
//RutaCorta empieza vacía para ir añadiendo en while Length(Rutalarga) > 3
RutaCorta:='';

while Length(RutaLarga) > 2 // Si no es el directorio Raiz (Unidad:\)
do begin
//Buscamos el directorio que investigaremos actualmente
xx:=Length(RutaLarga);
while RutaLarga[xx]<>'\' do xx:=xx-1;
DirActual:=Copy(RutaLarga,xx+1,Length(RutaLarga)-xx);
Delete(Rutalarga,xx,Length(RutaLarga)-xx+1); // eliminamos el directorio que estamos comprobando
SetCurrentDirectory(PChar(RutaLarga+'\')); //Fijamos el directorio de búsqueda


ControlBusqueda:=FindFirstFile(PChar(RutaLarga+'\'+DirActual), RegFich);
if ControlBusqueda=INVALID_HANDLE_VALUE // Algo Falla
then begin
AlgoFalla:=True;
Goto Salir;
end
else begin // ControlBusqueda<>INVALID_HANDLE_VALUE No hay fallo
if RegFich.cFileName=DirActual
then NombreCorto:=String(RegFich.cAlternateFilename)
else while FindNextFile(ControlBusqueda,RegFich)
do if RegFich.cFileName=DirActual
then NombreCorto:=String(RegFich.cAlternateFilename);
end;// ControlBusqueda<>INVALID_HANDLE_VALUE

RutaCorta:=NombreCorto+'\'+RutaCorta;
end; //while Length(RutaLarga) > 2

RutaCorta:=RutaLarga+'\'+RutaCorta; // en DirActual debe quedar "Unidad\:"
// Aquí termina la ruta de los directorios
//////////////////////////////////////////////////////////////////////////////
Salir:
if AlgoFalla then RutaCorta:='';
RutaDOS:=RutaCorta;

// Terminamos uso de FindFirst/FindNext
Windows.FindClose(ControlBusqueda);
end;
Responder Con Cita
  #5  
Antiguo 25-03-2008
Avatar de cHackAll
[cHackAll] cHackAll is offline
Baneado?
 
Registrado: oct 2006
Posts: 2.159
Poder: 20
cHackAll Va por buen camino
Cita:
Empezado por jhonalone Ver Mensaje
...Me rindo. Creo que Microsoft nos toma el pelo con el API...
No, la razón de la "ineficiencia" de la API no es algo casual;

Cita:
Empezado por GetShortPathName
Remarks

When an application calls this function and specifies a path on a volume that does not support 8.3 aliases, the function fails with ERROR_INVALID_PARAMETER if the path is longer than 67 bytes.

Cita:
Empezado por jhonalone Ver Mensaje
Que alquien me lo explique. Yo desisto. A lo mejor tengo un error en el código y no me doy cuenta...
Es probable, para futuras ocaciones por favor... utiliza las etiquetas para enmarcar tu código. Así como lo dejaste nadie lo analizará.

Cita:
Empezado por jhonalone Ver Mensaje
De todas formas creo que el tema no interesa mucho (Solo 27 visitas en dos dias)
No es un tema que interese o no a los miembros; la poca concurrencia en un hilo puede deberse a la dificultad de la pregunta, a la repetición, a que es un tema demasiado común, a las faltas a la guia de estilos o por cualquier otra causa.

Al grano;

Código Delphi [-]
function GetShortName(FileName: string): string;
var
 Actually: string;
 FindData: TWin32FindData;
 Pos, Count: Integer;
begin
 Count := 3;
 Result := Copy(FileName, 1, 2);
 while Count < Length(FileName) do
  begin
   Inc(Count);
   Pos := System.Pos('\', Copy(FileName, Count, MAX_PATH)) - 1;
   if Pos <> -1 then Inc(Count, Pos) else Count := MAX_PATH;
   Windows.FindClose(FindFirstFile(PChar(Copy(FileName, 1, Count - 1)), FindData));
   Result := Result + '\' + FindData.cAlternateFileName;
  end;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
 ShowMessage(GetShortName('C:\Documents and Settings\Administrator\Start Menu\Internet Explorer.lnk'));
end;

Animos!
Responder Con Cita
  #6  
Antiguo 25-03-2008
jhonalone jhonalone is offline
Miembro
 
Registrado: sep 2007
Ubicación: Madrid
Posts: 547
Poder: 17
jhonalone Va por buen camino
Otra vez Gracias cHakAll.
¡Qué mas quisiera yo que poder poner el código tan bonito como lo tengo en el editor de Delphi, pero no tengo ni idea cómo se hace.
Conste que he buscado en el foro, pero no sé cómo lo hacéis. Comprenderás que no soy muy experto en el foro, llevo sólo 19 ó 20 posts. Pero prometo enterarme para la próxima vez que tenga que poner código.
Bueno al grano, como dices tu.
Siento informarte que el resultado obtenido con la función GetShortName que me has puesto, es exactamente el mismo que el que he obtenido con la RutaDOS, que yo te puse, es decir este es el resultado: "C:\\\\", el número de barrras es el mismo que los subdirectorios que hay hasta llegar al raiz. Mi SO es WXP Professional.
Probado en el de mi hijo, que es Vista64, el resultado es idéntico, en el antiguo ME si funciona GetShortPathName, el RutaDOS y el GetShortName no los he probado.
Vuelvo a darte las gracias y te pido que no pierdas más tiempo con este tema, no lo merece.

Saludos Juan
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Rellenar listbox con nombres de ficheros eduarcol Varios 2 11-08-2007 02:40:03
¿ Cómo obtener los nombres de bases de datos? Javi2 Varios 2 22-11-2006 09:46:21
como obtener los nombres de archivos de un directorio ilichhernandez Varios 3 14-07-2006 17:49:57
Copiar nombres de ficheros a un Combo Tomás Varios 2 12-01-2004 16:28:51
Obtener nombres hgiacobone Varios 1 23-07-2003 18:55:02


La franja horaria es GMT +2. Ahora son las 09:57:55.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi