Click here to download the solution
Below is the logical architecture

I have come across this issue quite a few times and this issue will be seen more often during deployment in QA/Production machine.
Its not unusual to see the below piece of code
using (FileStream fs = new FileStream(filePath, FileMode.Open))
{
XmlReader reader = XmlReader.Create(fs);
XmlSerializer serializer = new XmlSerializer(typeof(T));
Object o = serializer.Deserialize(reader);
}
Many times this will go unnoticed but if you look closely FileStream is using a constructor with FilePath and FileMode alone. System.IO.FileStream implementation of this constructor is
public FileStream(string path, FileMode mode) : this(path, mode, (mode == FileMode.Append) ? FileAccess.Write : FileAccess.ReadWrite, FileShare.Read, 0×1000, FileOptions.None, Path.GetFileName(path), false)
{
}
Default constructor asks for ReadWrite access, so now you see why your application is hosed in production, most of the developers use their system as admin user so of course they have the write access to the requested file. This is not to blame developers who run as admin because I can totally understand the pain.
By default, FileStream needs ReadWrite access that’s why System.UnauthorizedAccessException is thrown because on a production machine, User account under which asp.net worker process runs or a windows service or for that matter any process will not have the write access to a file by default.
Make sure, you ask for what you need. If your application needs only Read access to a file, make sure to specify that in your FileStream constructor. Don’t be GREEDY
using (FileStream fs = new FileStream(filePath, FileMode.Open,FileAccess.Read))
May be I would rather see a Read access by default in System.IO.FileStream implementation rather than ReadWrite.
With the release of Silverlight 3, you may run into issue where silverlight 2 application may not work as expected. Please read this article on msdn Ensuring That Your Silverlight 2 Applications Work with Silverlight 3
You may need to revert to Silverlight 2 runtime to make sure that the issue has to do with the Silverlight 3 runtime. First of all in order for you to revert back and forth between Silverlight 2 and Silverlight 3 runtime, you should not uninstall Silverlight 2 runtime from your machine. Silverlight runtime gets loaded based on Silverlight plug in which is a COM dll(npctrl.dll).
COM Dll CLSID is “DFEAF541-F3E1-4c24-ACAC-99C30715084A” which remains same in silverlight 3 basically, you can’t run Silverlight 2 and Silverlight 3 runtime(CLR for Silverlight) side by side. Once you install Silverlight 3 runtime, browser running silverlight 2 app will load the Silverlight 3 runtime, you can verify that by looking at the loaded silverlight runtime dll in browser process space. By Default, Silverlight 3 will be installed in “C:\Program Files\Microsoft Silverlight\3.xxxx” so in order for you to revert back and forth all you need to do is register and unregister com dll.
You can simply create a batch file to do the job
for example
Batch file to revert to silverlight 2 runtime, click to download
regsvr32 /u /s “C:\Program Files\Microsoft Silverlight\3.0.40624.0\npctrl.dll”
regsvr32 /s “C:\Program Files\Microsoft Silverlight\2.0.40115.0\npctrl.dll”
Revert to silverlight 3 runtime, click to download
regsvr32 /u /s “C:\Program Files\Microsoft Silverlight\2.0.40115.0\npctrl.dll”
regsvr32 /s “C:\Program Files\Microsoft Silverlight\3.0.40624.0\npctrl.dll”
I was writing a media streaming service along with file watcher so I thought I will share this piece of code in case anyone finds it useful. When developing Win32 Windows NT Service in old days, it used to be an exercise to debug a windows service from visual studio, I will always end up in writing a test harness to test those dependent dlls.
Although, managed code has made our life easier but I still write a service with nothing in it other than service control manager startup.
Step 1 – Define a contract for dynamic and configurable service
public interface IDynamicService
{
void StartUp(NameValueCollection configData);
void Shutdown();
}
Step2 – Service is configurable from a config file
<configuration>
<configSections>
<sectionGroup name=”StreamingServices”>
<section name=”ServiceMap” type=”System.Configuration.NameValueSectionHandler” />
<!– List of services–>
<section name=”MediaService” type=”System.Configuration.NameValueSectionHandler” />
<section name=”MaintenanceService” type=”System.Configuration.NameValueSectionHandler” />
</sectionGroup>
</configSections>
<appSettings>
<add key=”AppName” value=”StreamingServices” />
<add key=”ServiceName” value=”MediaService” />
</appSettings>
<StreamingServices>
<ServiceMap>
<!–Start MediaService only–>
<add key=”MediaService” value=”TRUE” />
</ServiceMap>
<MediaService>
<!– type name implementing the service–>
<add key=”Type” value=”StreamingMedia” />
<!– assembly name implementing the type, assembly metadata table only contains the assembly name with path or extension–>
<add key=”AssemblyName” value=”MediaService” />
<!–path to the assembly–>
<add key=”AssemblyPath” value=”MediaService.dll” />
<!–this service watches the folders for filesystem events–>
<add key=”Folders” value=”D:\StreamingService\Host” />
</MediaService>
<MaintenanceService>
<add key=”Type” value=”MaintenanceService” />
<add key=”AssemblyName” value=”MaintenanceService” />
<add key=”AssemblyPath” value=”MaintenanceService.dll” />
</MaintenanceService>
</StreamingServices>
</configuration>
Step 3 – create a struct for serviceinstance metadata
struct ServiceInstance
{
public NameValueCollection Configuration { get; set; }
public IDynamicService DynamicServiceInstance { get; set; }
}
Step 4 – Implementing the dynamic service
/// <summary>
///
/// </summary>
/// <param name=”appName”></param>
public DynamicService(string appName)
{
//read the service map section to iterate through list of services
NameValueCollection serviceMap = ConfigurationManager.GetSection(appName + “/ServiceMap”)
as NameValueCollection;
foreach (string serviceName in serviceMap.Keys)
{
try
{
//if the service name is true in the config file, add it to the list
//<add key=”MediaService” value=”TRUE” />
if (Convert.ToBoolean(serviceMap[serviceName]))
{
ServiceInstance serviceInstance = new ServiceInstance();
serviceInstance.Configuration = ConfigurationManager.GetSection(appName + “/” + serviceName)
as NameValueCollection;
serviceList.Add(serviceInstance);
}
}
catch (Exception ex)
{
//log it
throw ex;
}
}
}
public bool Start()
{
//iterate through each service set to true in config file
//<add key=”MediaService” value=”TRUE” />
for (int i = 0; i < serviceList.Count; i++)
{
try
{
ServiceInstance serviceInstance = serviceList[i];
//try to load the service using reflection
serviceInstance.DynamicServiceInstance = LoadServices(serviceInstance.Configuration);
if (serviceInstance.DynamicServiceInstance != null)
//service implementing the contract IDynamicService will be started here
serviceInstance.DynamicServiceInstance.StartUp(serviceInstance.Configuration);
}
catch (Exception ex)
{
//log it
throw ex;
}
}
return true;
}
/// <summary>
/// Shutdown all the services
/// </summary>
public void Shutdown()
{
//shutting down services in reverse order
for (int i = serviceList.Count – 1; i >= 0; i–)
{
try
{
ServiceInstance serviceInstance = serviceList[i];
if (serviceInstance.DynamicServiceInstance != null)
serviceInstance.DynamicServiceInstance.Shutdown();
}
catch (Exception ex)
{
//log it first
throw ex;
}
}
}
/// <summary>
/// this method is called recursively, it first loads the assembly as configured in .config
/// and then loads the type
/// </summary>
/// <param name=”assemblyPath”></param>
/// <param name=”typeName”></param>
/// <param name=”assemblyName”></param>
/// <returns></returns>
private object LoadType(string assemblyPath, string typeName, string assemblyName)
{
object objInstance = null;
bool assemblyLoaded = false;
try
{
//iterate through each assembly in the current domain to compare it with the
//configured assembly in app.config
Assembly[] assemblies = System.AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
//if assembly name is defined in the config file, load the type
//<add key=”AssemblyName” value=”MediaService” />
if (assembly.GetName().Name == assemblyName)
{
assemblyLoaded = true;
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (type.Name == typeName)
{
//<add key=”Type” value=”StreamingMedia” />
//if type name is defined, create the instance
objInstance = assembly.CreateInstance(type.FullName, false);
assemblyLoaded = true;
break;
}
}
break;
}
}
//called to load assembly from path
if (assemblyLoaded == false)
{
//<add key=”AssemblyPath” value=”MediaService.dll” />
Assembly.LoadFrom(assemblyPath);
//recursive call here
objInstance = LoadType(assemblyPath, typeName, assemblyName);
}
}
catch (Exception ex)
{
//log message
throw ex;
}
return objInstance;
}
/// <summary>
/// read the config section to load the assembly and type
/// </summary>
/// <param name=”configData”></param>
/// <returns></returns>
private IDynamicService LoadServices(NameValueCollection configData)
{
IDynamicService objRet = null;
try
{
string assemblyPath = configData[ASSEMBLY_PATH];
string typeName = configData[TYPE_NAME];
string assemblyName = configData[ASSEMBLY_NAME];
objRet = LoadType(assemblyPath, typeName, assemblyName) as IDynamicService;
}
catch (Exception ex)
{
//log message
throw ex;
}
return objRet;
}
}
Step 5 – Since we are going to watch the file system, we should never process a file in the same thread as the filewatcher event handler(cause of missing events, blocking the thread for longer duration, buffer and etc), we should just follow a producer consumer model to queue the data and hand it over to consumer. we will create a generic thread safe queue first
public class SyncQueue<T>
{
#region Private variables
private const int DEFAULT_CAPACITY = 25;
private object _syncRoot = null;
private Queue<T> _syncQueue = null;
private AutoResetEvent _resetEvent = new AutoResetEvent(false);
#endregion
#region Constructor
public SyncQueue()
: this(DEFAULT_CAPACITY)
{
}
public SyncQueue(int capacity)
{
_syncQueue = new Queue<T>(capacity);
_syncRoot = ((ICollection)_syncQueue).SyncRoot;
}
#endregion
#region public methods
public void Enqueue(T data)
{
if (data == null) new ArgumentNullException(“Null Argument”);
lock (_syncRoot)
{
_syncQueue.Enqueue(data);
}
_resetEvent.Set();
}
public T Dequeue()
{
lock (_syncRoot)
{
return _syncQueue.Dequeue();
}
}
public AutoResetEvent Signal
{
get { return _resetEvent; }
}
public int Count
{
get { return _syncQueue.Count; }
}
public Queue<T> Queue
{
get { return _syncQueue; }
}
#endregion
}
Step 6 – now we will define an abstract base class for File System Events, I have the FileSystemWatcher created in this base class to handle events but it may be better to have a composite type with filters and FileSystemWatcher created in a derived class for better reusability but it serves the purpose for me. I still prefer to suffix it with “Base” which is not preferred by many for abstract class
public abstract class FileSystemWatcherBase
{
#region Properties
private SyncQueue<string> FileQueue { get; set; }
private string RootPath { get; set; }
private string[] Filters { get; set; }
#endregion
#region constructors
protected FileSystemWatcherBase() { }
public void Initialize(FSStruct fsData)
{
CheckForNullArguments(fsData.FileQueue, “DataQueue<string> fileQueue”);
CheckForNullArguments(fsData.RootPath, “string rootPath”);
CheckForNullArguments(fsData.Filters, “string[] filters”);
FileQueue = fsData.FileQueue;
RootPath = fsData.RootPath;
Filters = fsData.Filters;
}
#endregion
#region public members
public virtual void Start()
{
string[] folders = Directory.GetDirectories(RootPath);
foreach (string folder in folders)
{
foreach (string filter in Filters)
{
CreateFSWatcher(folder, filter);
}
}
}
#endregion
#region protected members
protected void CreateFSWatcher(string folder, string filter)
{
FileSystemWatcher watcher = new FileSystemWatcher();
// Create a new FileSystemWatcher and set its properties.
watcher.Path = folder;
watcher.IncludeSubdirectories = true;
watcher.NotifyFilter = NotifyFilters.FileName;
watcher.Filter = filter;
// Add event handlers.
watcher.Created += new FileSystemEventHandler(OnCreated);
watcher.Error += new ErrorEventHandler(OnError);
// Begin watching.
watcher.EnableRaisingEvents = true;
}
#endregion
#region private methods
private void OnError(object source, ErrorEventArgs e)
{
Exception ex = e.GetException();
//to do—
}
private void OnCreated(object source, FileSystemEventArgs e)
{
FileQueue.Enqueue(e.FullPath);
}
private void CheckForNullArguments(object obj, string paramName)
{
if (obj == null)
throw new ArgumentNullException(paramName, “Null arguments in FileSystemWatcher Constructor”);
}
#endregion
}
#region data structure
public struct FSStruct
{
public SyncQueue<string> FileQueue;
public string RootPath;
public string[] Filters;
}
#endregion
Step 7 – Media Service to monitor and process the files
//implements the IDynamicService
public class MediaService : FileSystemWatcherBase, IDynamicService
{
private Thread workerThread;
private bool isRunning = false;
private SyncQueue<string> _fileQueue;
private AutoResetEvent _waitEvent;
public MediaService() { }
public void StartUp(NameValueCollection configData)
{
_waitEvent = new AutoResetEvent(false);
_fileQueue = new SyncQueue<string>();
string[] filters = { “*.mp4″, “*.mpeg” };
FSStruct fsData = new FSStruct()
{
FileQueue = _fileQueue,
Filters = filters,
RootPath = configData["Folders"]
};
Initialize(fsData);
Start();
}
public override void Start()
{
isRunning = true;
workerThread = new Thread(new ThreadStart(Run));
workerThread.Start();
_waitEvent.WaitOne();
Thread.Sleep(100);
base.Start();
}
public void Shutdown()
{
isRunning = false;
_fileQueue.Signal.Set();
ThreadHelper.WaitForThreadTermination(workerThread);
}
private void Run()
{
while (isRunning)
{
_waitEvent.Set();
_fileQueue.Signal.WaitOne(); // Wait for the file
while (_fileQueue.Count > 0)
{
try
{
//to do with file
}
catch (Exception ex)
{
//to do
}
}
}
}
}
Step 8 – Writing the service
Just 2 lines of code either in a console app or a Windows Service OnStart().
This will load numbers of services dynamically from a config file. Services can be removed or a new one can be added directly in a config file. You can debug it directly from a console appor a forms app making it reusable
protected override void OnStart(string[] args)
{
string appName = ConfigurationSettings.AppSettings["AppName"];
new DynamicService(appName).Start();
}
why do we have CLR.dll in .NET 4.0 but CoreCLR.dll in Silverlight. CoreCLR should be the .NET Framework 4.0 but you know what, Silverlight has stripped down version of CLR with everything stripped but the CORE so CoreCLR, whatever be the reason at least we have the similar name