Put all files from Filesystemwacther to virtual Mode ListView

MiPakTeh 1,476 Reputation points
2021-03-27T05:09:34.08+00:00

Hi All,

What I try to do is;

How to put all files coming using filesystemwacther into Virtual Mode ListView.Yhis code have one Class and
code Form.Somebody can show.

Class;

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Permissions;
using static System.IO.Path;

namespace Learning_13
{
    public class FileOperations : FileSystemWatcher
    {
        /// <summary>
        /// Path to check for new files
        /// </summary>
        public string MonitorPath { get; set; }
        /// <summary>
        /// Path to move file(s) too
        /// </summary>
        public string TargetPath { get; set; }

        public FileOperations(string monitorPath, string targetPath, string extension)
        {
            MonitorPath = monitorPath;
            TargetPath = targetPath;

            Created += OnCreated;
            Error += OnError;

            Path = MonitorPath;
            Filter = extension;

            EnableRaisingEvents = true;

            NotifyFilter = NotifyFilters.Attributes
                           | NotifyFilters.CreationTime
                           | NotifyFilters.DirectoryName
                           | NotifyFilters.FileName
                           | NotifyFilters.LastAccess
                           | NotifyFilters.LastWrite
                           | NotifyFilters.Security
                           | NotifyFilters.Size;
        }

        private void OnCreated(object sender, FileSystemEventArgs e)
        {

            try
            {


                System.IO.StreamWriter fileV = new System.IO.StreamWriter(MonitorPath);
                foreach (var sfile in MonitorPath)
                {
                    fileV.WriteLine(sfile);
                }

                var targetFile = Combine(TargetPath, GetFileName(e.FullPath));
                if (File.Exists(targetFile))
                {
                    File.Delete(targetFile);
                }

                File.Move(e.FullPath, targetFile);
            }
            catch (Exception exception)
            {
                Debug.WriteLine(exception.Message);
            }
        }

        public void Start()
        {
            EnableRaisingEvents = true;
        }

        public void Stop()
        {
            EnableRaisingEvents = false;
        }

        private static void OnError(object sender, ErrorEventArgs e) => DisplayException(e.GetException());
        /// <summary>
        /// For debug purposes
        /// For a production environment write to a log file
        /// </summary>
        /// <param name="ex"></param>
        private static void DisplayException(Exception ex)
        {
            if (ex != null)
            {
                Debug.WriteLine($"Message: {ex.Message}");
                Debug.WriteLine("Stacktrace:");
                Debug.WriteLine(ex.StackTrace);
                Debug.WriteLine("");

                DisplayException(ex.InnerException);
            }
        }
    }
}
  1. Form Code using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Windows.Forms; namespace Learning_13
    {
    public partial class Form1 : Form
    {
        List<string> filesAdded = new List<string>();
    
        private readonly FileOperations _fileOperations =
             new FileOperations(@"C:\", @"D:\Keeper\", "*.txt");
        public Form1()
        {
            InitializeComponent();
            Closing += OnClosing;
        }
    
        private void OnClosing(object sender, CancelEventArgs e)
        {
            _fileOperations.Stop();
        }
    
        void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
        {
            var item = new ListViewItem();
            if (_fileOperations.MonitorPath.Count() > 0)
            {
                item.Text = _fileOperations.MonitorPath[e.ItemIndex].ToString();
            }
            e.Item = item;
    
        }
    
        private void Start_Click(object sender, EventArgs e)
        {
            _fileOperations.Start();
            listView1.VirtualListSize = _fileOperations.MonitorPath.Count();
    
        }
    
        private void Stop_Click(object sender, EventArgs e)
        {
            _fileOperations.Stop();
        }
    
        private void Form1_Load(object sender, EventArgs e)
        {
            System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
            listView1.RetrieveVirtualItem += new RetrieveVirtualItemEventHandler(listView1_RetrieveVirtualItem);
            listView1.VirtualMode = true;
            listView1.View = View.Details;
            listView1.GridLines = true;
            listView1.Columns.Add("Filename", 600);
    
            listView1.RetrieveVirtualItem += new RetrieveVirtualItemEventHandler(listView1_RetrieveVirtualItem);
    
        }
    }
    
    }

...Thank.

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,217 questions
{count} votes

Accepted answer
  1. Timon Yang-MSFT 9,571 Reputation points
    2021-04-06T07:03:06.373+00:00

    I did not completely use your code but re-written a piece of code myself. There are two main differences between this code and your code.

    I didn't customize FileOperations to inherit FileSystemWatcher but directly used FileSystemWatche because I don't really understand the role of some methods in FileOperations.

    When the Created event is used, the file is moved to the target path as soon as it is created, and we have no time to rename it. This causes all files to use the default name, and the code will delete the file with the name already existing, so there will always be only one file with the default name in the target path.

    public partial class Form1 : Form  
    {  
        private string TargetPath = @"d:\test11\";  
        private bool IsNewFile = false;  
        private List<ListViewItem> myCache = new List<ListViewItem>();  
        public Form1()  
        {  
            InitializeComponent();  
        }  
    
        private void Form1_Load(object sender, EventArgs e)  
        {  
            listView1.View = View.Details;  
            listView1.GridLines = true;  
            listView1.VirtualMode = true;  
            listView1.RetrieveVirtualItem += ListView1_RetrieveVirtualItem;  
            listView1.Columns.Add("Filename", 600);  
            var watcher = new FileSystemWatcher(@"d:\test");  
    
            watcher.NotifyFilter = NotifyFilters.Attributes  
                                 | NotifyFilters.CreationTime  
                                 | NotifyFilters.DirectoryName  
                                 | NotifyFilters.FileName  
                                 | NotifyFilters.LastAccess  
                                 | NotifyFilters.LastWrite  
                                 | NotifyFilters.Security  
                                 | NotifyFilters.Size;  
            watcher.Created += OnCreated;  
            watcher.Renamed += OnRenamed;  
            watcher.Filter = "*.txt";  
            watcher.IncludeSubdirectories = true;  
            watcher.EnableRaisingEvents = true;  
        }  
    
        private void ListView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)  
        {  
            if (myCache .Count>0)  
            {  
                e.Item = myCache[e.ItemIndex];  
            }  
        }  
    
        private void OnCreated(object sender, FileSystemEventArgs e)  
        {  
            IsNewFile = true;  
        }  
       private void OnRenamed(object sender, RenamedEventArgs e)  
        {  
            if (IsNewFile)  
            {  
                string TargetFile = Path.Combine(TargetPath, e.Name);  
    
                using (StreamWriter fileV = new System.IO.StreamWriter(e.FullPath))  
                {  
                    foreach (var sfile in e.FullPath)  
                    {  
                        fileV.WriteLine(sfile);  
                    }  
                }  
                if (File.Exists(TargetFile))  
                {  
                    File.Delete(TargetFile);  
                }  
              
                //The File.Delete process may not end in time, causing File.Move to be abnormal, indicating that the file is being used.                   
                Thread.S*leep(100);  
                File.Move(e.FullPath, TargetFile);  
                myCache.Add(new ListViewItem() { Text = TargetFile });  
                this.Invoke((MethodInvoker)delegate ()  
                {  
                    listView1.VirtualListSize = myCache.Count;  
                });  
            }  
        }  
    

    Update:

    I build a new winform application, and then add a listview from the toolbox.

    I made a small modification to the code, because when the monitored folder is the root directory of c, in fact, new files created in its subdirectories will also be monitored.

    The previous code will have an error in handling this situation. I modified it slightly in the OnRenamed handler:

                    FileInfo fileInfo = new FileInfo(e.FullPath);  
                    string TargetFile = Path.Combine(TargetPath, fileInfo.Name);  
    

    The current situation is as follows:

    87294-1.gif

    The file mentioned in the exception message is obviously not the *.txt file that we need to monitor. It is a file of Sql Server and contains transaction logs for Microsoft SQL Server relational database that record all completed and pending transactions since last checkpoint.

    I am not sure why it was detected, but when I re-checked the program, I found a problem that I hadn't noticed before.

    If we create a file but do not rename it, and then rename the previous file, the previous file will be written and moved.

    I added a new field and used it like this:

            private string newFilePath;  
            private void OnCreated(object sender, FileSystemEventArgs e)  
            {  
                newFilePath = e.FullPath;  
                IsNewFile = true;  
            }  
            private void OnRenamed(object sender, RenamedEventArgs e)  
            {  
                if (IsNewFile && e.OldFullPath == newFilePath)  
               // ......  
    

    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


0 additional answers

Sort by: Most helpful