Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Calling code in another class 1

Status
Not open for further replies.

theniteowl

Programmer
May 24, 2005
1,975
US
I have a windows forms application and am trying to add a FileSystemWatcher routine into it so that it will update a list of files in a ListView box.
I have the watcher working in the application but now when an event is triggered by a change in the folder I want to call the fillListView routine in my form application code but do not know how to make the call to another class.

I am just learning C# and am probably missing some fundamentals so please bear with me.

From OnChanged in Program.cs I am trying to execute fillListView in AnnuityQtrStmtFTP.cs

The following code is under Program.cs
Code:
using System;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Threading;

public class FileInputMonitor
{
    private FileSystemWatcher fileSystemWatcher;
    string folderToWatchFor = WindowsFormsApplication2.frmVendorFileHandling.FTPPath;

    public FileInputMonitor()
    {
        fileSystemWatcher = new FileSystemWatcher(folderToWatchFor);
        fileSystemWatcher.EnableRaisingEvents = true;

        // Instruct the file system watcher to call the FileCreated method
        // when there are files created at the folder.
        fileSystemWatcher.Created += new FileSystemEventHandler(OnChanged);
        fileSystemWatcher.Deleted += new FileSystemEventHandler(OnChanged);
    }

    private void OnChanged(Object sender, FileSystemEventArgs e)
    {    
        MessageBox.Show("File: " + e.FullPath + " " + e.ChangeType);
//        fillListView(lvFTPFolder, FTPPath);
    }
}

namespace WindowsFormsApplication2
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            FileInputMonitor fileInputMonitor = new FileInputMonitor();
            //Console.Read();
            Application.Run(new frmVendorFileHandling());
        }
    }

}

This code is under AnnuityQtrStmtFTP.cs
Code:
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Windows.Forms;


namespace WindowsFormsApplication2
{
    public partial class frmVendorFileHandling : Form
    {
        public static string StagingPath = ConfigurationManager.AppSettings.Get("StagingPath");
        public static string FTPPath = ConfigurationManager.AppSettings.Get("FTPPath");
        string ZipBackupPath = ConfigurationManager.AppSettings.Get("ZipBackupPath");
        string INIPath = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "filepaths.ini");
        public frmVendorFileHandling()
        {
            InitializeComponent();
            fillListView(lvStagingFolder, StagingPath);
            fillListView(lvFTPFolder, FTPPath);
            fillListView(lvZIPBackupFolder, ZipBackupPath);
        }

        public void fillListView(ListView listview, string p)
        {
            string Msg = "";
            DirectoryInfo sourceInfo = new DirectoryInfo(p);
            FileInfo[] sFiles = sourceInfo.GetFiles("*.*");
            try
            {
                foreach (FileInfo file in sFiles)
                {
                    try
                    {
                        if (file.Name != "")
                        {
                            ListViewItem item = new ListViewItem(file.Name);                               // Create the item variable and assign the file name as the primary value
                            item.SubItems.Add(file.LastWriteTime.ToString("MM/dd/yyyy H:mm:ss"));          // Add the last write time to the item as a subitem value
                            item.SubItems.Add(file.Length.ToString());                                     // Repeat as needed for each subitem - could even build an inner loop if needed
                            listview.Items.Add(item);                                                      // Add the item variable to the ListView
                        }
                    }
                    catch (UnauthorizedAccessException UnAuthTop)
                    {
                        Msg = Msg + UnAuthTop.Message;
                    }
                }
            }
            catch (DirectoryNotFoundException)
            {
                Msg = Msg + "Error: Could not find Staging folder - " + StagingPath + Environment.NewLine;
            }
            catch (UnauthorizedAccessException)
            {
                Msg = Msg + "Error: Access not allowed at - " + StagingPath + Environment.NewLine;
            }
            catch (PathTooLongException)
            {
                Msg = Msg + "Error: Directory path is too long." + Environment.NewLine;
            }
            if (string.IsNullOrEmpty(Msg) == false)
            {
                MessageBox.Show(Msg);
            }
        }

        private void btnMoveStagingtoFTP_Click(object sender, EventArgs e)
        {
            string Msg = "";
            if (lvStagingFolder.CheckedIndices.Count > 0)
            {
                foreach (ListViewItem item in lvStagingFolder.Items)
                {
                    if (item.Checked)
                    {
                        string sourceFile = Path.Combine(StagingPath, System.IO.Path.GetFileName(item.Text));
                        string destinationFile = Path.Combine(FTPPath, item.Text);
                        if (System.IO.File.Exists(sourceFile))
                        {
                            if (System.IO.File.Exists(destinationFile))
                            {
                                Msg = Msg + "File " + item.Text + " already exists in destination folder." + Environment.NewLine;
                            }
                            else
                            {
                                System.IO.File.Move(sourceFile, destinationFile);
                                Msg = Msg + item.Text + " has been moved to FTP folder." + Environment.NewLine;
                            }
                        }
                        else
                        {
                            Msg = Msg + "File " + sourceFile + " no longer exists in the STAGING folder, it may have been manually deleted." + Environment.NewLine;

                        }
                        lvStagingFolder.Items.Remove(item);
                    }
                }
                if (string.IsNullOrEmpty(Msg) == false)
                {
                    MessageBox.Show(Msg);
                    lvFTPFolder.Items.Clear();
                    fillListView(lvFTPFolder, FTPPath);
                }
            }
        }

        private void btnDeleteSelected_Click(object sender, EventArgs e)
        {
            string Msg = "";
            if (lvStagingFolder.CheckedIndices.Count > 0)
            {
                foreach (ListViewItem item in lvStagingFolder.Items)
                {
                    if (item.Checked)
                    {
                        string sourceFile = Path.Combine(StagingPath, System.IO.Path.GetFileName(item.Text));
                        if (System.IO.File.Exists(sourceFile))
                        {
                            System.IO.File.Delete(sourceFile);
                            Msg = Msg + item.Text + " has been deleted from the Staging folder." + Environment.NewLine;
                        }
                        lvStagingFolder.Items.Remove(item);
                    }
                }
                if (string.IsNullOrEmpty(Msg) == false)
                {
                    MessageBox.Show(Msg);
                }
            }
        }


        private void btnFTPtoStaging_Click(object sender, EventArgs e)
        {
            string Msg = "";
            if (lvFTPFolder.CheckedIndices.Count > 0)
            {
                foreach (ListViewItem item in lvFTPFolder.Items)
                {
                    if (item.Checked)
                    {
                        string sourceFile = Path.Combine(FTPPath, System.IO.Path.GetFileName(item.Text));
                        string destinationFile = Path.Combine(StagingPath, item.Text);
                        if (System.IO.File.Exists(sourceFile))
                        {
                            if (System.IO.File.Exists(destinationFile))
                            {
                                Msg = Msg + "File " + item.Text + " already exists in destination folder." + Environment.NewLine;
                            }
                            else
                            {
                                System.IO.File.Move(sourceFile, destinationFile);
                                lvFTPFolder.Items.Remove(item);
                                Msg = Msg + item.Text + " has been moved to the STAGING folder." + Environment.NewLine;
                            }
                        }
                        else
                        {
                            Msg = Msg + sourceFile + " has already been sent to the vendor or was manually deleted from the folder." + Environment.NewLine;
                            lvFTPFolder.Items.Remove(item);
                        }
                        item.Checked = false;
                    }
                }
                if (string.IsNullOrEmpty(Msg) == false)
                {
                    MessageBox.Show(Msg);
                    lvStagingFolder.Items.Clear();
                    fillListView(lvStagingFolder, StagingPath);
                }
            }
        }

        private void btnReSendtoVendor_Click(object sender, EventArgs e)
        {
            string Msg = "";
            if (lvZIPBackupFolder.CheckedIndices.Count > 0)
            {
                foreach (ListViewItem item in lvZIPBackupFolder.Items)
                {
                    if (item.Checked)
                    {
                        string sourceFile = Path.Combine(ZipBackupPath, System.IO.Path.GetFileName(item.Text));
                        string destinationFile = Path.Combine(FTPPath, item.Text);
                        if (System.IO.File.Exists(sourceFile))
                        {
                            if (System.IO.File.Exists(destinationFile))
                            {
                                Msg = Msg + "File " + item.Text + " already exists in destination folder." + Environment.NewLine;
                            }
                            else
                            {
                                System.IO.File.Copy(sourceFile, destinationFile);
                                Msg = Msg + item.Text + " has been copied to FTP folder." + Environment.NewLine;
                            }
                        }
                        else
                        {
                            Msg = Msg + "File " + sourceFile + " no longer exists in the ZIP_BACKUP folder and may have been manually deleted." + Environment.NewLine;
                            lvZIPBackupFolder.Items.Remove(item);
                        }
                        item.Checked = false;
                    }
                }
                if (string.IsNullOrEmpty(Msg) == false)
                {
                    MessageBox.Show(Msg);
                    lvFTPFolder.Items.Clear();
                    fillListView(lvFTPFolder, FTPPath);
                }
            }
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            lvStagingFolder.Items.Clear();
            fillListView(lvStagingFolder, StagingPath);
            lvFTPFolder.Items.Clear(); 
            fillListView(lvFTPFolder, FTPPath);
            lvZIPBackupFolder.Items.Clear(); 
            fillListView(lvZIPBackupFolder, ZipBackupPath);
        }
    }
}

At my age I still learn something new every day, but I forget two others.
 
You cannot easily do this because your file system watcher is in its own class.

Instead put the FileInputMonitor class inside your Form class. Expose the FileSystemWatcher as public as subscribe its events in the Form class. Example shown below. However from your code i dont see any real need to have FileInputMonitor in its own class. Just put the FileSystemWatcher directly into the Form class.

Also because the events are triggered in a different thread you cannot update the form directly as they can only be updated in the UI thread. See the line this.Invoke(new Action<ListView, string>(fillListView), lvFTPFolder, FTPPath);


Code:
    public partial class frmVendorFileHandling : Form
    {
        public frmVendorFileHandling()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            FileInputMonitor fileInputMonitor = new FileInputMonitor();
            fileInputMonitor.fileSystemWatcher.Changed += new FileSystemEventHandler(fileSystemWatcher_Changed);
            fileInputMonitor.fileSystemWatcher.Deleted += new FileSystemEventHandler(fileSystemWatcher_Changed);
            fileInputMonitor.fileSystemWatcher.EnableRaisingEvents = true;
        }

        void fileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
        {
            ListView lvFTPFolder = new ListView();
            string FTPPath = "c:\\";

            MessageBox.Show("File: " + e.FullPath + " " + e.ChangeType);

            this.Invoke(new Action<ListView, string>(fillListView), lvFTPFolder, FTPPath);
        }

        public void fillListView(ListView listview, string p)
        {
            // Change list view here
        }

        public class FileInputMonitor
        {
            public FileSystemWatcher fileSystemWatcher;
            string folderToWatchFor = "c:\\Pathhere\\";

            public FileInputMonitor()
            {
                fileSystemWatcher = new FileSystemWatcher(folderToWatchFor);
            }
        }
    }

Do you want some custom SIM scripts developed. Contact me via my website
 
CathalMF, thank you for the help.
Using your example I have gotten the watcher to work and although the fillListView function is called, it does not make any change to the existing view on the form. I have tried variations on the Invoke command but it still does not update the listview and the Changed event fires three times instead of once.

Any thoughts on why it will not update the screen? I have verified that it does indeed call fillListView passing the parameters by executing a MessageBox within the function.


At my age I still learn something new every day, but I forget two others.
 
By commenting out the following lines I was able to get it updating the existing ListView box.
Code:
        void fileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
        {
//            ListView lvFTPFolder = new ListView();
//            string FTPPath = "c:\\";

            MessageBox.Show("File: " + e.FullPath + " " + e.ChangeType);

            this.Invoke(new Action<ListView, string>(fillListView), lvFTPFolder, FTPPath);

The change event seems to fire three times though and I am not sure why.
Oddly also, when I drop a new file into the folder the message that shows is that the file was changed rather than that the file was created which I am pretty sure it said previously. Files deleted are reported as deleted. When I create a file directly in the folder rather than copying it to the folder there is no firing of onchange.

Getting closer anyway. I suspect there is another event type I should be looking for to recognize files created in the folder.

Thanks.

At my age I still learn something new every day, but I forget two others.
 
I managed to get it working.
However I send or create files in the watched folder can result in more than one event.
Different apps handle file creation in different ways and each time they touch the file it triggers an event.
Copying a file into the folder triggers a create event and then two modified events. I understand the create event and possibly a modified event when the file is released by the system and the last modified property is updated but am not certain what the one in between is. Perhaps the system puts a lock on the file while writing it out then releases the lock which triggers an event, then updates last modified when closing out the file. In any event, when the system or an app accesses a file it may perform several tasks that each trigger their own individual event.

With this in mind I made a simple change to my code to test if the filename of the file involved in the current event was also involved in the last event and suppress the execution of the handling code if it is for the same file.

Code:
        void fileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
        {
            if (lastfile != e.FullPath)
            {
                MessageBox.Show("File: " + lastfile + " != " + e.FullPath + "  " + e.ChangeType);
                this.Invoke(new Action(() => lvFTPFolder.Items.Clear()));
                this.Invoke(new Action<ListView, string>(fillListView), lvFTPFolder, FTPPath);
                lastfile = e.FullPath;
            }
        }

Apparently this is a very common issue with FileSystemWatcher and there are a lot of ways to work around it depending on your applications needs.
I could have setup a dictionary to track the names of the files being modified or a timer in which duplicate events could be suppressed but this seemed the easiest. My goal is only to update the display of file names in the ListView so this seems to be adequate. The one thing I am uncertain of is if multiple files are dropped into the folder will the events for them be mixed rather than all events for a single file coming through sequentially. I can do some testing for this but for my app it is not critical.

I had to add the command for lvFTPFolder.Items.Clear as well to prevent getting duplicate file names in the ListView but now everything seems to be working well.

Thanks again CathalMF for your assistance.


At my age I still learn something new every day, but I forget two others.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top