Windows Service w/ FileSystemWatcher in C# - c#

I have to create a program that monitors changes in file size. I already made a simple windows service and filesystemwatcher so I am now familiar w/ the concept. I also made a code that checks for the filesize (made it in a form button)but haven't yet implemented in my filesystemwatcher. How do I create a windows service that has a filewatcher that monitors the file size? Do I have to put a filesystemwatcher inside the windows service and call the watcher via the OnStart method?

If you're making a Window's service, then you'll want to do it programmatically. I usually keep forms out of my services and make a separate interface for them to communicate. Now the FileSystemWatcher doesn't have an event to watch solely for size, so you'll want to make a method that ties to FileSystemWatcher.Changed to check for modifications to existing files. Declare and initialize the control in your OnStart method and tie together the events as well. Do any cleanup code in your OnStop method. It should look something like this:
protected override void OnStart(string[] args)
{
FileSystemWatcher Watcher = new FileSystemWatcher("PATH HERE");
Watcher.EnableRaisingEvents = true;
Watcher.Changed += new FileSystemEventHandler(Watcher_Changed);
}
// This event is raised when a file is changed
private void Watcher_Changed(object sender, FileSystemEventArgs e)
{
// your code here
}
Also note, the FileSystemWatcher will fire off multiple events for a single file, so when you're debugging watch for patterns to work around it.

You can simply enable your filesystemwatcher object in the OnStart method by setting
EnableRaisingEvents = true;
Then handle the event. That should do it.

you can create a delegate to handle what has changed like
myWatcher.Changed += new FileSystemHandler(FSWatcherTest_Changed);
private void FSWatcherTest_Changed(object sender,
System.IO.FileSystemEventArgs e)
{
//code here for newly changed file or directory
}
And so on
I would recommend you to read this article http://www.codeproject.com/Articles/18521/How-to-implement-a-simple-filewatcher-Windows-serv
Also have this delegate on_start in windows service

Related

Windows service timer issue

I have developed windows application which will watch source folder if it finds any folders under source it will move that folder to process folder after performing some operation in process folder it will move those folders destnation folder or Error folder.
This Windows application i converted to windows service and i make this service will call every 30 seconds but now i am not getting how to check before calling service next time previous process completed or not if it not complete how to avoid calling service again.
I added timer interval for 30 sec but process may take more than 30 sec(unpredictable).
protected override void OnStart(string[] args)
{
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 30000; //5000number in milisecinds
timer.Enabled = true;
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
foldermovinglogic();
}
You are overcomplicating things, .Net has a built in FileSystemWatcher which will drop a event when something in the directory was changed, from there on you can filter by created folders, and compare the subfolders now against the subfolders on the last change and do what you intend to do with the newly created folders.
An example for you:
using System.IO;
Declare the FileSystemWatcher
private static FileWatcher yourFileWatcher;
Initialize the FileSystemWatcher
yourFileWatcher = new FileSystemWatcher(directory);
yourFileWatcher.Created += new FileSystemEventHandler(OnCreated);
OnCreated is where you compare the now structure to the past structure it hasto have the following Format:
private void FSW_Created(object sender, FileSystemEventArgs e)
See this tutorial

Preventing FileSystemWatcher throwing TaskCanceledException when calling Shutdown()

I am building a WPF application that checks whether a file has been modified within a certain period of time and if so, the application exits.
I am having an issue that the method that ultimately triggers the call of App.Current.Shutdown() is an event handler attached to a FileSystemWatcher event and causes a TaskCanceledException to be thrown.
A minimal working example is as follows:
Create a new WPF application. In App.xaml.cs
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
FileSystemWatcher w = new FileSystemWatcher();
w.Path = /*path to suitable test folder*/
w.Filter = "Test.txt";
w.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite;
w.Changed += (s, a) =>
{
//Shutdown(); --Throws InvalidOperationException (Calling thread cannot access this object)
Application.Current.Dispatcher.Invoke(() => Shutdown());
};
w.EnableRaisingEvents = true;
}
}
Edit the file Test.txt and the application should close.
In order to prevent the exception showing, I can surround the shutdown call with a empty try-catch block
try
{
Application.Current.Dispatcher.Invoke(() => Shutdown())
}
catch(TaskCanceledException)
{
}
but this seems to be a hack and doesn't solve the underlying issue.
It seems to me that C# is trying to tell me I am going about this the wrong way. Is there a better way?
There is a special method in the dispatcher to invoke a shutdown: InvokeShutdown
Calling Application.Current.Dispatcher.InvokeShutdown(); from the Changed event handler avoids the exception.
This shuts down the dispatcher, which in turn leads to the shutdown of the application. There's some discussion on the difference between this and Application.Shutdown here.

how to wait for filesystemwatcher event to finish

Please excuse me if this is redundant, however all the questions related to this seem to point in different directions, also I am new to multithreaded programming.
I have a FileSystemWatcher class in my code, which watches the created event. It looks like a created event of file system watcher starts it's own thread. So sometimes the calling thread continues it's work before the work initiated in called thread of FileSystemWatcher created event finishes. I don't want this. My workflow needs to be single-threaded, so what I want to achieve is wait for for created event to finish it's work before the calling thread gets an opportunity to resume.
pesudo code:
main() {
FileSystemWatcher fsw = new FileSystemWatcher()
fsw.Path = ini.location;
fsw.Created += new FileSystemEventHandler(OnFileCreation);
fsw.EnableRaisingEvents = true;
main_engine.processDataToFile();
main_engine.processCreatedFile();
}
void OnFileCreation(object sender, FileSystemEventArgs e) {
// do some file processing
// takes time based on size of file and whether file is locked or not etc.
}
void processDataToFile() {
// do some data processing on received data and output to a file.
}
void processCreatedFile() {
// do not want this method to be called, unless OnFileCreation() finish it's work.
}
The reason choose to use FileSystemWatcher was because sometimes files are directly placed for processing instead of main_engine getting the data first and it works on multiple locations, so did not want to roll out a homegrown solution when FileSystemWatcher was available.
If the event fires in the separate thread you cant make it single-threaded. because this is not your code. end of story.
however it is quite simple to wait on:
...
me.WaitOne();
main_engine.processCreatedFile();
}
...
void OnFileCreation(object sender, FileSystemEventArgs e) {
// do some file processing
// takes time based on size of file and whether file is locked or not etc.
...
me.Set();
}
ManualResetEventSlim me = new ManualResetEventSlim(false);

FileSystemWatcher with Samba on Linux

I'm using a FileSystemWatcher on my C# application (running on Windows) in order to update in my app the files that I'm currently browsing.
It's work well when I browse a local directory. I am notified when a file is renamed, deleted or added.
But for example when I rename a file on the network drive the first time, the FileSystemWatcher notifies me of a rename action and then, when I rename the same file or another file, the FileSystemWatcher notifies me of an error :
the specified server cannot perform the requested operation.
Then the FileSystemWatcher not notify me about anything.
Sometimes I can rename twice before the FileSystemWatcher not notify me nothing...
Here is my test code :
static void Main(string[] args)
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = #"N:\prive\defFolder";
watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite;
watcher.Changed += new FileSystemEventHandler(watcher_Changed);
watcher.Created += new FileSystemEventHandler(watcher_Changed);
watcher.Deleted += new FileSystemEventHandler(watcher_Changed);
watcher.Renamed += new RenamedEventHandler(watcher_Renamed);
watcher.Error += new ErrorEventHandler(watcher_Error);
watcher.EnableRaisingEvents = true;
Console.Read();
watcher.Dispose();
}
static void watcher_Error(object sender, ErrorEventArgs e)
{
Console.WriteLine("error : " + e.GetException().Message);
}
static void watcher_Renamed(object sender, RenamedEventArgs e)
{
Console.WriteLine("rename success");
}
static void watcher_Changed(object sender, FileSystemEventArgs e)
{
Console.WriteLine("change success");
}
First of all, file system monitoring of remote shares is always going to be somewhat unreliable. You should not depend on your app getting all the events - in fact, I would suggest you provide a backup polling mechanism to check for changes that you may have missed. A refresh button in the GUI could be another option, depending on your app.
That said, your particular problem doesn't seem to be that uncommon. I googled around a bit and found these things:
Problem with FileSystemWatcher on 2003 server box - seems to be the same problem as you have, with a samba share and that "The specified server cannot perform the requested operation" error message.
SO Question regarding the same issue and one of the answers indicate that it worked for some customers and not for others
My guess is that this is a problem with certain versions (or configuration) of Samba combined with Windows. Are there anything in the Samba logs on the linux server that could point you towards the cause of the problem?
As an immediate workaround, I suggest you try these things:
Add a polling mechanism that ensures that you do get the folder changes even if the FSW breaks down
When the FSW breaks, try to "restart" it by creating a new one. You may also want to check if EnableRaisingEvents is set to false when you get the error - maybe you can just set it to true to start receiving events again.
(Grasping for straws here) try playing around with the internal buffer size in case that's the problem (I doubt it, but it's worth a shot)
if (Directory.Exists(monitorPath))
{
watcher.Path = monitorPath;
watcher.IncludeSubdirectories = true;
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.CreationTime;
watcher.InternalBufferSize = 65536;
watcher.Filter = "test_prod-Pg1_ICT*";
watcher.Changed += new FileSystemEventHandler(fileChangedEvent);
watcher.EnableRaisingEvents = true;
LogEvent("Folder Syncronization Service is Started!");
}
I created a Window Service FileSystemWatcher based class to Monitor a Samba Shared Folder onChanges and used DifferenceEngine from CodeProject to check the different and copy over to Window Shared Folder Path if there is a changes. I also added a Timer to check every 10 seconds to handle when network is fail. There is a List Array To store the changes count. Added into List when File Changed event is Raised and remove the List when is success.
I have tested two HP Laptop on Window 7 Pro OS, working fine.
But Failed to working on other Window 7 Pro Laptop and also Window XP Pro SP3 Desktop. (We are on same Company Network/VLAN and Service Pack)
The failed is mean if i amended something in Samba Shared Folder, it will not Sync the Latest content to Window Share Path.
I also has added these
[PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
[PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
in the top of the coding, it seem does not work
For people recently having this kind of problem, quoting from my answer to this question:
We are yet to test that this is a suitable alternative in our
situation, but it seems that Microsoft introduced
PhysicalFileProvider some time ago.
It has a UsePollingFileWatcher property specifically for this
kind of problem.
Then for the file watching, it seems you want the Watch method.
The documentation is currently showing it as not available on certain
platforms or target frameworks, but in practice the NuGet package
claims to be .NET Standard 2.0 compatible, so that should cover
basically everything.

How to copy a file as it is being written in C#

I am currently working on Windows Service to copy data from our security cameras as it is being written to the Google Drive directory on the computer for instant upload. The files are accessible immediately after creation by the provided playback software so we would like if possible to immediately copy the data stream, that way we have some video even if the recording is interrupted (the files are 10 minute time blocks).
I currently have a service created which can watch the directory, however I am having some difficulty determining the best way to watch these files. Since they are modified continuously for 10 minutes, I will receive a large number of changed events. I was hoping there might be a way that I can capture the initial creation and start streaming the data to a second file. My concern here is that I need to ensure that I don't overrun the recording stream.
If this isn't possible or relatively simple, then I will just have to detect when the file is no longer being written to by using some logic with the last write time, but I am looking for suggestions on what the best way to do this might be. I am aware of the solutions proposed Here, but I am unsure if they apply to the situation I am dealing with. There are a large number of files within sub-directories so trying to keep track of which files I have are no longer triggering events could get very messy. Does anyone have any suggestions for how to do either of these methods?
Hmmm... You could try using a timer... This way, you can limit when it fires
private Boolean TimeToCheck=false;
public static void Run()
{ Timer timer=new Timer(2000); //2 seconds
FileSystemWatcher fileWatch=new FileSystemWatcher();
fileWatch.Path="DirToWatch";
fileWatch.Filter="fileToWatch";
fileWatch.Changed += new FileSystemEventHandler(OnChanged);
fileWatch.Created += new FileSystemEventHandler(OnChanged);
fileWatch.Deleted += new FileSystemEventHandler(OnChanged);
//If you want rename, you could use the rename event as well fileWatch.Renamed += new RenamedEventHandler(OnRenamed);
timer.Elapsed += new ElapsedEventHandler(timer_done);
watcher.EnableRaisingEvents = true;
timer.Enabled = true; // Enable it
}
private static void OnChanged(object source, FileSystemEventArgs e)
{
if(TimeToCheck)
{
TimeToCheck=false;
timer.Enabled = false; // Enable it
//move the files
timer.Enabled = true; // Enable it
}
}
private static void OnRenamed(object source, RenamedEventArgs e)
{
if(TimeToCheck)
{
TimeToCheck=false;
timer.Enabled = false; // Enable it
//move the files
timer.Enabled = true; // Enable it
}
}
private static void timer_done(object sender, ElapsedEventArgs e)
{
TimeToCheck=true;
}
You could try to do this but to be honest this seems like a hack and I'm skeptical that Windows has any supported method for doing what you're trying to do. Essentially you're trying to listen in on a write stream.
It sounds like whatever solution you're working with right now is a black box so accessing the stream directly probably isn't an option. However, there is another approach. I would look into how you can create a virtual drive with your app in windows. That way you can have the recording application writing to your virtual drive path which will allow you to handle the streams however you like. Which can include writing them to two separate locations at the same time. Both Google drive and some local storage of some kind for example.
Here's a StackOverflow question on how to create virtual drives that should get you started: C#: Create a virtual drive in Computer
Have you looked at the FileSystemWatcher object? If i'm understanding the question correctly, it may be something you may want to use.... If you were to put this security file within a certain directory, you could then use file.copy to move the updated security log into the google drive folder...

Categories