Here is my final code for the FileSystemWatcher class. I added two things. One, I noted in my last post. I also updated the code to make a change to the properties of the file I am overwriting on the target servers. I found that if the file was read-only on the target server, it raised an error and did not overwrite the file.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.IO;
using System.Xml;
namespace Replicator
{
public class FileReplicator : System.ServiceProcess.ServiceBase
{
private FileSystemWatcher FileWatcher;
private XmlDocument Config;
private System.Collections.Hashtable TargetServers;
///
/// Required designer variable.
///
private System.ComponentModel.Container components = null;
public FileReplicator()
{
// This call is required by the Windows.Forms Component Designer.
InitializeComponent();
}
// The main entry point for the process
static void Main()
{
System.ServiceProcess.ServiceBase[] ServicesToRun;
// More than one user Service may run within the same process. To add
// another service to this process, change the following line to
// create a second service object. For example,
//
// ServicesToRun = New System.ServiceProcess.ServiceBase[] {new Service1(), new MySecondUserService()};
//
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new FileReplicator() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
this.FileWatcher = new System.IO.FileSystemWatcher();
((System.ComponentModel.ISupportInitialize)(this.FileWatcher)).BeginInit();
//
// FileWatcher
//
this.FileWatcher.EnableRaisingEvents = true;
this.FileWatcher.Changed += new System.IO.FileSystemEventHandler(this.FileWatcher_Changed);
this.FileWatcher.Created += new System.IO.FileSystemEventHandler(this.FileWatcher_Changed);
//Allow Pause and Continue actions on the service
this.CanPauseAndContinue = true;
//Allow people to shutdown the service
this.CanShutdown = true;
//The name that will show in the services control panel
this.ServiceName = "Production Image Replicator";
((System.ComponentModel.ISupportInitialize)(this.FileWatcher)).EndInit();
this.EventLog.WriteEntry("Production Image Replicator Service Initializing.",System.Diagnostics.EventLogEntryType.Information,1,1);
}
///
/// Clean up any resources being used.
///
protected override void Dispose( bool disposing )
{
this.EventLog.WriteEntry("Production Image Replicator Service Dispose.",System.Diagnostics.EventLogEntryType.Information,1,1);
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
///
/// Set things in motion so your service can do its work.
///
protected override void OnStart(string[] args)
{
this.EventLog.WriteEntry("Starting Production Image Replicator Service.",System.Diagnostics.EventLogEntryType.Information,1,1);
this.FileWatcher.EnableRaisingEvents = true;
Config = new XmlDocument();
TargetServers = new Hashtable();
string localpath = System.IO.Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase );
try
{
Config.Load(localpath+"\\config.xml");
this.EventLog.WriteEntry("Loaded Config File at "+localpath+"\\config.xml",System.Diagnostics.EventLogEntryType.Information,1,1);
}
catch (System.Xml.XmlException xex)
{
this.EventLog.WriteEntry("Could not open config file. Error was:\n"+xex.Message,System.Diagnostics.EventLogEntryType.Error,1,1);
}
FileWatcher.Path = Config.SelectSingleNode("configuration/sourceserver/@path").Value;
foreach (XmlNode node in Config.SelectNodes("configuration/targetserver"))
{
TargetServers.Add(node.SelectSingleNode("@name").Value,node.SelectSingleNode("@path").Value);
}
FileWatcher.Filter = "*.gif";
FileWatcher.NotifyFilter=NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.Size;
FileWatcher.IncludeSubdirectories=false;
FileWatcher.InternalBufferSize=40960;
this.EventLog.WriteEntry("Production Image Replicator Service Started.",System.Diagnostics.EventLogEntryType.Information,1,1);
}
///
/// Pause this service.
///
protected override void OnPause()
{
this.FileWatcher.EnableRaisingEvents = false;
this.EventLog.WriteEntry("Production Image Replicator Service Paused.",System.Diagnostics.EventLogEntryType.Information,1,1);
}
///
/// Stop this service.
///
protected override void OnStop()
{
this.FileWatcher.EnableRaisingEvents = false;
this.EventLog.WriteEntry("Production Image Replicator Service Stopped.",System.Diagnostics.EventLogEntryType.Information,1,1);
}
private void FileWatcher_Changed(object sender, System.IO.FileSystemEventArgs e)
{
this.EventLog.WriteEntry("In FileWatcher_Changed.",System.Diagnostics.EventLogEntryType.Information,1,1);
IDictionaryEnumerator ListEnumerator = TargetServers.GetEnumerator();
string strCopyToPath = "";
try
{
if (e.ChangeType==WatcherChangeTypes.Created || e.ChangeType==WatcherChangeTypes.Changed)
{
while (true)
{
//don't do anything till the file has finished copying to the source server
try
{
if (File.Exists(e.FullPath))
break;
}
catch(IOException ix)
{
//ignore the exception, continue trying to open file
}
}
this.EventLog.WriteEntry("Create Event Triggered: "+e.FullPath,System.Diagnostics.EventLogEntryType.Information,1,1);
while (ListEnumerator.MoveNext())
{
strCopyToPath = ListEnumerator.Value.ToString()+"\\"+e.Name;
try
{
if (File.Exists(strCopyToPath))
{
File.SetAttributes(strCopyToPath,FileAttributes.Normal);
}
File.Copy(e.FullPath, strCopyToPath, true);
this.EventLog.WriteEntry("Copied File to "+strCopyToPath,System.Diagnostics.EventLogEntryType.Information,1,1);
}
catch(IOException ix)
{
this.EventLog.WriteEntry("IOException while copying to " + strCopyToPath + ". Error was:\n"+ix.Message,System.Diagnostics.EventLogEntryType.Error,1,1);
}
}
}
}
catch (IOException ix)
{
this.EventLog.WriteEntry("IOException while copying files. Error was:\n"+ix.Message,System.Diagnostics.EventLogEntryType.Error,1,1);
}
catch (Exception x)
{
this.EventLog.WriteEntry("Unknown Exception while copying files. Error was:\n"+x.Message,System.Diagnostics.EventLogEntryType.Error,1,1);
}
}
}
}
When a file is uploaded to an FTP server directory that is being monitored the code portion below is ignored. the event fires as soon as the file is placed in the ftp window. I need to wait for the file to finsh uploading before i perform any action on it.
Thanks
Toby.
{
//don't do anything till the file has finished copying to the source server
try
{
if (File.Exists(e.FullPath))
break;
}
catch(IOException ix)
{
//ignore the exception, continue trying to open file
}
}
Posted by: Toby | Wednesday, December 22, 2004 at 11:58 AM
Hi,
can you post or send me an example config.xml file. i do not understand the logic and i didn´t get the programm running :). i have made some tests with c# 2005 Beta
Posted by: Jens Lewald | Saturday, May 14, 2005 at 02:28 PM
Hi,
can you post or send me an example config.xml file. i do not understand the logic and i didn´t get the programm running :)
Thank you very much
Posted by: kamikaze | Wednesday, January 02, 2008 at 03:41 PM
I have just finished the article.It is the first time for me to read the whole post carefully,I always just look through the article,and forget quickly.But I had save your articl,it is more than useful to me.
Posted by: christian louboutin | Tuesday, November 02, 2010 at 03:24 AM
Writing an exact man,i admire you.
Posted by: air jordans | Thursday, November 11, 2010 at 02:07 AM
Maybe you are right, but I am wondering about it.
Posted by: Chanel Mens Watches | Thursday, March 31, 2011 at 04:43 AM
Looks good just a couple of cmtoenms:* You might want to use an enum for your levels.* Is there a reason you're loading the log level from the config file every time append is called? Seems like this could get expensive if there are tons of logging calls. Same with opening/closing the StreamWriter; why not keep it around?* If you do decide to keep the StreamWriter around, you probably need to put a lock{} around the calls to it it's not guaranteed to be threadsafe.* Instead of dt.ToString( yyyy ) + dt.ToString( MM ) + dt.ToString( dd ), how about dt.ToString( yyyyMMdd )?* It might be cool to be able to add your own log listeners (like log4j's appenders). That way you could log to multiple sinks at once (database, event log, etc.). I've previously tackled this with .NET events; I declare a static event whose EventArgs include the message's priority/level, text, and date/time, and anyone who cares can just register for that event.* I sympathize with you but I think most C# developers would appreciate it if your append method began with a capital A * What's Ignition Labs? -joe
Posted by: Kazuki | Saturday, April 28, 2012 at 10:37 PM
Hi,I have a custom made decvie which has ARM Linux on it, the decvie also has a usb host controller onit, so decvie can act as host, from this decvie i want to talk to a application running on a blackberry through USB port, since RIM doesn't provide drivers for Linux, i though of using Barry, but i am confused on how to use barry libraries on ARM linux.It will be great help if you can guide me on where to start and how to use the barry to interact with blackberry.
Posted by: Alesinloye | Sunday, April 29, 2012 at 01:53 AM
wir sind ihr partner in sehacn computer und internet. wir entwickeln fe3bcr sie individuelle software nur auf sie zugeschnitten. wir machen ihr webdesign und optimieren ihre webseite, damit sie eine gute positionierung bei suchmaschinen bekommen.
Posted by: Yanal | Tuesday, May 01, 2012 at 03:46 AM
Writing an exact man,i admire you.
+1
Posted by: flash game sites | Tuesday, July 10, 2012 at 08:05 PM
Hi, David The filter tab is aillvabae for our Pro, Enterprise and Dedicated customers. To get to it, head to Reports. Create whatever form of report you choose (a Summary Report, for example), then click on the report name from the list of reports. The Filter tab should appear on the left of the report content.Thanks! on Wed, Jul 20 11 at 10:23 am
Posted by: Inding | Sunday, July 15, 2012 at 01:59 AM
Hi Kent,Thanks for replying. I will not be able to add meyslf to that group. However, I asked the BizTalk Admin to run the same code from his desktop. It failed with the same error :Exception Details: System.Runtime.InteropServices.COMException (0xC0C025CA): Instance of the WMI class is not found.BizTalk Server cannot access SQL server. This could be due to one of the following reasons:1. Access permissions have been denied to the current user. Either log on as a user that has been granted permissions to SQL and try again, or grant the current user permission to access SQL Server.2. The SQL Server does not exist or an invalid database name has been specified. Check the name entered for the SQL Server and database to make sure they are correct as provided during SQL Server installation.3. The SQL Server exists, but is not currently running. Use the Windows Service Control Manager or SQL Enterprise Manager to start SQL Server, and try again.4. A SQL database file with the same name as the specified database already exists in the Microsoft SQL Server data folder.Internal error from OLEDB provider: "Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'." at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo) at System.Management.ManagementObject.Initialize(Boolean getObject) at System.Management.ManagementObject.get_ClassPath() at System.Management.ManagementObject.GetMethodParameters(String methodName, ManagementBaseObject& inParameters, IWbemClassObjectFreeThreaded& inParametersClass, IWbemClassObjectFreeThreaded& outParametersClass) at System.Management.ManagementObject.InvokeMethod(String methodName, Object[] args)So, the issue maybe somewhere else. Any other ideas?Thanks.
Posted by: Julie | Friday, December 28, 2012 at 06:47 PM