FileSystemWatcher vs locked files

Standard

Git repository with example code discussed in this article.


Another Problem with FileSystemWatcher

You’ve just written your nice shiny new application to monitor a folder for new files arriving and added the code send that file off somewhere else and delete it. Perhaps you even spent some time packaging it in a nice Windows Service. It probably behaved well during debugging. You move it into a test environment and let the manual testers loose. They copy a file, your eager file watcher spots the new file as soon as it starts writing and does the funky stuff and BANG!… an IOException:

The process cannot access the file X because it is being used by another process.

The copying had not finished before the event fired. It doesn’t even have to be a large file as your super awesome watcher is just so efficient.

A Solution

  1. When a file system event occurs, store its details in Memory Cache for X amount of time
  2. Setup a callback, which will execute when the event expires from Memory Cache
  3. In the callback, check the file is available for write operations
  4. If it is, then get on with the intended file operation
  5. Else, put it back in Memory Cache for X time and repeat above steps

It would make sense to track and limit the number of retry attempts to get a lock on the file.

Code Snippets

I’ve built this on top of the code discussed in a previous post on dealing with multiple FileSystemWatcher events.

Complete code for this example solution here

When a file system event is handled, store the file details and the retry count, using a simple POCO, in MemoryCache with a timer of, something like 60 seconds:

A simple POCO:

In the constructor, I initialised my cache item policy with a callback to execute when these cached POCOs expire:

The callback itself…

  1. Increment the number retries
  2. Try and get a lock on the file
  3. If still lock put it back into the cache for another 60 seconds (repeat this MaxRetries times)
  4. Else, get on with the intended file operation

Other ideas / To do….

  • Could also store the actual event object
  • Could explore options for non-volatile persistence
  • Might find sliding expiration more appropriate in some scenario

A robust solution for FileSystemWatcher firing events multiple times

Standard

Git repository with example code discussed in this article.


The Problem

FileSystemWatcher is a great little class to take the hassle out of monitoring activity in folders and files but, through no real fault of its own, it can behave unpredictably, firing multiple events for a single action.

Note that in some scenarios, like the example used below, the first event will be the start of the file writing and the second event will be the end, which, while not documented behaviour, is at least predictable. Try it with a very large file to see for yourself.

However, FileSystemWatcher cannot make any promises to behave predictably for all OS and application behaviours. See also, MSDN documentation:

Common file system operations might raise more than one event. For example, when a file is moved from one directory to another, several OnChanged and some OnCreated and OnDeleted events might be raised. Moving a file is a complex operation that consists of multiple simple operations, therefore raising multiple events. Likewise, some applications (for example, antivirus software) might cause additional file system events that are detected by FileSystemWatcher.

Example: Recreating edit a file in Notepad firing 2 events

As stated above, we know that 2 events from this action would mark the start and end of a write, meaning we could just focus on the second, if we had full confidence this would be the consistent behaviour. For the purposes of this article, it makes for a convenient examples to recreate.

If you edited a text file in c:\temp, you would get 2 events firing.

Complete Console applications for both available on Github.

A robust solution

Good use of NotifyFilter (see my post on how to select NotifyFilters) can help but there are still plenty of scenarios, like those above, where additional events will still get through for a file system event.

I worked on a nice little idea for utilising MemoryCache as a buffer to ‘throttle’ additional events.

  1. A file event ( Changed in the example below) is triggered
  2. The event is handled by OnChanged. But instead of completing the desired action, it stores the event in MemoryCache with a 1 second expiration and a CacheItemPolicy  callback setup to execute on expiration.
  3. When it expires, the callback OnRemovedFromCache completes the behaviour intended for that file event.

Note that I use AddOrGetExisting as an simple way to block any additional events firing within the cache period being added to the cache.

If you’re looking to handle multiple, different, events from a single/unique file, such as Created with Changed , then you could key the cache on the file name and event named, concatenated.

NotifyFilters enumeration explained (FileSystemWatcher)

Standard

The Problem

When I first worked with the FileSystemWatcher class I ended up experimenting with combinations of NotifyFilters and event handlers to get the desired result; it is not immediately clear, which changes to files and folders, trigger which events.

The job can only get harder when also up against a known issues (just search on stackoverflow.com) with events firing twice.

EDIT: See my separate blog post, on a more reliable solution to the ‘two FileSystemWatcher events firing twice problem’.

Here, I hope to provide simple guidance on using the NotifyFilter enumeration for those just starting out with FileSystemWatcher.

What is a NotifyFilter?

These filters determine what you are watching and thus, which events can be triggered.

They can also be helpful in limiting the number of events trigger in some scenarios where complex file operations, or applications like antivirus software cause additional events to be triggered (see above) although you can’t have 100% confidence without some additional defensive coding.

Note that the default values for the NorifyFilter property  are LastWrite, FileName and DirectoryName.

So, what filters can result in a Changed event being triggered?

  • Attributes
  • CreationTime
  • LastAccess
  • LastWrite
  • Security
  • Size

Which filters can result in a Renamed event being triggered?

  • DirectoryName
  • FileName

Which filters can result in a Created event being triggered?

  • DirectoryName
  • FileName

And which filters can result in a Deleted event being triggered?

  • DirectoryName
  • FileName

In case you missed it in the MSDN documentation, you can combine more than one NotifyFilters member by using the bitwise OR operator like so:

I get two events when I create a new file… what’s with that?

Most guides to FileWatcher tend to lead you towards the Changed event. However, using this often leads to multiple events, which is not desirable. Try out the code in this gist to see the two-event behaviour (just copy a fileinto c:\temp when it’s running). Then try out the code in this other gist, demonstrating how you can use Created with NotifyFilters.FileName to get a single event from a new file in a folder.

A bit more….Where are the events for copying and moving?

Copied files will trigger Created events in the destination folder so use NotifyFilters.FileName.

The same applies for moved files but you can also watch the source folder for Deleted events (still using the same NotifyFilter).

The above works for copied  and moved folders (using instead, NotifyFilters.DirectoryName), although more code is required to trigger events for any files inside the folder. See: https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher(v=vs.110).aspx.

Appendix A – Table detailing NotifyFilters enumeration from MSDN:

Attributes The attributes of the file or folder.
CreationTime The time the file or folder was created.
DirectoryName The name of the directory.
FileName The name of the file.
LastAccess The date the file or folder was last opened.
LastWrite The date the file or folder last had anything written to it.
Security The security settings of the file or folder.
Size The size of the file or folder.

Source: https://msdn.microsoft.com/en-us/library/system.io.notifyfilters(v=vs.110).aspx

Appendix B – Table of events you’ll be interested in if you’ve landed here 

Changed Occurs when a file or directory in the specified Path is changed.
Created Occurs when a file or directory in the specified Path is created.
Deleted Occurs when a file or directory in the specified Path is deleted.
Renamed Occurs when a file or directory in the specified Path is renamed.

Source: https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher(v=vs.110).aspx

C# image extension methods for physical print size in millimetres

Standard

We had a business need for the actual print size of an image in millimetres.

The PhysicalDimension property on System.Drawing.Image was unfortunately not what I had hoped for.

Here’s a couple of extension methods that use the width and height in pixels, along with the DPI (as HorizontalResolution and VerticalResolution) to return an Image object’s width and height in mm.

Usage example for those new to using extension methods:

Persisting multiple checkbox states in session Storage (using jQuery)

Standard

The problem:

An existing ASP.NET MVC page allowed the user to apply additional an additional filter a to jQuery DataTable with a bunch of checkboxes in a modal/popup. These were being forgotten each time the user followed one of the links in the table and then returned.

The filtering took values directly from the checkboxes.

The state of the checkboxes needed to be saved when the modal was closed, then reloaded when they returned to the page.

The solution:

A quick fix using session storage on the client.

A brief explanation of Window.sessionStorage

It gives you access to an object on which to store key-value pairs, on the client side for the duration a window (or tab) is open.

Window.localStorage is also available, differing in that it does not expire on closing of the window.

As this was an internal website with all users on IE11 and there was no server-side need for the data, cookies were deemed unnecessary.

Key bits

To save the state of the check-boxes to session storage as JSON array:

To reload the state of the check-boxes:

Side note

The jQuery.inArray()> function behaves in a similar way to array.indexOf i.e.

JavaScript’s Array indexOf() method returns the index of the specified item, which is -1 if  not found. Similarly, jQuery’s inArray returns -1 for not found or otherwise the index (first only) where the item is found.

The consequence being, we need to avoid the == or !=, as doing so will result in a 0 being evaluated as false. So remember to use !==. Not so important in the example above as we are checking for -1 only.

JSFiddle

CSS for checkboxes borrowed from aahz’s Bootsnip.

Using FakeItEasy with Entity Framework 6

Standard

What this article is about

I have quickly become a fan of FakeItEasy. If you are not familiar with it, visit https://fakeiteasy.github.io/ and check out the super fluent interface yourself.

I couldn’t resist looking for a way to quickly fake out EF6 and I am going to share how that went.

What I will not be discussing

  • The differences between mocks, stubs and so on (see Gerard Meszaro‘s list for that)
  • The usefulness of mocking ORMs
  • The limitations of in-memory test doubles for a database


Background – testing with EF5

In EF5 (before my time!) we would create a mock DbSet class that implemented IDbSet, with a whole load of properties and methods. Then create an interface for a DbContext and implement that with a mocked context. I did this following the instructions here and it generated quite a lot of code to maintain for my relatively small project.

Changes in EF6

In EF6, DbSet gained an additional protected internal constructor. So instead of creating all those mocks, we mark the DbSet properties virtual, allowing FakeItEasy to override them:


Working with the DbSet methods

This is fairly straightforward and requires the behaviour of any DbSet method called to be defined.

Create instances of a fake context and fake DbSet, arrange the behaviour for calls to the Products getter and calls to the Add method on the DbSet:

Why not setup calls direct to the methods given as we need to define their behaviour individually?

We can but I prefer the first way as it has clearer logic and keeps things consistent with the way we can work with LINQ extension methods below. Opinions?

Note that there is no difference in arrangement between DbSet’s asynchronous and non-asynchronous methods.


Working with the LINQ extension methods (non-asynchronously)

So what if the method under test is using LINQ extension methods on the DbSet?

On the face of it these are tidier to work with because after setting up your fake DbSet, LINQ-to-Objects kicks in and there is no need to identify the behaviour of individual methods. We will take advantage of DbSet  implementing IQueryable:

For our in-memory storage we will use a List that implements IQueryable, which allows us to return its properties and method to use in the fake DbSet.

Next, we setup the fake DbSet. Note that FakeItEasy needs to be told explicitly to implement IQueryable in order for the Castle proxy to intercept.

To setup the behaviour for the DbSet under LINQ methods we can ‘redirect’ all calls to the method and properties of the IQueryable interface to the fakeIQueryable.

Finally, we setup the fake context and its behaviour when the Products DbSet getter is called; then go ahead and instantiate the object under test, passing it the fake context and a dummy to the Get method.

 

Working with the LINQ extension methods (asynchronously)

Problem 1: What if we used a similar test arrangement for a test method that calls an asynchronous LINQ extension method? e.g.

We get an error: The provider for the source IQueryable does not implement IDbAsyncQueryProvider…

So here we must change our behaviour for the Provider property. I have made use of a class provided by MSDN that wraps up our fakeIQueryable to provide an implementation of IDbAsyncQueryProvider:

Problem 2: What if we want to enumerate through the DbSet asynchronously?

We’ll get a different error message, and the solution here is to use another class provided in the link above to wrap up our fakeIQueryable to implement IDbAsyncEnumerator, replacing the original call to GetEnumerator form earlier.

FakeItEasy now also needs to be told to implement IDbAsyncEnumerable.

 

Validation

I did not have time to look at FakeItEasy and EF’s validation in depth.

I briefly considered one scenario where we might be relying on EF for our data validation, catching any DbEntityValidationException. We could quite easily check how our code handles validation errors by throwing a DbEntityValidationException e.g.

Then construct an IEnumerable of DbEntityValidationResult . However, this is just theory and I have not tried this myself yet!


Summary

If you are already using FakeItEasy in your tests, it is quite nice for consistency to be able to use it with Entity Framework without having to maintain mock code for DbContext and DbSet.

There are obvious limitations to how much behaviour can be faked this way. I did say I would not be debating the merits of mocking an ORM but here are just two issues with mocking EF:

  • The differences in behaviour between LINQ-to-Objects and LINQ-to-Entities are many – there is a good Stackoverlow.com answer here detailing some of these.
  • Mocking the behaviour of EF’s validation would likely be unmanageable

I would be interested in hearing others’ experiences of scenarios where it has been useful to mock EF.


Other options

There are a few other efforts (get the reference?) out there to provide support for testing EF but they are often poorly maintained. Highway.Data looks interesting but I have not tried it yet (link).

.NET Core now has an InMemory provider for testing (link).