Ir al contenido


Foto

Problema bucle Infinito


  • Por favor identifícate para responder
10 respuestas en este tema

#1 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 260 mensajes

Escrito 13 agosto 2012 - 06:49

Buenas con todos, yo aquí después de un tiempito vengo con una pequeña consulta, resulta que últimamente estoy teniendo problema con un bucle, el cual en ciertos momentos funciona bien y en otros no, quizas ya mucho de ustedes habrán visto el código que utilizo, lo postee hace un tiempo cuando tenía otro problema...  lo utilizo para cambiar atributos en forma recursiva o sino para listar archivos y carpetas recursivamente.

el código como muchos sabrán es:



delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2.   procedure ChangeAttributes(const path:String);
  3.   var
  4.     search : TSearchRec;
  5.     nFiles : integer;
  6.     cPath : String;
  7.   begin
  8.     application.ProcessMessages;    // ESTE HACE QUE NO SE CUELGUE EL PROGRAMITA... JEEEEE
  9.     cpath:=path {GetCurrentDir+'\';};
  10.     //cpath:=letra+'\';
  11.  
  12.     nfiles:=findfirst(cpath + '*.*', faanyfile, search);
  13.  
  14.     while nfiles = 0 do
  15.     begin
  16.       if search.Attr = fadirectory then
  17.       begin
  18.         if (search.Name<>'.') and (search.Name<>'..') then
  19.         begin
  20.           setfileattributes(Pchar(cpath+search.Name), FILE_ATTRIBUTE_NORMAL);
  21.           ChangeAttributes(path + search.Name + '\');
  22.           //memo1.Lines.Add(cPath+search.Name);
  23.         end;
  24.       end
  25.       else
  26.       begin
  27.         SetFileAttributes(PChar(cPath + search.Name),FILE_ATTRIBUTE_NORMAL);
  28.         ChangeAttributes(path + search.Name + '\');
  29.         memo1.Lines.Add(cPath+search.Name);
  30.       end;
  31.       nFiles:=FindNext(Search);
  32.     end;
  33.     SysUtils.FindClose(search);
  34.   end;
  35. begin
  36.   ChangeAttributes(GetCurrentDir+'\'); // esta es su llamada
  37. end;



Debo aclarar que el código trabaja bien casi todo el tiempo, pero por momentos como que se vuelve loco y no para de dar vueltas y vueltas de forma infinita....

Ahora para poder ver lo que está procesando he colocado un "tmemo" para poder registrar todo lo que se procesa (archivos y carpetas) y me he dado con la sorpresa que en los momentos que se vuelve loco sale esto en el memo:

Ejemplo:

D:\trabajos\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\


lo cual me deja más intrigado....    :|
He probado varias veces buscando la causa y una pista que pude encontrar es que este problema también ocurre cuando un archivo o carpeta esta "comprimida para ahorrar espacio" el cual es una característica de windows para NTFS...

Agradezco a cualquiera que me de una mano y saber si a alguien más le ha pasado esto, también les adjunto un ejemplo con el error presente.


PD: la carpeta con el error se llama "prueba" y tienen que "comprimirlo para ahorrar espacio" ahí
verán el error.

:)

Archivos adjuntos


  • 0

#2 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 14 agosto 2012 - 01:40

Buenas,

Intenta indentar bien el código, es muy complicado de leer si no lo está
  • 0

#3 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 14 agosto 2012 - 01:45

Buenas,

Una vez indentado, veamos.....

A simple vista (y sin probar el código), a mi me sobraría la línea "ChangeAttributes(path + search.Name + '\');" cuando el fichero NO es un directorio. No tiene sentido hacer esa llamada recursiva (que sí lo tiene en el caso de los directorios).

Nos leemos

  • 0

#4 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 14 agosto 2012 - 02:59

Como te ha indicado cadetill el código está mal diseñado No debe reentrar en el caso de archivos y es por esa razón por la que tienes el problema del "bucle infinito"

Hace tiempo publiqué una función recursiva y de uso general para cambiar atributos, ¿recuerdas?:

Aquí te respondí a esta misma cuestión. ¿Recuerdas?


Te la vuelvo a copiar:


delphi
  1. procedure SetAttribute(Path: String; dwFileAttributes: DWORD; SubDir: boolean = false);
  2. var
  3.   A:  integer;
  4.   sr: TSearchRec ;
  5.   FileName, Dir: String;
  6. begin
  7.   A:= FileSetAttr(PCHAR(Path), dwFileAttributes);
  8.   Dir:= ExtractFileDir(Path) + '\';
  9.   FileName:= ExtractFileName(Path);
  10.   if FileName = '' then FileName:= '*.*';
  11.   if (Dir <> '') and (FindFirst(Dir + FileName, faAnyFile, sr) = 0) then
  12.   repeat
  13.     if (sr.Name <> '.') and (sr.Name <> '..') then
  14.     begin
  15.       A:= FileSetAttr(PCHAR(Dir + sr.Name), dwFileAttributes);
  16.       if (sr.Attr and faDirectory) <> 0  then
  17.         if SubDir then SetAttribute(Dir + sr.Name + '\', dwFileAttributes, true);
  18.     end;
  19.   until (FindNext(sr) <> 0);
  20.   FindClose(sr);
  21. end;



Para tu propósito el uso sería así:


delphi
  1. SetAttribute(GetCurrentDir+'\', FILE_ATTRIBUTE_NORMAL, true);



Como detalle diferencial, la que yo publico usa la función FileSetAttr y la tuya la API de Windows SetFileAttributes. Pues bien, tratándose de Lazarus es mejor no usar la API de Windows y usar FileSetAttr por compatibilidad con otras plataformas.


Saludos.
  • 0

#5 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 260 mensajes

Escrito 14 agosto 2012 - 07:30

Gracias por su pronta ayuda amigos, intentaré lo que me están sugeriendo..... ;)

También quiero preguntarle al amigo Escafranda si utilizo su código para poder cambiar los atributos de todos los archivos y carpetas su llamada estaría bien si lo uso así:



delphi
  1. SetAttribute(GetCurrentDir+'\', FILE_ATTRIBUTE_NORMAL, true);



ó así:



delphi
  1. SetAttribute(GetCurrentDir+'\', faArchive, true);




Saludos... :)

PD: que significa "dwFileAttributes"


  • 0

#6 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 14 agosto 2012 - 07:36

PD: que significa "dwFileAttributes"


No significa nada, es sólo el nombre de una variable ;)

Y a la primera pregunta, la primera opción es la buena

Nos leemos
  • 0

#7 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 260 mensajes

Escrito 14 agosto 2012 - 10:27

Gracias por la aclaración  :)......  les cuento que hice lo que me recomendaron, elimine la parte de:


delphi
  1. ChangeAttributes(path + search.Name + '\');



En donde procesaba archivos ........ y ahora funciona bien, no se traba, pero al momento de cambiar atributos solo lo hace a los archivos de la raiz mas no hay recursión...  :(

Estoy pensando utilizar el código del amigo Escafranda.... seguiré probando y les cuento.  :)


  • 0

#8 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 16 agosto 2012 - 06:31

No debes eliminar todas las líneas, sólo cuando NO es un directorio. En los directorios SI debe haber recursividad.


Saludos.
  • 0

#9 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 260 mensajes

Escrito 16 agosto 2012 - 07:28

Hola amigo escafranda, justo he hecho lo que me han sugerido solo donde se procesa los archivos y sucede lo que les puse arriba, procesa todo pero no recursivamente, les pongo como lo hice:



delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2.   procedure ChangeAttributes(const path:String);
  3.       var
  4.           search : TSearchRec;
  5.           nFiles : integer;
  6.           cPath : String;
  7.       begin
  8.       application.ProcessMessages; 
  9.       cpath:=path;
  10.      
  11.       nfiles:=findfirst(cpath + '*.*', faanyfile, search);
  12.       while nfiles = 0 do
  13.       begin
  14.         if search.Attr = fadirectory then
  15.         begin
  16.         if (search.Name<>'.') and (search.Name<>'..') then
  17.  
  18.         begin
  19.         setfileattributes(Pchar(cpath+search.Name), FILE_ATTRIBUTE_NORMAL);
  20.         ChangeAttributes(path + search.Name + '\');
  21.         end;
  22.         end
  23.         else
  24.         begin
  25.         SetFileAttributes(PChar(cPath + search.Name),FILE_ATTRIBUTE_NORMAL);
  26.         //ChangeAttributes(path + search.Name + '\');  // ACA LO DESHABILITE
  27.         memo1.Lines.Add(cPath+search.Name);
  28.         end;
  29.         nFiles:=FindNext(Search);
  30.         end;
  31.         SysUtils.FindClose(search);
  32.         End;
  33.  
  34. begin
  35.   ChangeAttributes(GetCurrentDir+'\'); // esta es su llamada
  36. end;





Les pido una manito ....  :)
  • 0

#10 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 17 agosto 2012 - 03:41

Dos cosas:

1. Indenta correctamente el código.
2. Estás mirando mal los atributos de Directorio.

Cambia la línea:


delphi
  1. if  search.Attr = fadirectory then


por


delphi
  1. if (search.Attr and fadirectory) <> 0 then



Los atributos son valores de bit "acumulativos"



Saludos.
  • 0

#11 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 260 mensajes

Escrito 17 agosto 2012 - 07:12

Lo acabo de probar y ahora si agarra.... gracias amigo escafranda  :).
 
  • 0




IP.Board spam blocked by CleanTalk.