none
Monitoreo de Archivos en varias Carpetas. RRS feed

  • Pregunta

  • Hola Como estan?,

    Estoy queriendo realizar una aplicación que monitoree varias carpetas y que compare la fecha de creación de los archivos con la fecha actual y que al ser mayor de cierto tiempo de una alerta. Pero también quiero que tome las carpetas y los tipos de archivo de un XML(para mayor facilidad de agregar carpetas o de quitarlas).

    Este es mi archivo XML:

    <?xml version="1.0" encoding="utf-8"?><ArrayOfCustomFolderSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">  <CustomFolderSettings FolderID="XMLFiles">    <FolderEnabled>true</FolderEnabled>    <FolderDescription>      Files in format XML corresponding to the example project    </FolderDescription>    <FolderFilter>*.XML</FolderFilter>    <FolderPath>C:\Temp\testXML\</FolderPath>    <FolderIncludeSub>false</FolderIncludeSub>  </CustomFolderSettings></ArrayOfCustomFolderSettings>

    Creo la clase donde tomo los datos:

     
     public class CustomFolder
        {
            /// <summary>Unique identifier of the combination File type/folder.
            /// Arbitrary number (for instance 001, 002, and so on)</summary>
            [XmlAttribute]
            public string FolderID { get; set; }
            /// <summary>If TRUE: the file type and folder will be monitored</summary>
            [XmlElement]
            public bool FolderEnabled { get; set; }
            /// <summary>Description of the type of files and folder location –
            /// Just for documentation purpose</summary>
            [XmlElement]
            public string FolderDescription { get; set; }
            /// <summary>Filter to select the type of files to be monitored.
            /// (Examples: *.shp, *.*, Project00*.zip)</summary>
            [XmlElement]
            public string FolderFilter { get; set; }
            /// <summary>Full path to be monitored
            /// (i.e.: D:\files\projects\shapes\ )</summary>
            [XmlElement]
            public string FolderPath { get; set; }
            /// <summary>If TRUE: the folder and its subfolders will be monitored</summary>
            [XmlElement]
            public bool FolderIncludeSub { get; set; }
    
            public CustomFolder()
            {
            }
        }

                     


    Pero no logro realizar el listado de archivos y la comparacion de la fecha, les copio el codigo para ver si me pueden ayudar o sugerir algo.

                                                                                                
    
    
    class Funcion
        {
           
            public void ListFileSystem()
            {
                var FileNameXML = ConfigurationSettings.AppSettings["XMLSettings"];
                XmlSerializer deserializer =
                new XmlSerializer(typeof(List<CustomFolder>));
                TextReader reader = new StreamReader(FileNameXML);
                object obj = deserializer.Deserialize(reader);
                reader.Close();
                // Obtiene la lista de carpetas
                List<CustomFolder> listFolders = obj as List<CustomFolder>;
            }
    
            public void StartFileWatcher()
            {
                
                List<FileSystemWatcher>  listFileSystemWatcher = new List<FileSystemWatcher>();
                // Crea el Loop
                foreach (CustomFolder customFolder in listFolders)
                {
                    DirectoryInfo dir = new DirectoryInfo(customFolder.FolderPath);
                   
                    if (customFolder.FolderEnabled && dir.Exists)
                    {
                        // Crea una nueva instancia
                        FileSystemWatcher fileSWatch = new FileSystemWatcher();
                        // Coloca el tipo de archivo
                        fileSWatch.Filter = customFolder.FolderFilter;
                        // Coloca la ubicacion de la carpeta
                        fileSWatch.Path = customFolder.FolderPath;
                       if (NotifyFilters.CreationTime > DateTime.Now)
                        {
                            //Muestra el siguiente Mensaje
                        }
                        
                        fileSWatch.EnableRaisingEvents = true;
                      
                        listFileSystemWatcher.Add(fileSWatch);
                        
                        CustomLogEvent(String.Format(
                          "Guarda dato del evento",
                          fileSWatch.Filter, fileSWatch.Path));
                    }
                }
            }
    
        }

    Muchas gracias por la ayuda, Saludos.

    lunes, 13 de noviembre de 2017 16:45

Respuestas

  • Lo que quiero hacer es un servicio de windows que se ejecute cada cierto tiempo y me valide ese solo dato.

    Ah, eso es distinto. Si lo que quieres es ejecutar código cada cierto tiempo, entonces puedes usar un Timer dentro del servicio, y que el evento del Timer use System.IO.Directory para recorrer los directorios y examinar los ficheros.

    El FileSystemWatcher tiene una finalidad distinta. Lo usarías si en lugar de querer ejecutar la operación cada cierto tiempo quisieras que fuese instantánea, es decir, que en el momento en que cambie un fichero se te dispare un evento que puedas interceptar para saber que ese fichero ha cambiado.

    • Marcado como respuesta 20Daniel lunes, 13 de noviembre de 2017 17:50
    lunes, 13 de noviembre de 2017 17:42
    Moderador

Todas las respuestas

  • hola

    lo que noto es que defines la instancia de listFolders de forma local en el metodo ListFileSystem(), deberia ser algo como

    class Funcion
    {
        private List<CustomFolder> listFolders;
       
    	public void ListFileSystem()
    	{
    		//resto codigo
    
    		listFolders = obj as List<CustomFolder>;
    	}
    
    	//resto codigo
    la idea es que definas la variable de forma global en la clase para despues usarla en el otro metodo StartFileWatcher()

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    lunes, 13 de noviembre de 2017 16:59
  • hola

    lo que noto es que defines la instancia de listFolders de forma local en el metodo ListFileSystem(), deberia ser algo como

    class Funcion
    {
        private List<CustomFolder> listFolders;
       
    	public void ListFileSystem()
    	{
    		//resto codigo
    
    		listFolders = obj as List<CustomFolder>;
    	}
    
    	//resto codigo
    la idea es que definas la variable de forma global en la clase para despues usarla en el otro metodo StartFileWatcher()

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    Muchas gracias, se me habia saltado eso...

    Con respecto a la comparacion de archivos con la fecha que seria mejor hacerlo de esta manera

    (Aclaro que puse "Fecha de creacion" porque no se como sacarla de esa manera.

     // Crea una nueva instancia
                        FileSystemWatcher fileSWatch = new FileSystemWatcher();
                        // Coloca el tipo de archivo
                        fileSWatch.Filter = customFolder.FolderFilter;
                        // Coloca la ubicacion de la carpeta
                        fileSWatch.Path = customFolder.FolderPath;
                        foreach (var f in customFolder.FolderPath)
                        { 
                            if (fi."Fecha de creacion" > DateTime.Now)
                            {
                                //Muestra el siguiente Mensaje
                            }
                        }

    O seria mejor que lo haga de esta manera

    foreach (var fi in dir.GetFiles("*.XML"))
                        {
                            if (fi.CreationTime > DateTime.Now)
                            {
                                //Muestra el siguiente Mensaje
                            }
                        }

    Gracias por la ayuda..

    lunes, 13 de noviembre de 2017 17:26
  • Además, otra cosa que observo es que no has conectado ninguno de los eventos de los FileSystemWatcher, con lo que no harán nada cuando cambien los ficheros. Has puesto bien el EnableraisingEvents=true para que los eventos se disparen, pero luego no usas los eventos en ningún sitio ???

    No sé si esperabas que los mensajes te salgan gracias al "if (NotifyFilters.CreationTime > DateTime.Now)...". Esa sentencia se limita a leer una sola vez en el momento de la inicialización el valor que tiene el CreationTime de NotifyFilters. Pero no sirve para nada porque no has inicializado NotifyFilters con ningún valor, y es una propiedad "fija", que no cambia durante el funcionamiento del FileSystemWatcher. Los NotifyFilters solo sirven para restringir cuáles son los ficheros que quieres vigilar, no devuelven ninguna información acerca de los ficheros.

    lunes, 13 de noviembre de 2017 17:29
    Moderador
  • Además, otra cosa que observo es que no has conectado ninguno de los eventos de los FileSystemWatcher, con lo que no harán nada cuando cambien los ficheros. Has puesto bien el EnableraisingEvents=true para que los eventos se disparen, pero luego no usas los eventos en ningún sitio ???

    No sé si esperabas que los mensajes te salgan gracias al "if (NotifyFilters.CreationTime > DateTime.Now)...". Esa sentencia se limita a leer una sola vez en el momento de la inicialización el valor que tiene el CreationTime de NotifyFilters. Pero no sirve para nada porque no has inicializado NotifyFilters con ningún valor, y es una propiedad "fija", que no cambia durante el funcionamiento del FileSystemWatcher. Los NotifyFilters solo sirven para restringir cuáles son los ficheros que quieres vigilar, no devuelven ninguna información acerca de los ficheros.

    Hola, es que en realidad nunca use el NotifyFilters, estuve investigando un poco de como funciona pero estoy un poco mareado desde hace tanto que no programo que se me esta complicando por eso estaba pensando en usar mejor

    foreach (var fi in dir.GetFiles("*.XML"))
                        {
                            if (fi.CreationTime > DateTime.Now)
                            {
                                //Muestra el siguiente Mensaje
                            }
                        }
    Lo que quiero hacer es un servicio de windows que se ejecute cada cierto tiempo y me valide ese solo dato.

    lunes, 13 de noviembre de 2017 17:36
  • Lo que quiero hacer es un servicio de windows que se ejecute cada cierto tiempo y me valide ese solo dato.

    Ah, eso es distinto. Si lo que quieres es ejecutar código cada cierto tiempo, entonces puedes usar un Timer dentro del servicio, y que el evento del Timer use System.IO.Directory para recorrer los directorios y examinar los ficheros.

    El FileSystemWatcher tiene una finalidad distinta. Lo usarías si en lugar de querer ejecutar la operación cada cierto tiempo quisieras que fuese instantánea, es decir, que en el momento en que cambie un fichero se te dispare un evento que puedas interceptar para saber que ese fichero ha cambiado.

    • Marcado como respuesta 20Daniel lunes, 13 de noviembre de 2017 17:50
    lunes, 13 de noviembre de 2017 17:42
    Moderador
  • Excelente!!! esa era mi duda... Muchas gracias!!!!
    lunes, 13 de noviembre de 2017 17:50
  • hola

    Esta comparacion

    if (fi.CreationTime > DateTime.Now)

    NUNCA sera verdadera, no puede existir un archivo donde la creacion sea mayor a la fecha y hora del momento

    podrias validar si el archivo se creo en un rango, digamos de la fecha actual 2 horas antes, para eso usarias

    DateTime fechaComparacion = DateTime.Now.AddHours(-2);
    
    if (fi.CreationTime > fechaComparacion){ ...

    por supuesto puedes cambiar el rango, quizas quieras validar las que se crearon mas horas atras

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    lunes, 13 de noviembre de 2017 18:18