Posts Tagged ‘cambo’

cambo » LINQ Deferred Execution & Lambda Methods for providing Simple Stats (Part II)

Friday, May 24th, 2013

Important!

This is part 2 in a series of posts on Linq & Lambda capabilities in C# 

Deferred Execution

So lets take a minute to talk about deferred execution. You may here this referred to as Lazy Execution as well. But in a nutshell what this means is that when you write a linq or lambda query against a collection or list, the execution of that query doesn’t actually happen until the point where you need to access the resuts. Let’s look at a simple example.

var ienum = Enumerable.Range(1, 10).ToList();

var query = from i in ienum
            where i%2 == 0
            select i;

ienum.Add(20);
ienum.Add(30);

SuperConsole.WriteLine(query);
//prints 2, 4, 6, 8, 10, 20, 30

So why does it print out 20 and 30. This is deferred execution in practice. At the point where you write your query (var query) the query is not actually executed against your datasource (ienum). After the query is setup, more data is added to your data source, and the query is only actually executed at the point where the results need to be evaluated (SuperConsole.WriteLine)

This holds true in a number of other Linq Scenarios. In Linq-to-Sql or Linq-to-Entity Framework, execution of the Sql Query is only sent to the database at the point where you need to evaluate your queries. It’s important to understand this so that queries don’t go out of scope before being executed, so that un-executed queries aren’t inadvertently passed to other parts or layers in your application and so that you don’t end up introducing N+1 problems where you think your working on data in memory but in actual fact, your performing multiple executions over and over in a loop. If you do need to make your queries “Greedy” and force them to execute there and then, you can wrap them in parenthesis and immediately call .ToList() on them to force the execution.

Min, Max, Count & Average

Linq has a number of convenient built in methods for getting various numeric stats about the data your working on. Consider a collection of Movies which you want to Query.

public class Movie
{
    public string Title { get; set; }
    public double Rating { get; set; }
}

...

var movies = new List
    {
        new Movie() {Title = "Die Hard", Rating = 4.0},
        new Movie() {Title = "Commando", Rating = 5.0},
        new Movie() {Title = "Matrix Revolutions", Rating = 2.1}
    };

Console.WriteLine(movies.Min(m => m.Rating));
//prints 2.1

Console.WriteLine(movies.Max(m => m.Rating));
//prints 5

Console.WriteLine(movies.Average(m => m.Rating));
//prints 3.7

Console.WriteLine(movies.Count);
Console.WriteLine(movies.Count());
//prints 3

Min, Max and Average are all fairly straight forward, finding the Minimum, Maximum and Average movie rating values respectively. It’s worth mentioning with regards the Count implementations that there are different “versions” of the count implementation depending on the underlying data structure you are operating on. The Count property is a property of the List class are returns the current number of items in that collection. The Count() method is an extension method on the IEnumerable interface which can be executed on any IEnumerable structure regardless of implementation.

In general LINQ’s Count will be slower and is an O(N) operation while List.Count and Array.Length are both guaranteed to be O(1). However in some cases LINQ will special case the IEnumerable parameter by casting to certain interface types such as IList or ICollection. It will then use that Count method to do an actual Count() operation. So it will go back down to O(1). But you still pay the minor overhead of the cast and interface call. Ref: [http://stackoverflow.com/questions/981254/is-the-linq-count-faster-or-slower-than-list-count-or-array-length/981283#981283]

This is important as well if you are testing your collections to see if they are empty. People coming from versions of .NET previous to Generics would use the Count or Length properties of a collection to see if they were empty. i.e.

if(list.Count == 0)
{ 
    //empty
}
if(array.Length == 0)
{
    //empty
}

Linq however provides another method to test for contents called Any(). It can be used to evaluate whether the collection is empty, or if the collection has any items which validate a specific filter.

if(list.Any()) //equivalent of count == 0
{ 
    //empty
}
if(list.Any(m => m.Rating == 5.0)) //if it contains any top rated movies.
{
    //empty
}

If you are starting with something that has a .Length or .Count (such as ICollection, IList, List, etc) – then this will be the fastest option, since it doesn’t need to go through the GetEnumerator()/MoveNext()/Dispose() sequence required by Any() to check for a non-empty IEnumerable sequence. For just IEnumerable, then Any() will generally be quicker, as it only has to look at one iteration. However, note that the LINQ-to-Objects implementation of Count() does check for ICollection (using .Count as an optimisation) – so if your underlying data-source is directly a list/collection, there won’t be a huge difference. Don’t ask me why it doesn’t use the non-generic ICollection… Of course, if you have used LINQ to filter it etc (Where etc), you will have an iterator-block based sequence, and so this ICollection optimisation is useless. In general with IEnumerable : stick with Any() Ref: [http://stackoverflow.com/questions/305092/which-method-performs-better-any-vs-count-0/305156#305156]

Next post, we’ll look at some different mechanisms for filtering and transforming our queries.

~Eoin C

cambo » Handy LINQ & Lambda Methods and Extensions (Part I)

Thursday, May 23rd, 2013

The System.Linq namespace contains a fantastic set of utility extension methods for filtering, ordering & manipulating the contents of your collections and objects. In the following posts I’ll go through some of the most useful ones (in my humble opinion) and how you might use them in your C# solutions

Important!

This is part 1 in a series of posts on Linq & Lambda capabilities in C# 

Before we start, here’s a handy static method to print your resulting collections to the console so you can quickly verify the results.

public class SuperConsole
{
    public static void WriteLine<T>(IEnumerable<T> list, bool includeCarriageReturnBetweenItems =false)
    {
        var seperator = includeCarriageReturnBetweenItems ? ",\n" : ", ";
        var result = string.Join(seperator, list);
        Console.WriteLine(result);
    }
}

Enumerable

The System.Linq.Enumerable type has 2 very useful static methods on it for quickly generating a sequence of items. Enumerable.Range & Enumerable.Repeat. The Range method allows you to quickly generate a sequential list of integers from a given starting point for a given number of items.

IEnumerable<int> range = Enumerable.Range(1, 10);
SuperConsole.WriteLine(range);
//prints "1, 2, 3, 4, 5, 6, 7, 8, 9, 10"

So why is this useful, well you could use it to quickly generate a pre-initialised list of integers rather than new’ing up a list and then iterating over it to populate it. Or you could use it to replicate for(;;) behavior. e.g.

for (int i = 1; i <= 10; i++) 
{     
    //DoWork(i); 
} 

Enumerable.Range(1, 10).ToList().ForEach(i =>
    {
        //DoWork(i)
    });

Repeat is similar but is not limited to integers. You can generate a Sequence of a given length with the same default value in every item. Imagine you wanted to create a list of 10 strings all initialised with a default string of “ABC”;

var myList = Enumerable.Repeat("ABC", 10).ToList();

Item Conversion

There are also a few handy ways to convert/cast items built into the System.Linq namespace. The Cast<T> extension method allows you to cast a list of variables from one type to another as long as a valid cast is available. This can be useful for quickly changing a collection of super types into their base types.

var integers = Enumerable.Range(1, 5);
var objects = integers.Cast<object>().ToList();

Console.WriteLine(objects.GetType());
SuperConsole.WriteLine(objects);

//prints
//System.Collections.Generic.List`1[System.Object]
//1, 2, 3, 4, 5

But what if a valid implicit cast isn’t available. What if we wanted to convert our collection of integers into a collection of strings with a ‘:’ suffix. Thankfully Linq has us covered with it’s ConvertAll Method on List

var integers = Enumerable.Range(1, 5);
var converter = new Converter<int, string>(input => string.Format("{0}: ", input));
var results = integers.ToList().ConvertAll(converter);

SuperConsole.WriteLine(results, true);
/*prints
    1:
    2:
    3:
    4:
    5:
    */

In the next post, we’ll look at some the lazy & deferred execution capabilities of LINQ and some useful methods for performing quick calculations and manipulations on our collections.

~Eoin C

cambo » Implementing HTML Formatted Emails in the Enterprise Library Logging Block

Tuesday, May 21st, 2013

Enterprise LibraryThe Microsoft Patterns & Practices Enterprise Library contains a number of useful applications blocks for simplifying things like DataAcces, Logging & Exception Handling in your .NET Applications. Recently we had a requirement to add HTML based formatting to the Email TraceListener in the Logging Application Block, something that’s unfortunately missing from the base functionality. Thankfully, Enterprise Library is an open source code plex project so implementing a custom solution is a relatively trivial task. The email tracelistener functionality is contained in 3 main files: EmailTraceListener – The actual listener which you add to your configuration EmailTraceListenerData – The object representing the configuration settings EmailMessage – The wrapper object around a LogMessage which gets sent via email. Unfortunately because of the the way these classes are implemented in the EnterpriseLibrary Logging Block, they are not easily extended due to dependencies on Private Variables and Internal classes in the EnterpriseLibaray Logging Assembly so they need to be fully implemented in your own solution.

Implementing a Solution

Step 1 was to take a copy of these three files and place them in my own Library Solution. I prefixed the name of each of them with Html; HtmlEmailTraceListener, HtmlEmailTraceListenerData and HtmlEmailMessage. Other code needed to be cleaned up including removing some dependencies on the internal ResourceDependency attributes used to decorate properties within the class & tidying up the Xml Documentation Comments. The main change was then to enable the IsBodyHtml flag on the mail message itself. This was done in the CreateMailMessage method of the HtmlEmailMessage

protected MailMessage CreateMailMessage()
{
	string header = GenerateSubjectPrefix(configurationData.SubjectLineStarter);
	string footer = GenerateSubjectSuffix(configurationData.SubjectLineEnder);

	string sendToSmtpSubject = header + logEntry.Severity.ToString() + footer;

	MailMessage message = new MailMessage();
	string[] toAddresses = configurationData.ToAddress.Split(';');
	foreach (string toAddress in toAddresses)
	{
		message.To.Add(new MailAddress(toAddress));
	}

	message.From = new MailAddress(configurationData.FromAddress);

	message.Body = (formatter != null) ? formatter.Format(logEntry) : logEntry.Message;
	message.Subject = sendToSmtpSubject;
	message.BodyEncoding = Encoding.UTF8;
	message.IsBodyHtml = true;

	return message;
}

Using your new solution

Once implemented it’s simply a matter of reconfiguring your app/web.config logging sections to use the new types you’ve created instead of the original Enterprise Library types. You need to change the type and listenerDataType properties of your Email Listener in the &gl;listeners@gt; section of your config.

<listeners>
      <!-- Please update the following Settings: toAddress, subjectLineStarter, subjectLineEnder-->
      <add name="EmailLog"
           toAddress="toAddress@example.com"
           subjectLineStarter="Test Console - "
           subjectLineEnder=" Alert"
           filter="Verbose"
           fromAddress="fromAddress@example.com"
           formatter="EmailFormatter"
           smtpServer="smtp.gmail.com"
           smtpPort="587"
           authenticationMode="UserNameAndPassword"
           useSSL="true"
           userName="fromAddress@example.com"
           password="Password"
           type="YourLibrary.YourNamespace.HtmlEmailTraceListener, YourLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0000000000000000"
           listenerDataType="YourLibrary.YourNamespace.HtmlEmailTraceListenerData,  YourLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0000000000000000"
           traceOutputOptions="Callstack" />
    </listeners>

You’ll also need to ensure that you’ve escaped your Html formatted textFormatter template in the formatters section of your code. i.e. replacing <html> with &lt;html&gt;

<formatters>
      <add name="EmailFormatter" 
              type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
              template="
                  &lt;html&gt;
                  &lt;body&gt;
                  &lt;table border=&quot;1&quot; style=&quot;border: solid 1px #000000; border-collapse:collapse;&quot;&gt;
                  &lt;tr&gt;&lt;td&gt;&lt;b&gt;Message&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;{message}&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;Local TimeStamp&lt;/td&gt;&lt;td&gt;{timestamp(local)}&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;Timestamp&lt;/td&gt;&lt;td&gt;{timestamp}&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;Title&lt;/td&gt;&lt;td&gt;{title}&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;Severity&lt;/td&gt;&lt;td&gt;{severity}&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;Category&lt;/td&gt;&lt;td&gt;{category}&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;Priority&lt;/td&gt;&lt;td&gt;{priority}&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;EventId&lt;/td&gt;&lt;td&gt;{eventid}&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;Local Machine&lt;/td&gt;&lt;td&gt;{localMachine}&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;AppDomain&lt;/td&gt;&lt;td&gt;{appDomain}&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;LocalDomain&lt;/td&gt;&lt;td&gt;{localAppDomain}&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;Local Process Name&lt;/td&gt;&lt;td&gt;{localProcessName}&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;Local Process&lt;/td&gt;&lt;td&gt;{localProcessId}&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;Win32ThreadId&lt;/td&gt;&lt;td&gt;{win32ThreadId}&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;ThreadName&lt;/td&gt;&lt;td&gt;{threadName}&lt;/td&gt;&lt;/tr&gt;
                  &lt;tr&gt;&lt;td&gt;Extended Properties&lt;/td&gt;&lt;td&gt;
                  &lt;table border=&quot;1&quot; style=&quot;border: solid 1px #000000; border-collapse:collapse;&quot;&gt;
                  {dictionary(&lt;tr&gt;&lt;td&gt;{key}&lt;/td&gt;&lt;td&gt;{value}&lt;/td&gt;&lt;/tr&gt;)}
                  &lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;
                  &lt;/table&gt;
                  &lt;/body&gt;
                  &lt;/html&gt;
" />

    </formatters>

All done. Now you can happily send email log messages in HTML format via your Application Logging calls.

~EoinC

cambo » Using Signlar to Publish Dashboard Data

Wednesday, May 15th, 2013
SignalR

SignalR

Recently David Fowler announced the release of the Signlar 1.1.0 Beta Release. So I decided to do some dabbling to get a prototype application up and running. The solution is pretty simple. It uses a SignlaR hub to broadcast the current Processor % usage, and renders it in a nice visual graph using HighCharts.

 

Important!

The completed solution can be found on GitHub at https://github.com/eoincampbell/signalr-processor-demo 

First things first we’ll need a bare bones web application which we can pull in the relevant nuget packages into. I started with a basic empty web application running under .NET 4.5. Installing the signlar & highcharts packages is a breeze. Open up the PowerShell Nuget Console and run the following commands. HighCharts gets installed as a solution level package so you’ll need to manually copy the relevant JavaScript files to your scripts directory in your application.

Install-Package HighCharts
Install-Package Microsoft.AspNet.SignalR

The Hub

Signalr relies on a “Hub” to push data back to all the connected Clients. I’ve created a “ProcessorDataHub” which implements the Signalr Base Hub to manage this process. It contains a constructor for Initializing a static instance of my ProcessorTicker class, and a start method to start the thread within the ticker. The HubName attribute specifies the name which the hub will be accessible by on the Javascript side.

[HubName("processorTicker")]
public class ProcessorDataHub : Hub
{
    private readonly ProcessorTicker _ticker;

    public ProcessorDataHub() : this(ProcessorTicker.Instance) { }

    public ProcessorDataHub(ProcessorTicker ticker)
    {
        _ticker = ticker;
    }

    public void Start()
    {
        _ticker.Start(Clients);
    }
}

The ProcessorTicker

The heavy lifting is then done by the ProcessorTicker. This is instantiated with a reference to the Clients object, a HubConnectionContext which contains dynamic objects allowing you to push notifications to some or all connected client side callers. The implementation is fairlly simple using a System.Thread.Timer which reads the current processor level from a peformance counter once per second, and Broadcasts that value to the client side.

Since the Clients.All connection is dynamic, calling “updateCpuUsage” on this object will work at runtime, so long as the relevant client side wiring up to that expected method has been done correctly.

Clients.All.updateCpuUsage(percentage);

The Client Side

One change since the previous version of SignalR is the requirement for the developer to manually & explicity wireup the dynamically generated Javascript endpoint where SignalR creates it’s javascript. This can be done on Application Start by calling the RouteTable..Routes.MapHubs() method

protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.MapHubs();
}

Finally we’re ready to consume these published messages on our Client Page. Signlar requires the following javascript includes in the Head Section of your page.

<script type="text/javascript" src="/Signalr/Scripts/jquery-1.6.4.js"></script>
<script type="text/javascript" src="/Signalr/Scripts/jquery.signalR-1.1.0-beta1.js"></script>
<script type="text/javascript" src="/Signalr/signalr/hubs"></script>

With those inplace, we wire up our own custom Javascript function to access our ProcessorTicker, start the Hub on a button click, and begin receiving and processing the

    <script type="text/javascript">
    $(function () {
        var ticker = $.connection.processorTicker;

        //HighCharts JS Omitted..

        ticker.client.updateCpuUsage = function (percentage) {
            $("#processorTicker").text("" + percentage + "%");

            var x = (new Date()).getTime(), // current time
                y = percentage,
                series = chart.series[0];

            series.addPoint([x, y], true, true);
        };

        // Start the connection
        $.connection.hub.start(function () {
            //alert('Started');
        });

        // Wire up the buttons
        $("#start").click(function () {
            ticker.server.start();
        });
    });
</script>

The result is that I can fire up a number of separate browser instances and they’ll all get the correct values published to them from the hub over a persistent long running response. Obviously this an extremely powerful system that could be applied to Live Operations Systems where dash boards have traditionally relied on polling the server at some regular interval.

Live Processor Data to Multiple Browsers via SignalR

Live Processor Data to Multiple Browsers via SignalR

~Eoin C

cambo » When’s a Deep Dive not a Deep Dive ?

Monday, April 29th, 2013

Global Windows Azure Bootcamp

This weekend, I attended the Global Windows Azure Deep Dive conference in the National College of Ireland, Dublin. Microsoft in conjunction This was a community organised event where Local & National IT Organisations, Educational Institutions & .NET Communities were running a series of events in parallel in a number of cities around the world. The purpose; Deep Dive into the latest technology available on Microsoft as well as take part in a massively parallel lab where participants from all over the world would spin up worker roles to contribute to 3D graphics rendering based on depth data from a KINECT. Alas, Deep it was not, and Dive we didn’t.

I suppose I can’t complain too much. You get what you pay for and it was a free event but I’d have serious reservations about attending this type of session again. Don’t get me wrong, I don’t want to sound ungrateful, and fair dues to the organisers for holding the event but if you’re going to advertise something as a “Deep Dive” or a “Bootcamp” then that has certain connotations that there would actually be some Advanced Hands-on learning.

Instead the day would barely have qualified as a Level 100 introduction to 2 or 3 Windows Azure technologies interspersed with Sales Pitches, Student Demo’s of their project work and filler talks relating to cloud computing in general. Probably most disappointingly we didn’t actually take part in the RenderLab experiment which kinda torpedoed the “Global” aspect of the day as well. You can see the agenda below. I’ve highlighted the practical aspects in Red.

Time Topic
0930 Welcome Dr Pramod – Pathak, Dean, School of Computing, NCI
0935 Schedule for the day  – Vikas Sahni, Lecturer, School of Computing,NCI
0940 How ISIN can help – Dave Feenan, Manager, ISIN
0945 Microsoft’s Best Practice in Data Centre Design – Mark O’Neill, Data Center Evangelist, Microsoft
1000 Virtual Machines – Demo and Lab 1 - Vikas Sahni, Lecturer, School of Computing, NCI
1100 Careers in the Cloud – Dr Horacio Gonzalez-Velez, Head, Cloud Competency Center, School of Computing, NCI
1110 Graduates available today - Robert Ward, Head of Marketing, NCI
1120 Break
1135 Web Sites – Demo and Lab 2 – Vikas Sahni, Lecturer, School of Computing, NCI
1235 Building the Trusted Cloud – Terry Landers, Regional Standards Officer for Western Europe, Microsoft
1300 Lunch
1400 Tools for Cloud Development – Colum Horgan, InverCloud
1410 Windows Azure Mobile Services – Overview and Showcase –  Vikas Sahni, Lecturer, School of Computing, NCI and Students of NCI
1440 Developing PaaS applications – Demo – Michael Bradford, Lecturer, School of Computing, NCI
1530 Break
1545 Windows Azure – The Big Picture – Vikas Sahni, Lecturer, School of Computing, NCI
1645 Q&A

Alas even the practical aspects of the day were extremely basic and the kinda of thing that most people in the room had done/could do in their own spare time.

  • During the Virtual Machines Lab, we spun up a Virtual Machine from the Windows Azure Gallery and remote desktop connected into it.
  • During the Websites Lab, we deployed a WordPress install… unless you were feeling brave enough to do something else. To be fair I hadn’t done a hands on GitHub Deploy of the code so that was interesting.
  • During the PaaS Application Demo… well it was supposed to be a Hello World web/worker role deployment but god love the poor chap he was out of his depth with Visual Studio and had a few technical hiccups and it was just a bad demo. Upshot was we ran out of time before there was an opportunity for any hands on time in the room.

At 15:30 we left… I didn’t have another lecture in me, although at least we’d had the common courtesy to stay that long. Half the room didn’t come back after lunch.

The takeaways; I know that alot of time and effort goes into these events, and particularly when they are free, that time and effort is greatly appreciated. But you need to make sure you get your audience right. If you advertise Advanced and deliver basic, people will be disappointed. That was clear from the mass exodus that occured during the day… I’m kinda curious to know if there was anyone around for the Q&A at all. I’ll be sure as heck checking the agenda on these type of events before committing my time to them in future. We aren’t currently using Windows Azure in our company yet, and embarrassingly I had been promoting it internally and had convinced several of my colleagues to give up their Saturday for it.

~Eoin C

cambo » Could not load type ‘System.Runtime.CompilerServices. ExtensionAttribute’ from assembly mscorlib when using ILMerge

Wednesday, March 6th, 2013
Works On My Machine

Works On My Machine

I ran into a pretty horrible problem with ILMerge this week when attempting to build and deploy a windows service I’d been working on. While the merged executable & subsequently created MSI worked fine on my own machine, it gave the following rather nasty problem when run on a colleagues machine.

Error!

Could not load type ‘System.Runtime.CompilerServices.ExtensionAttribute’ from assembly mscorlib

It turns out that between .NET 4.0 & .NET 4.5; this attribute was moved from System.Core.dll to mscorlib.dll. While that sounds like a rather nasty breaking change in a framework version that is supposed to be 100% compatible, a [TypeForwardedTo] attribute is supposed to make this difference unobservable.

Unfortunately things breakwhen ILMerge is used to merge several assemblies into one. When I merge my .NET 4.0 app, with some other assemblies on the machine with .NET 4.5 installed, it sets the targetplatform for ILMerge to .NET 4.0. This in turn looks into C:\windows\Microsoft.NET\Framework\v4.0.30319 to find the relevant DLLs. But since .NET 4.5 is an in place upgrade, these have all been updated with their .NET 4.5 counter parts.

Breaking Changes

“Every well intended change has at least one failure mode that nobody thought of”

You need to specific that ILMerge should use the older .NET 4.0 reference assemblies which are still available in C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0. (or program files x86) if your on a 64-bit box). There’s more info on the stackoverflow question where I finally found a solution and in a linked blog post by Matt Wrock.

http://stackoverflow.com/questions/13748055/could-not-load-type-system-runtime-compilerservices-extensionattribute-from-a

and

http://www.mattwrock.com/post/2012/02/29/What-you-should-know-about-running-ILMerge-on-Net-45-Beta-assemblies-targeting-Net-40.aspx

To override this behavior you need to specify this target platform directory as part of your ILMerge command. e.g.

"C:\Path\To\ILMerge.exe"
    /out:"$(TargetDir)OutputExecutable.exe"
    /target:exe
    /targetplatform:"v4,C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"
      "$(TargetDir)InputExecutable.exe"
      "$(TargetDir)A.dll"
      "$(TargetDir)B.dll"
I had previously been using the ILMerge.MSBuild.Tasks tool from nuget but unfortunately, this library doesn’t currently support specifying the TargetPlatform. There’s an unactioned open item on their issue tracker in google code.
~EoinC

cambo » Automatically update the AssemblyFileVersion attribute of a .NET Assembly

Friday, January 25th, 2013
Automatic AssemblyFileVersion Updates

Automatic AssemblyFileVersion Updates

There is support in .NET for automatically incrementing the AssemblyVersion of a project by using the “.*” notation. e.g.
[assembly: AssemblyVersion("0.1.*")]

Unfortunately the same functionality isn’t available for the AssemblyFileVersion. Often times, I don’t want to bump the AssemblyVersion of an assembly as it will effect the strong name signature of the assembly, and perhaps the changes (a bug fix) isn’t significant enough to warrant it. However I do want to automatically increment the file version, so that in a deployed environment, I can right click the file and establish when the file was built & released.

Important!

Enter the Update-AssemblyFileVersion.ps1 file.

This powershell script, (heavily borrowed from David J Wise’s article), runs as a pre-build command on a .NET Project. Simply point the command at an assembly info file, (or GlobalAssemblyInfo.cs if you’re following my suggested versioning tactics)  and ta-da, automatically updating AssemblyFileVersions.

The Build component of the version number will be set using the following formula based on a daycount since the year 2000.

# Build = (201X-2000)*366 + (1==>366)
#
    $build = [int32](((get-date).Year-2000)*366)+(Get-Date).DayOfYear
 

The Revision component of the version number will be using the following formula based on seconds in the current day.

# Revision = (1==>86400)/2 # .net standard
#
    $revision = [int32](((get-date)-(Get-Date).Date).TotalSeconds / 2)
 

The Major & Minor components are not set to update although they could be. Simply add the following command to your Pre-Build event and you’re all set.

%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe 
    -File "C:\Path\To\Update-AssemblyFileVersion.ps1"  
    -assemblyInfoFilePath "$(SolutionDir)\Project\Properties\AssemblyInfo.cs"

~Eoin C

cambo » Adding Custom Message Headers to a WCF Service using Inspectors & Behaviors

Friday, December 14th, 2012
WCF Header Man

He has a WCF Header… Get it !

Often, you’ll need to pass some piece of information on some or all of your  WCF Service operations. For my team, we had recently exposed some functionality in an old WCF Endpoint via a Web Front End and wanted to log some auditing information on each and every Service Call. Obviously modifying every single method signature to accept the new parameters would be a pretty significant breaking change to all the consumers so instead we looked at passing this information as a Custom WCF Message Header. WCF exposes a number of interfaces which you can leverage to inspect & modify messages  on the fly and to add customer behaviors to service endpoints. In the following demo, we’ll go through the process of building a Custom Header for our WCF Service & subsequently passing that information from the Consumer Client back to the service. In our contrived example I’ll be attempting to pass 3 pieces of information to the WCF Service as part off every message call.

  • The username of the currently logged in web front-end user
  • Since our website is deployed across multiple nodes, the id of the web node
  • The “Special Session Guid” of the current users Session

Important!

The completed solution can be found on GitHub at https://github.com/eoincampbell/wcf-custom-headers-demo 
This scenario could apply to a number of other real world situations. Perhaps the service is secured and called using a single WS Security Account, but we need to log the user who’s session, the service call originated from on every service call. Or perhaps you’re exposing your service to the public and as well as providing a username & password to authenticate, the caller also needs to provide some sort of “Subscription Account Number” in addition to their Credentials. Any of these scenarios are candidates for adding a custom header to a WCF Service.

The Quick & Dirty Solution

Of course I could just edit method signatures of each service call to accept this additional information as additional parameters but this causes a number of other problems. This might be feasible for a small in-house service, or dummy application but it causes a number of issues in reality.
  • I need to add additional parameters to every service call which isn’t a particularly elegant solution
  • If I need to add more information in the future, I must edit every service call signature which at worst is a breaking change for every client and at best, a significant amount of work & re-factoring.
  • Depending on the scenario, I’m potentially intermingling Business Logic with Authentication/Authorization or some other sort of Service Wide Validation logic which is going to increase the complexity of any future re-factoring.

Operation Context & Custom Message Headers

A better solution would be to “tag” each service call with some sort of header information. In this way, we could piggy-back our additional data along without interfering with the individual method signatures of each service call. Thankfully WCF includes built-in support for MessageHeaders. The services OperationContext includes Incoming & Outgoing Message Header collections.

//Service Contract
    [ServiceContract]
    public interface ISimpleCustomHeaderService
    {
        [OperationContract]
        void DoWork();
    }

//Client Code
    using (var client = new SimpleCustomHeaderServiceClient())
    using (var scope = new OperationContextScope(client.InnerChannel))
    {
        var webUser = new MessageHeader("joe.bloggs");
        var webUserHeader = webUser.GetUntypedHeader("web-user", "ns");
        OperationContext.Current.OutgoingMessageHeaders.Add(webUserHeader);

        client.DoWork();
    }

For now I’ve created a very simple Service Contract which has a single void method on it called DoWork(). Adding a custom header to this service call is relatively trivial. First we instantiate a new instance of our WCF Client Proxy. We also nee to create an OperationContextScope using the WCF client channel. Since the OperationContext is accessed, via the static Current property, instantiating this scoping object, stores the current context & the OperationContext of the current Clients IContextChannel becomes that returned by the Current Property. This allows us to modify the OutgoingMessageHeaders collection of the clients channel. Once disposed the state of the original Current OperationContext is restored. MessageHeaders are passed as untyped data as they travel on the wire. In the example above I’ve created a strongly typed .NET object. That is then converted to an untyped header; keyed by name & namespace for transmission in the OutgoingMessageHeaders Collection. If we observe the data that travels across the wire using fiddler, we can see our Custom Header Data has been appended to the soap header section of the message.

Fiddler WCF Headers

Fiddler WCF Headers

Finally, these Header values can be retrieved from the IncomingMessageHeader Collection as part of the service call processing. Since we’re already in the scope the Current OperationContext, we can just directly access that context’s header collection to read our headers. I’ve added a simple generic helper method to test to see if the Header can first be found and if so, will be returned.

public class SimpleCustomHeaderService : ISimpleCustomHeaderService
{
    public string DoWork()
    {
        //Do Work
        //...

        //Capture Headers
        var userName = GetHeader("web-user", "ns");
        var webNodeId = GetHeader("web-node-id", "ns");
        var webSessionId = GetHeader("web-session-id", "ns");

        Debug.WriteLine("User: {0} / Node: {1} / Session: {2}", userName, webNodeId, webSessionId);
        var s = string.Format("HeaderInfo: {0}, {1}, {2}",
            userName,
            webNodeId,
            webSessionId);

        return s;
    }

    private static T GetHeader(string name, string ns)
    {
        return OperationContext.Current.IncomingMessageHeaders.FindHeader(name, ns) > -1
            ? OperationContext.Current.IncomingMessageHeaders.GetHeader(name, ns)
            : default(T);
    }
}

Leveraging Client & Dispatch Message Inspectors

The above solution comes with some pros and cons. On the plus side headers can be added in an adhoc manner with little friction to existing code. On the downside, it’s not really ideal from a code maintenance/organization point of view. Header Data is relatively unstructured and disparate. We also end up with a lot of touch-points. Adding headers requires creating an OperationContextScope in close proximity to every service call… similarly, accessing the resultant header values must be done in the Service Methods… Imagine our WCF Service had 100 service methods, and all we wanted to do was send a single additional header to be logged on the server. That results in 100′s of lines of additional code.

A better solution would be to use the built in message inspector interfaces in WCF. Message Inspectors provide you with a way to plug directly into the WCF Communications Pipeline on both the client or server side of the communication Channel. The IDispatcherMessageInspector allows us to affect messages either just after the request has arrives on the server (AfterReceiveRequest) or just before the response leaves the server (BeforeSendReply) The IClientMessageInspector allows us to affect messages either just before the request leaves the client  (BeforeSendRequest) or just after the response is received by the client (AfterReceiveReply)


public class CustomInspectorBehavior : IDispatchMessageInspector, IClientMessageInspector
{
    #region IDispatchMessageInspector

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    { ... }
    #endregion

    #region IClientMessageInspector
    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    { ... }
    #endregion
}

Injecting ourselves into the message pipeline like this serves a number of advantages, We now have the opportunity to add our messages to the outbound client request in a single place. We also have a single touch point for capturing the request on the server side. If this was a licence-code validation check, this would save us from peppering every single service call with the validation check code.

In the following sections we’ll look at creating a custom data header object, creating a message inspector implementation to manage injecting and extracting this data from our WCF Service, creating Client & Service Behaviors to attach our Message Inspectors and creating a behavior extension to allow these behaviors to be applied to our service through configuration.

Solution Organisation

Since both our Web Application (which will host the Web Services) and the Console Application will have some common dependencies, I’ve split out the majority of the code in these next sections and stored them in Common Class Library folder which both Applications can then reference.

Solution Organisation

Solution Organisation

Custom Header Data Contract

The first thing I’ll create is a simple data contract object to represent our custom header information. This POCO Data Contract provides a simple way for us to encapsulate our header information into a single payload which will be transmitted with our Service Calls.

    [DataContract]
    public class CustomHeader
    {
        [DataMember]
        public string WebUserId { get; set; }
        [DataMember]
        public int WebNodeId { get; set; }
        [DataMember]
        public Guid WebSessionId { get; set; }
    }

Message Inspectors

Next I create our Message Inspectors. The two interfaces that are required are the System.ServiceModel.Dispatcher.IDispatchMessageInspector (which hooks into our pipeline on the service side) and the  System.ServiceModel.Dispatcher.IClientMessageInspector (which hooks into our pipeline on the consumer side). Within these two interfaces the two methods I’m most interested in are the IClientMessageInspector.BeforeSendRequest which allows me to modify the outgoing header collection on the client and the IDispatchMessageInspector.AfterReceiveRequest which allows me to retrieve the data on the service side.

    #region IDispatchMessageInspector
    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        //Retrieve Inbound Object from Request
        var header = request.Headers.GetHeader("custom-header", "s");
        if (header != null)
        {
            OperationContext.Current.IncomingMessageProperties.Add("CustomHeader", header);
        }
        return null;
    }
    #endregion

    #region IClientMessageInspector
    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        //Instantiate new HeaderObject with values from ClientContext;
        var dataToSend = new CustomHeader
            {
                WebNodeId = ClientCustomHeaderContext.HeaderInformation.WebNodeId,
                WebSessionId = ClientCustomHeaderContext.HeaderInformation.WebSessionId,
                WebUserId = ClientCustomHeaderContext.HeaderInformation.WebUserId
            };

        var typedHeader = new MessageHeader(dataToSend);
        var untypedHeader = typedHeader.GetUntypedHeader("custom-header", "s");

        request.Headers.Add(untypedHeader);
        return null;
    }
    #endregion

I’ll also need to create a simple static Client Context class which will provide the conduit for the Consumer Application to set header values to be picked up inside the message inspector methods.

    public static class ClientCustomHeaderContext
    {
        public static CustomHeader HeaderInformation;

        static ClientCustomHeaderContext()
        {
            HeaderInformation = new CustomHeader();
        }
    }

WCF Custom Behaviors

WCF Service Behaviors define how the endpoint (the actual service instance) interacts with its clients. Attributes like security, concurrency, caching, logging, and attached message inspectors – those are all part of the behavior. We’re going to implement a new custom behavior for both the Service side and the Client side of this interaction. Since these are still just interface implementations, there’s no need to create a new class to implement them. We can add this functionality to the same class which contains our Message Inspector functionality. Of course if you wanted to be a purist about it, there’s nothing to stop you implementing the two message inspectors and two service behaviors in four completely separate classes.

The two behavior contracts I’m interested in here are the System.ServiceModel.Description.IEndpointBehavior, which is responsible for the client side behavior and the System.ServiceModel.Description.IServiceBehavior which is responsible for the service side behavior. Implementing these interfaces allows me to add an instance of the Message Inspectors to the service.

#region IEndpointBehavior
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
    var channelDispatcher = endpointDispatcher.ChannelDispatcher;
    if (channelDispatcher == null) return;
    foreach (var ed in channelDispatcher.Endpoints)
    {
        var inspector = new CustomInspectorBehavior();
        ed.DispatchRuntime.MessageInspectors.Add(inspector);
    }
}

public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
    var inspector = new CustomInspectorBehavior();
    clientRuntime.MessageInspectors.Add(inspector);
}
#endregion

#region IServiceBehaviour
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
    foreach (ChannelDispatcher cDispatcher in serviceHostBase.ChannelDispatchers)
    {
        foreach (var eDispatcher in cDispatcher.Endpoints)
        {
            eDispatcher.DispatchRuntime.MessageInspectors.Add(new CustomInspectorBehavior());
        }
    }
}

#endregion

Adding the Custom Behavior to a WCF Service

Behaviors can be applied to services using a special Service Behavior attribute which decorates the ServiceContract. The last step is to extend the Attribute class in our CustomHeaderInspectorBehavior class and then to decorate each of services with that attribute.

[AttributeUsage(AttributeTargets.Class)]
public class CustomInspectorBehavior : Attribute, ... { ... }

[CustomInspectorBehavior]
public class ComplexCustomHeaderService : IComplexCustomHeaderService { ... }

Configuring a WCF Client to use a specific behavior

On the client side, I need to do a tiny bit more work. I can manually configure the Behavior on the WcfClientProxy every time I instantiate it but this is extra bloat and eventually I’ll forget to set it somewhere and lose my behavior functionality.

using(var client = new ComplexCustomHeaderServiceClient()) {
    client.ChannelFactory.Endpoint.Behaviors.Add(new CustomHeaderInspectorBehavior());
}

Instead I’d prefer to be able to set this once in configuration and never have to worry about it again. I can achieve this by using a BehaviorExtension Element as follows and adding it to my application configuraiton file.

public class CustomInspectorBehaviorExtension : BehaviorExtensionElement
{
    protected override object CreateBehavior()
    {
        return new CustomInspectorBehavior();
    }
    public override Type BehaviorType
    {
        get { return typeof (CustomInspectorBehavior); }
    }
}

And below is the equivalent configuration file.

    <system.serviceModel>
      <behaviors>
        <endpointBehaviors>
          <behavior name="CustomInspectorBehavior">
            <CustomInspectorBehavior />
          </behavior>
        </endpointBehaviors>
      </behaviors>
      <extensions>
        <behaviorExtensions>
          <add name="CustomInspectorBehavior"
               type="WCFCustomHeaderDemo.Lib.Extensions.CustomInspectorBehaviorExtension,WCFCustomHeaderDemo.Lib" />
        </behaviorExtensions>
      </extensions>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_ISimpleCustomHeaderService" />
                <binding name="BasicHttpBinding_IComplexCustomHeaderService" />
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost/TestService/ComplexCustomHeaderService.svc"
                behaviorConfiguration="CustomInspectorBehavior"
				binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_IComplexCustomHeaderService"
                contract="ComplexCustomHeaderService.IComplexCustomHeaderService"
                name="BasicHttpBinding_IComplexCustomHeaderService" />
        </client>
    </system.serviceModel>

Calling our Client

Finally, we can call our client and test to see if our Server side application can see the headers being submitted and echo them back.

using(var client = new ComplexCustomHeaderServiceClient())
{
    ClientCustomHeaderContext.HeaderInformation.WebNodeId = 465;
    ClientCustomHeaderContext.HeaderInformation.WebSessionId = Guid.NewGuid();
    ClientCustomHeaderContext.HeaderInformation.WebUserId = "joe.bloggs";
    System.Console.WriteLine(client.DoWork());
}
Wcf Header Demo Result

WCF Header Demo Result

Excellent.

~Eoin C

cambo » Unexpected Variable Behaviour in DOS Batch and Delayed Expansion

Tuesday, December 4th, 2012

What would you expect the following piece of Code to print. if the directory ‘A’ doesn’t exist

@ECHO OFF
IF '1'=='1' (
        CD a
        ECHO %ERRORLEVEL%
)

CD a
ECHO %ERRORLEVEL%

Not very intuitive right?

This is because the DOS batch processor treats the whole if statement as one command, expanding the variables only once, before it executes the conditional block. So you end up with %ERRORLEVEL% being expanded to its value, which is 0, before you start the block, You can get around this by enabling Delayed Expansion. As the name suggests this forces the the Batch Processor to only expand variables once required to do so in the middle of execution.
To enable this behavior you need to do 2 things.
  1. SET ENABLEDELAYEDEXPANSION at the top of your script.
  2. Replace % delimited variables with an Exclamation. i.e. %ERRORLEVEL% becomes !ERRORLEVEL!

Now our script looks like this, and behaves as expected.

Working Script

@ECHO OFF
REM Enable Delayed Expansion
setlocal enabledelayedexpansion
IF '1'=='1' (
        CD a
        REM Use Exclamations instead of percentages
        ECHO !ERRORLEVEL!
)

CD a
ECHO %ERRORLEVEL%
For when powershell just isn’t retro enough ;-)
~Eoin C

cambo » .NET Windows Services – Tips & Tricks

Friday, November 23rd, 2012
Windows Services

Windows Services

If you’ve ever worked with windows services, you’ll know that they’re a very powerful tool to have in your background processing arsenal. Unfortunately they can be also quite a pain to work with in developer land. Recently we’ve been spinning up a lot of new windows service projects in work as part of a Business Intelligence Data Processing Project. I thought this would be a good time to brain dump some of the tips & tricks I’ve come across over the past few years for dealing with .Net Windows Services.

I’ll look at the basics for getting a service up and going, using the built project installer & Install Util. Then I’ll take a look at easier ways of running the service inside the IDE, and how to run the service in user interactive mode.

Finally I’ll look at ways to make the service self-installing without having to rely upon the InstallUtil.exe as well as gaining access to configuration settings during the installation process.

Important!

The completed solution can be found on GitHub at https://github.com/eoincampbell/demo-windows-service 

Windows Services Basics

I’m going to build a very trivial Windows Service. The service will start a timer, which will then log the current time every 100ms to a file in the same path  as the executable. It will also attempt to write to the console if there is one attached. A few notes. Don’t leave this running. It will devour your disk space. You’ll also need to make sure that the account you install the service as has permission to write to that path on the file system.

When I first create a new windows service, there are a number of setup tasks I perform to keep the service organised. YMMV with these.

  1. If I’m only adding a single Service.cs in this project, then I’ll rename the service class to the same name as the project. This will make the Service Name match with the Executable Name which I’ve found saves confusion. In my example the Project, Service Class, Namespace & Executable are all DemoWindowsService.
  2. Open the Service.Designer.cs file and ensure that the property this.ServiceName  also matches this naming convention
  3. Add an installer to your service by Right-Clicking the design canvas of the service and choosing “Add Installer” (See Image Below)
  4. Once you’ve added your ProjectInstaller open that file also and ensure that the property this.serviceInstaller1.ServiceName also matches this naming convention
  5. We’ll also  specify a Description on the serviceInstaller1 object to give our service a meaningful description when it appears in services.msc listing
Add Installer to Windows Service

Add Installer to Windows Service

After building your windows service application, you can then use InstallUtil.exe from the command line to install or uninstall your applicaiton.

InstallUtil.exe DemoWindowsService.exe
net start DemoWindowsService
net stop DemoWindowsService
InstallUtil.exe /u DemoWindowsService.exe

Debugging Windows Services

Relying on InstallUtil is all well and good but it doesn’t lend itself to an easy developer debugging experience. If you attempt to press F5 in order to start your Windows Service from within the IDE, you’ll be presented with the following rather unhelpful popup.

Windows Service Start Failure

Windows Service Start Failure

This is because the default code which is added to program.cs relies on launching the Service using the static ServiceBase.Run() method. This is the entry point for “the scum”. (The SCM, or Service Control Manager is the external program which controls launching the services). We can still debug our Application from here but it’s a little bit round about.

  1. Build the Service.
  2. install it using InstallUtil.exe
  3. NET START the service.
  4. Attach to that Process using the Debug menu in Visual Studio.
  5. Find a bug.
  6. Detachn & NET STOP the service.
  7. Uninstall, re-build, wash-rinse-repeat.

Using Debugger.Launch & Debugger.Break

Another option available to trigger debugging is to embed calls to the Debugger directly in your code. These calls could be surrounded by Conditional attributes to prevent Debug Launch statements leaking into release versions of code.

        protected override void OnStart(string[] args)
        {
            DebugLaunch();
            MainTimer.Enabled = true;
        }

        private void MainTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            DebugBreak();
            var path = Assembly.GetExecutingAssembly().Location;
            var dir = Path.GetDirectoryName(path);
            var text = string.Format("Tick: {0:yyyy-MM-dd HH:mm:ss.fff}{1}", DateTime.Now, Environment.NewLine);
            File.AppendAllText(dir + "\\output.log", text);
            Console.Write(text);
        }

        [Conditional("DEBUG")]
        public void DebugLaunch()
        {
            Debugger.Launch();
        }

        [Conditional("DEBUG")]
        public void DebugBreak()
        {
            Debugger.Break();
        }

Notice

Unfortunately it would appear that this doesn’t work in Windows 8. Microsoft have slowly been phasing out the ability of Windows Services to run in Interactive mode and interact with the desktop. Since the Debugger.Launch statement needs to load a GUI for the user to interact with, the Windows Service would appear to hang on this statement.

Launch Windows Service with F5

What would be very helpful is if we could just launch our application from within the Debugger as needed. Well it turns out we can by conditionally launching the service using the ServiceBase.Run() method or by just launching it as a regular instantiated class.

    static class Program
    {
        static void Main(string [] args)
        {
            var service = new DemoService();

            if (Debugger.IsAttached)
            {
                service.InteractiveStart(args);
                Console.WriteLine("Press any key to stop!");
                Console.Read();
                service.InteractiveStop();
            }
            else
            {
                ServiceBase.Run(service);
            }
        }
    }

Now if I press F5, the application entry point will check if the application is in Debug Mode (Debugger Attached) and if so will simply launch the application as a console application. In order to get this to work I’ve had to make a few small changes.

  1. Go to the Project Properties screen & change the application type from “Windows Application” to “Console Application”
  2. Add two public wrapper methods to the service for InteractiveStart & InteractiveStop since the OnStart & OnStop methods are protected
  3. Add a Console.Read() between calling Start and Stop to prevent the Service from immediately shutting down.

Command Line Switch Driven Behaviour

Relying on the Debugger being attached is all well and good but what if I just want to run my application optionally in stand-alone mode. We could extend the runtime condition from the last code snippet to also test whether the application is running in InteractiveMode. But I think I’d prefer a little more power so I’ve added a command line switch to create this behavior. Now I have the option to Install from the command line using InstallUtil, run from the command line interactively, and I can set a startup switch argument in Project Properties -> Debug -> Start Options to run the application in Console mode from the IDE.

    static class Program
    {
        static void Main(string [] args)
        {
            var service = new DemoService();

            if (args.Any() && args[0].ToLowerInvariant() == "--console")
            {
                RunInteractive(service,args);
            }
            else
            {
                ServiceBase.Run(service);
            }
        }

        private static void RunInteractive(DemoService service, string [] args)
        {
            service.InteractiveStart(args);
            Console.WriteLine("Press any key to stop!");
            Console.Read();
            service.InteractiveStop();
        }
    }

Self Managed Installation

My service is becoming more self-sufficient and useful but I still have this external dependency on InstallUtil. Wouldn’t it be great if I could just drop my application on a server and have it install itself. Enter the ManagedInstallerClass

    static void Main(string [] args)
    {
        var service = new DemoService();
        var arguments = string.Concat(args);
        switch(arguments)
        {
            case "--console":
                RunInteractive(service,args);
                break;
            case "--install":
                ManagedInstallerClass.InstallHelper(new [] { Assembly.GetExecutingAssembly().Location });
                break;
            case "--uninstall":
                ManagedInstallerClass.InstallHelper(new [] { "/u", Assembly.GetExecutingAssembly().Location });
                break;
            default:
                ServiceBase.Run(service);
                break;
        }
    }

If you want to simplify matters even further, you can modify your ProjectInstaller.Designer.cs file and specify that the Service should be of type AutomaticStart

    // 
    // serviceInstaller1
    // 
    this.serviceInstaller1.ServiceName = "DemoWindowsService";
    this.serviceInstaller1.StartType = ServiceStartMode.Automatic;

InstallUtil Install-Time Configuration

One final thing you might find useful is the ability to query values from your configuration file when using Intsall Util. The problem here is that the AppSettings collection during installation is not the collection in the service.config but the collection in the InstallUtil app.config. Have a read of the following link for getting access to your own config at install time (e.g. in order to install with Default Supplied UserName & Password).

http://trycatch.me/installutil-windows-services-projectinstallers-with-app-config-settings/

Future Proofing

One last piece of advice. If you’re building any sort of sizeable windows service/back-end processor, I would strongly suggest you NOT implement any logic in the service class itself. Typically I will create some sort of “Engine” class that encapsulates all my functionality with 3 external accessible members.

  • A public constructor called from Service Constructor
  • A public Start or Init method, called from OnStart()
  • A public Stop or End method, called from OnStop()

The reason for this is simply to prevent lock-in & tight coupling to the windows service treating it only as a helpful host. This allows me to easily spin up my Engine class in a standalone Console Application, inside a web apps Global.asax or in an Azure Worker role with a minimum of refactoring in order to extract the functionality.

~Eoin C