Ce programme permet de traiter des fichiers créés dans un dossier donné.
Cela marche actuellement pour des copies de fichier, pas pour des fichiers dézippés par exemple, ni avec SuperCopier.
Le traitement du fichier est fait dans un thread séparé.
On peut mettre en pause le traitement pendant que le FileSystemWatcher continue de surveiller le dossier.
Les commentaires sont en anglais.
Attention, pour tester il faut bien copier les fichier, et non les déplacer. Le code ci-dessous supprime le fichier copié.
Source / Exemple :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
namespace FileWatcher
{
public partial class Form1 : Form
{
FileSystemWatcher myWatcher;
string scanFolder = @"c:\"; // Folder to scan
string fileMask = "*.*";
Dictionary<string, int> filesLastWrite;
Queue<string> queue;
static readonly Object objLockQueue = new Object();
System.Threading.Timer timer;
bool cancelPending;
delegate void reportProgressDelegate(int percentProgress, string message);
delegate void stopScanDelegate();
public Form1()
{
InitializeComponent();
Init();
}
private void Init()
{
// Timers
AutoResetEvent autoEvent = new AutoResetEvent(false);
// Integrator
System.Threading.TimerCallback timerDelegate = new System.Threading.TimerCallback(this.timer_Tick);
timer = new System.Threading.Timer(timerDelegate, autoEvent, Timeout.Infinite, Timeout.Infinite);
filesLastWrite = new Dictionary<string, int>();
queue = new Queue<string>();
myWatcher = new FileSystemWatcher(scanFolder, fileMask);
myWatcher.NotifyFilter = NotifyFilters.LastWrite;
myWatcher.Changed += new FileSystemEventHandler(myWatcher_Changed);
myWatcher.SynchronizingObject = this;
// Activer
myWatcher.EnableRaisingEvents = true;
// Integrator
this.btnStart.Enabled = true;
this.btnStop.Enabled = false;
this.lblState.Text = "Stopped";
}
void myWatcher_Changed(object sender, FileSystemEventArgs e)
{
lock (objLockQueue)
{
if (filesLastWrite.ContainsKey(e.FullPath))
{
FileInfo fileInfo = new FileInfo(e.FullPath);
int nbTotalAccess;
int nbWriteAccess = filesLastWrite[e.FullPath] + 1;
// 3x for file copy, 2x if file size = 0
if (fileInfo.Length > 0)
nbTotalAccess = 3;
else
nbTotalAccess = 2;
if (nbWriteAccess < nbTotalAccess)
filesLastWrite[e.FullPath] = nbWriteAccess + 1;
else
{
filesLastWrite[e.FullPath] = 0;
queue.Enqueue(e.FullPath);
}
}
else
filesLastWrite.Add(e.FullPath, 1);
}
}
void timer_Tick(Object stateInfo)
{
if (queue.Count > 0)
{
string fileNameFull;
int nbFichiersTraites = 0;
while (queue.Count > 0)
{
// Cancel ?
if (cancelPending)
{
this.Invoke(new stopScanDelegate(this.StopScan));
return;
}
// Progress
int percentProgress;
nbFichiersTraites++;
lock (objLockQueue)
{
percentProgress = (int)100 * nbFichiersTraites / (queue.Count + nbFichiersTraites - 1);
fileNameFull = queue.Dequeue();
}
string message = percentProgress + "%" + " Processing file " + Path.GetFileName(fileNameFull);
this.Invoke(new reportProgressDelegate(this.reportProgress), new Object[] { percentProgress, message });
// Launch file operation
OperateFile(fileNameFull);
}
}
// cancel ?
if (cancelPending)
{
this.Invoke(new stopScanDelegate(this.StopScan));
// The timer is not reactivated
}
else
{
// Progression
this.Invoke(new reportProgressDelegate(this.reportProgress), new Object[] { 0, "Scanning..." });
// Activate timer (1 time, in 1 second)
timer.Change(1000, Timeout.Infinite);
}
}
private void OperateFile(string fileNameFull)
{
Console.WriteLine("Operating file " + fileNameFull);
// ...
// Work with this file
// ...
File.Delete(fileNameFull); // by example
}
public void reportProgress(int percentProgress, string message)
{
this.progressBar.Value = percentProgress;
this.lblState.Text = message;
}
private void btnStop_Click(object sender, EventArgs e)
{
btnStop.Enabled = false;
// Cancel operation for the next file
cancelPending = true;
}
private void StopScan()
{
// Timer is already off
cancelPending = false;
reportProgress(0, "Stopped.");
this.btnStop.Enabled = false;
this.btnStart.Enabled = true;
this.btnStart.Focus();
}
private void btnStart_Click(object sender, EventArgs e)
{
BeginScan();
}
private void BeginScan()
{
this.btnStop.Enabled = true;
this.btnStop.Focus();
this.btnStart.Enabled = false;
timer.Change(0, Timeout.Infinite); // Activate timer now (1 time)
}
}
}
Conclusion :
Pourquoi ne pas utiliser l'évènement OnCreate ? Parce que pour les gros fichiers, on est confrontée à l'erreur suivante :
Le processus ne peut pas accéder au fichier 'xxx', car il est en cours d'utilisation par un autre processus.
Pourquoi de pas utiliser OnChange + NotifyFilter.LastAccess ?
Parce qu'il loupe parfois des fichiers de petite taille.
J'attends vos commentaires !
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.