August 28, 2012

Modifying Directory Access Rules

Here is the routine to do the work:
 
// Adds an ACL entry on the specified directory for the specified account.
public static void AddDirectorySecurity(
    string folderName, 
 string account, 
 FileSystemRights rights, 
 AccessControlType controlType)
{
    // Create a new DirectoryInfo object.
    DirectoryInfo dirInfo = new DirectoryInfo(folderName);

    // Get a DirectorySecurity object that represents the 
    // current security settings.
    DirectorySecurity dSecurity = dirInfo.GetAccessControl();

    // Add the FileSystemAccessRule to the security settings. 
    dSecurity.AddAccessRule(new FileSystemAccessRule(account,
                                                    rights,
                                                    controlType));

    // Set the new access settings.
    dirInfo.SetAccessControl(dSecurity);
}

Sample usage of the routine:
DirectoryInfo targetDir = GetDirectoryInfo();    
// eg Deny the current user write permission on a given directory       
AddDirectorySecurity(targetDir.FullName, Environment.UserName, 
    FileSystemRights.Write, AccessControlType.Deny);

There is a remove as well:
// Removes an ACL entry on the specified directory for the specified account.
public static void RemoveDirectorySecurity(string folderName, string account, FileSystemRights rights, AccessControlType controlType)
{
    // Create a new DirectoryInfo object.
    DirectoryInfo dInfo = new DirectoryInfo(folderName);

    // Get a DirectorySecurity object that represents the 
    // current security settings.
    DirectorySecurity dSecurity = dInfo.GetAccessControl();

    // Add the FileSystemAccessRule to the security settings. 
    dSecurity.RemoveAccessRule(new FileSystemAccessRule(account,
                                                    rights,
                                                    controlType));

    // Set the new access settings.
    dInfo.SetAccessControl(dSecurity);

}
These methods are useful when unit testing writing to a directory without the appropriate permission.

August 2, 2012

Generic Event Firer


Here is the common .NET pattern for firing some event
// Here is the event
public event EventHandler<ReminderEventArgs> ReminderOccured;
...
// And to fire it
EventHandler<ReminderEventArgs> reminderOccured = this.ReminderOccured;
if (reminderOccured != null)
{
    reminderOccured(this, new ReminderEventArgs { Reminder = reminder });
}

This is a common pattern so a helper class to tidy this up might be of some use:
public static class EventFirer
{
    public static void FireEvent<TEventArgs>(object firer, 
        EventHandler<TEventArgs> eventToFire, TEventArgs eventargs)
        where TEventArgs : EventArgs
    {
        EventHandler<TEventArgs> eventToFireReference = eventToFire;
        if (eventToFireReference != null)
        {
            eventToFireReference(firer, eventargs);
        }
    }

    public static void FireEvent(object firer, EventHandler eventToFire, 
        EventArgs eventargs)
    {
        EventHandler eventToFireReference = eventToFire;
        if (eventToFireReference != null)
        {
            eventToFireReference(firer, eventargs);
        }
    }
}
With this class firing the event becomes:
EventFirer.FireEvent<ReminderEventArgs>(this, 
    this.ReminderOccured, 
    new ReminderEventArgs { Reminder = reminder });

June 29, 2012

Windows Service Class

A WindowsService class to expose a windows service. This class also exposes some techniques such as
  1. Delegating events.
  2. Using Interlocked.CompareExchange to reduce the threads waiting in a timer delegate.
  3. The use of a System.Threading.Timer type timer.
  4. Implementing IDisposable
/// <summary>
/// WIP: Exposes a window service including an event 
/// that fires when the service status changes
/// </summary>
public class WindowsService : IDisposable
{
  ServiceController serviceController = null;
 
  /// <summary>
  /// Use this method to check that the named service exists 
  /// before creating a WindowsService object for it.
  /// </summary>
  /// <param name="serviceDisplayName">The user friendly name for the service</param>
  /// <param name="machineName">Machine upon which the service is created</param>
  /// <returns>true if a service by the given name and on the given machine exists</returns>
  public static bool CheckServiceExists(string serviceDisplayName, 
                                        string machineName = ".")
  {      
    ServiceController[] scs = ServiceController.GetServices(machineName);
    ServiceController scFound = scs.FirstOrDefault(
      (ServiceController sc) => sc.DisplayName == serviceDisplayName);
    return (scFound != null);
  }
 
  public WindowsService(string serviceDisplayName, string machineName = ".")
  {
    serviceController = new ServiceController(serviceDisplayName, machineName);
    timer = new Timer(new TimerCallback(TimerProc));
  }
 
  public WindowsService(ServiceController sc)
  {
    // Check sc, how?
    string str = sc.DisplayName;
    serviceController = sc;
    timer = new Timer(new TimerCallback(TimerProc));
  }
 
  private string Path
  {
    get
    {
      string path = "\\\\" + this.serviceController.MachineName +
        "\\root\\cimv2:Win32_Service.Name='" + 
        this.serviceController.ServiceName + "'";
      return path;
    }
  }
 
  public string MachineName
  {
    get { return this.serviceController.MachineName; }
  }
 
  public string ServiceName
  {
    get { return this.serviceController.ServiceName; }
  }
 
  public void Start()
  {
    this.serviceController.Start();
  }
 
  public void Stop()
  {
    this.serviceController.Stop();
  }
 
  object statusRefreshlock = new object();
 
  private ServiceControllerStatus GetStatus() // thread safe
  {
    ServiceControllerStatus scs;
    lock (this.statusRefreshlock)
    {
      this.serviceController.Refresh();
      scs = this.serviceController.Status;
    }
    return scs;
  }
 
  public ServiceControllerStatus Status // thread safe
  {
    get { return this.GetStatus(); }
  }
 
  public bool CanPauseAndContinue
  {
    get { return this.serviceController.CanPauseAndContinue; }
  }
 
  public bool CanShutdown
  {
    get { return this.serviceController.CanShutdown; }
  }
 
  public bool CanStop
  {
    get { return this.serviceController.CanStop; }
  }
 
  public string DisplayName
  {
    get { return this.serviceController.DisplayName; }
  }
 
  #region Extra properties
 
  public string Description
  {
    get
    {
      string res = "";
      ManagementPath mPath = new ManagementPath(this.Path);
      //construct the management object
      using (ManagementObject ManagementObj = new ManagementObject(mPath))
      {
        object obj = ManagementObj["Description"];
        if (obj != null)
        {
          res = obj.ToString();
        }
      }
      return res;
    }
  }
 
  public string FilePath
  {
    get
    {
      string res = "";
      ManagementPath mPath = new ManagementPath(this.Path);
      //construct the management object
      using (ManagementObject ManagementObj = new ManagementObject(mPath))
      {
        object obj = ManagementObj["PathName"];
        if (obj != null)
        {
          res = obj.ToString();
        }
      }
      return res;
    }
  }
 
 
  /// <summary>
  /// Gets or sets the start mode.
  /// </summary>
  public ServiceStartMode StartMode
  {
    get
    {
      ManagementPath mPath = new ManagementPath(this.Path);
      string mode = "";
      using (ManagementObject manager = new ManagementObject(mPath))
      {
        mode = manager["StartMode"].ToString();
      }
      ServiceStartMode res = ServiceStartMode.Disabled;
      Enum.TryParse<ServiceStartMode>(mode, out res);
      return res;
    }
    set
    {
      ManagementPath mPath = new ManagementPath("Win32_Service.Name='" + this.serviceController.ServiceName + "'");
      using (ManagementObject manager = new ManagementObject(mPath))
      {
        manager.InvokeMethod("ChangeStartMode"new object[] { value.ToString() });
      }
    }
  }
 
  #endregion Extra properties
 
  /// <summary>
  /// Send an event when the status of the windows service has changed, 
  /// Beware: this event will be invoked on a foreign thread!
  /// </summary>
  public event EventHandler<StatusChangedEventArgs> StatusChanged
  {
    add
    {
      serviceStatusChanged += value;
      ++count;
      if (count == 1) // Start listening as soon as someone registers for an event
        timer.StartPeriodic(updatePeriod);
    }
    remove
    {
      serviceStatusChanged -= value;
      --count;
      if (count == 0) // Stop listening as soon as there is no-one registered for events
        timer.Stop();
    }
  }
 
  #region ServiceStatusChanged Implementation
 
  // Normally implementation of add/remove are hidden 
  // but it is still possible to define them explicitly
  private EventHandler<StatusChangedEventArgs> serviceStatusChanged;
  int count = 0; // count the number of event handlers added
 
 
  public class StatusChangedEventArgs : EventArgs
  {
    public StatusChangedEventArgs(ServiceControllerStatus oldState, 
                                  ServiceControllerStatus newState)
    {
      OldStatus = oldState;
      NewStatus = newState;
    }
 
    public ServiceControllerStatus OldStatus
    {
      get;
      private set;
    }
 
    public ServiceControllerStatus NewStatus
    {
      get;
      private set;
    }
 
  }
 
  const int updatePeriod = 500; // update period in millseconds
 
  Timer timer = null;
  // prevStatus only ever accessed in the TimerProc method by one thread at a time
  ServiceControllerStatus prevStatus = ServiceControllerStatus.Stopped;
  int timerProcInUse = 0;
 
  // The Timer delegate to be invoked on a callback (from 
  // another thread)
  private void TimerProc(object obj)
  {
    // Only allow one thread to enter but dont block other threads 
    // they will simply exit, but this does not matter 
    // as only one update at a time is required.
    // This will stop them running into each other if the 
    // PC slows down or when debugging
    if (System.Threading.Interlocked.CompareExchange(
        ref timerProcInUse, 1, 0) == 0)
    {
      // Careful. TimeOut callback occurs on another thread
      // GetStatus() is thread safe
      ServiceControllerStatus newStatus = this.GetStatus(); 
      if (newStatus != this.prevStatus)
      {
        this.prevStatus = newStatus;
        if (this.serviceStatusChanged != null)
        {
          this.serviceStatusChanged(this, 
            new StatusChangedEventArgs(prevStatus, newStatus));
        }
      }
      // No longer in use
      timerProcInUse = 0;
    }
  }
 
  #endregion ServiceStatusChanged Implementation
 
  #region Dispose Implementation
 
  private void DisposeTimer()
  {
    if (this.timer != null)
    {
      this.timer.Dispose();
      this.timer = null;
    }
  }
 
  // Use C# destructor syntax for finalization code.
  ~WindowsService()
  {
    Debug.Assert(false"This object was not disposed of");
    Dispose(false);
  }
 
  private bool m_Disposed = false;
 
  //Implement IDisposable.
  public void Dispose()
  {
    Dispose(true);
    GC.SuppressFinalize(this);
  }
 
  protected virtual void Dispose(bool disposing)
  {
    if (m_Disposed)
      return;
 
    // leanup unmanaged resources in WindowsService
    DisposeTimer();
 
    m_Disposed = true;
  }
 
  #endregion Dispose Implementation
 
}
Uses the System.Threading.Timer extension methods

System.Threading.Timer extension methods

The methods of the System.Threading.Timer are not particularly intuitive. Wrote these set of extension methods to make them a bit easier to use:

public static class TimerExtensions
{
 
  /// <summary>
  /// Stop the timer. 
  /// </summary>
  /// <param name="timer"></param>
  public static void Stop(this System.Threading.Timer timer)
  {
    timer.Change(Timeout.Infinite, Timeout.Infinite);
  }
 
  /// <summary>
  /// Start the timer as a periodic timer.  
  /// </summary>
  /// <param name="timer">target timer</param>
  /// <param name="periodMs">Delay imbetween TimerCallback invokations.
  /// Period is expressed in milliseconds </param>
  public static void StartPeriodic(this System.Threading.Timer timer, int periodMs)
  {
      // Note that timer.Change(Timeout.Infinite, periodMs); does not work!
      timer.Change(periodMs, periodMs);
  }
  /// <summary>
  /// Start the timer as a once only timer. 
  /// </summary>
  /// <param name="timer">target timer</param>
  /// <param name="periodMs">Period before the single invokation of the TimerCallback, 
  /// expressed in milliseconds </param>
  public static void StartOneTime(this System.Threading.Timer timer, int periodMs)
  {
    timer.Change(periodMs, Timeout.Infinite);
  } 
then the timer can be created, started and stopped very simply:
Timer timer = new Timer(new TimerCallback(TimerProc));
...
timer.StartPeriodic(500);
...
timer.Stop();

Don't forget the timer delegate:
// The Timer delegate to be invoked on a callback (from 
// another thread)
private void TimerProc(object obj)
{
    // Careful! callback occurs on another thread
}

Don't forget to dispose of the timer:

private void DisposeTimer()
{
    if (this.timer != null)
    {
        this.timer.Dispose();
        this.timer = null;
    }
}

May 2, 2012

XmlSerializer Usage

C# Tutorial - XML Serialization

Watch out for derived classes, the Xml serializer will not know how to serialize them without being told about them.
For example, a base class is "MenuItemDefinition"
Derived classes are "StartExecutableMenuItem", "RestartExecutableMenuItem"
To serialize instances of the base class, create an XmlSerializer thus:
XmlSerializer serializer = new XmlSerializer(
  typeof(List<MenuItemDefinition>),   // Object type to serialize
  // Following list of types are derived class types that the 
  // XmlSerializer will need to know about to perform the serialization
  new Type[] { typeof(StartExecutableMenuItem), typeof(RestartExecutableMenuItem), });
so here is the full serialization:
private void MenuItemsSerialize()
{
    IEnumerable<MenuItemDefinition> menuItems = LoadMenuItemDefinitions();
    var li = new List<MenuItemDefinition>();
    li.AddRange(menuItems);

    XmlSerializer serializer = new XmlSerializer(
      typeof(List<MenuItemDefinition>), // Object type to serialize
      // List of types that are derived class types that the 
      // XmlSerializer will need to know about to perform the serialization
      new Type[] { 
        typeof(StartExecutableMenuItem), 
        typeof(RestartExecutableMenuItem), }
    );
    string path = Path.Combine(Path.GetTempPath(), "delme.xml");
    TextWriter textWriter = new StreamWriter(path);
    serializer.Serialize(textWriter, li);
    textWriter.Close();
}
Alternatively a bunch of XmlInclude attributes on the base class will do the job.

April 29, 2012

Page Breaks in HTML

Page break after description

Fixing page breaks just after a title when printing HTML.
Used an XSLT transform to break my document into sections each with a title. Trouble is when printing HTML, there is no way to know where the page break will be placed. In my case I ended up with page breaks just after a section title!. Fixed this by putting a <br style="page-break-after:always"/> at the end of each section. There are other types of page break in CSS but this fixed the problem and quickly. Some browsers do not accept all forms of page break; Firefox, for example.

April 24, 2012

Non-Virtual Interface Design Pattern

The Non-Virtual Interface Design Pattern is described here: http://www.blackwasp.co.uk/NVI.aspx

Basically the pattern promotes the use of non-virtual public base class methods that can be used by clients. A set of overridable behaviours are exposed (as protected or protected internal) that are invoked directly by exposed public methods in the base class. This way the base class behaviour can be overriden by deriving classes.