Friday, August 29, 2014

Revisiting REST Proxy

In June I published a blog post about creating a class for easily consuming data from RESTful web services (http://geek-goddess-bonnie.blogspot.com/2014/06/proxy-class-for-consuming-restful.html). Since then, I've had the need to use credentials to access a REST service, so my class has had to change a bit. Not much, but I thought it was enough to warrant a new blog post, so here it is. Basically all I did was add UserName and Password properties, plus another constructor like this:

public ProxyBaseREST(string baseAddress, string userName, string password) : this(baseAddress)
{
    this.UserName = userName;
    this.Password = password;
}

And the GetJSON() method was modified slightly to add the credentials to the WebClient:

WebClient WC = new WebClient();
if (!string.IsNullOrEmpty(this.UserName) && !string.IsNullOrEmpty(this.Password))
    WC.Credentials = new NetworkCredential(this.UserName, this.Password);

And the rest is the same as in my earlier post. Pretty easy, eh?

Thursday, August 14, 2014

FileSystemWatcher Improvements

A few months ago, I needed the capability to receive files, process them, and send the processed data to another part of the application. We send information around to various parts of our application by a queuing mechanism. This could be implemented with MSMQ (which is how we did it in version 1 of our app) or by mimicking a queue in database tables (version 2). The queuing mechanism isn't important to this post though, so I won't go into any detail about that.

For my first cut of a FileListener class, I simply used the System.IO.FileSystemWatcher class directly in my code. The code handles the Created event and sends only the filename of the file through to the queuing process in that event handler. The queuing process then pops the filename off the queue, opens and reads the file (simply by calling the File.ReadAllText() method), munges the data from the file and sends the data off to another queue processor. Here's a working example of that, with the queuing process not fleshed out at all, but supplemented by Console.WriteLine()'s so you can follow the progress:

public class MyFileListener
{
    protected FileSystemWatcher Watcher = null;
    protected string FilePath = @"F:\CompletePathToDirectory";
    protected bool ErrorProcessingFileName = true;


    // simulating queuing mechanism with a fake QueuingClass
    QueuingClass QueueManager;


    public MyFileListener()
    {
        this.QueueManager = new QueuingClass();
        this.Watcher = new FileSystemWatcher();
        this.Watcher .Path = this. FilePath;
        this.Watcher .EnableRaisingEvents = true;
        this.Watcher .Created += new FileSystemEventHandler(Watcher_Created);
        this.Watcher .Error += new ErrorEventHandler(Watcher_Error);
        Console.WriteLine( "Waiting for files to be deposited in {0}" , this.FilePath);
    }
    private void Watcher_Created(object sender, FileSystemEventArgs e)
    {
        using (TransactionScope scope = new TransactionScope(TransactionScopeOption .Required, new TransactionOptions() { IsolationLevel = IsolationLevel .ReadCommitted }))
        {
            try
            {
                this.CreateAndSendMessage(e .FullPath);
                scope .Complete();
            }
            catch (Exception ex)
            {
                this.ErrorProcessingFileName = true ;
            }
        }
    }
    private void Watcher_Error(object sender, ErrorEventArgs e)
    {
        this.ErrorProcessingFileName = true ;
    }


    private void CreateAndSendMessage(string filename)
    {
        Console.WriteLine( "Sending FileName {0} To Queue" , filename);
        // put code here to send the file to your queuing mechanism
        // for demo purposes, I'm going to simulate sending to a queue
        this.QueueManager .SendMessageToQueue(filename);
    }
}
public class QueuingClass
{
    private string Message;


    public void SendMessageToQueue(string message)
    {
        this.Message = message;
        this.PopMessageOffQueue();
    }
    protected void PopMessageOffQueue()
    {
        try
        {
            string filename = this. Message;
            if (File .Exists(filename))
            {
                string fileData = File. ReadAllText(filename);


                this.ProcessFileDataAndSend(fileData);


                if (File .Exists(filename))
                    File.Delete(filename);
            }
        }
        catch (FileNotFoundException ex)
        {
            // we can go ahead and eat this exception ... it means the file was processed and/or deleted in another thread
            Console.WriteLine( "File Already Removed: " + ex.FileName);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex .Message);
        }
    }
    protected void ProcessFileDataAndSend(string FileData)
    {
        Console.WriteLine( "Here is the data retrieved from file {0}:\r\n{1}" , this.Message, FileData);
        // This is where you'd process the data from the file
        // and send the processed data off to another queue
        // which I won't bother simulating here.
    }
}

All you have to do to use this MyFileListener class is create an instance of it. Then drop a file (or multiple files) into the directory you've specified and watch the fun. I've just used a Console application to run this ... you can do it however you want to, obviously.

private void TestFileListener()
{
    MyFileListener Listener = new MyFileListener();
}

But, there's a problem with using the Created event when you're attempting to process a large file. The Created event is fired when the file first starts to get copied to the directory you're listening to, not when the file has finished being copied. By attempting to read the file as soon as the Created event is raised, problems arose with blocking file access (the system sending the files couldn't complete the sending of the files, because presumably my trying to read it at the same caused file access issues). I even had the built-in delay of the queuing process (since the file isn't actually being read until it is "popped" off the queue).This ended up working OK for small files (there was enough of a delay), but not larger files. So, I needed to come up with a better idea.

So, I created my own class, sub-classed from FileSystemWatcher and used that instead. The difference being that I create a new event that I call FileReady and fire it when I know the file  copy has completed. How do I know when that happens? In a try/catch, I try to do a File.Open with FileShare set to None. If I can't open the file, then I know it's not done being copied yet and I keep trying until I can open it (at which point I fire the FileReady event). Here's the code for this new class:

public class MyFileWatcher : FileSystemWatcher
{
    public event FileSystemEventHandler FileReady;


    public MyFileWatcher()
    {
        this.Created += new FileSystemEventHandler(Watcher_Created);
    }
    private void Watcher_Created(object sender, FileSystemEventArgs e)
    {
        System.Threading.ThreadPool.QueueUserWorkItem((n) => { WaitForFileReady(e); });
    }
    private void WaitForFileReady(FileSystemEventArgs e)
    {
        while (true)
        {
            try
            {
                using (FileStream fs = File.Open(e.FullPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
                {
                    break;
                }
            }
            catch (FileNotFoundException ex)
            {
                return;
            }
            catch (Exception ex)
            {
                System.Threading.Thread.Sleep(100);
            }
        }
        OnFileReady(e);
    }
    protected virtual void OnFileReady(FileSystemEventArgs e)
    {
        if (this.EnableRaisingEvents && FileReady != null)
            FileReady(this, e);
    }
}

In order to utilize this in the MyFileListener class, simply replace the FileSystemWatcher with the MyFileWatcher and handle the FileReady event instead of the Created event (the code inside the event handler will be exactly the same). Here are the changes to make:

// the declaration
protected MyFileWatcher Watcher = null;
// the MyFileListener constructor
this.Watcher = new MyFileWatcher();
this.Watcher.FileReady += new FileSystemEventHandler(Watcher_FileReady);
// the new event handler name
private void Watcher_FileReady(object sender, FileSystemEventArgs e)

I hope this post helps you successfully implement your next application's needs … Happy Coding!

Thursday, July 31, 2014

Visual Studio 2013, Hyper-V And VMWare

We are big into doing all our development work on VMs and have been using VMWare for almost 5 years now. We've got a fantastic VMWare ESXi server with loads of RAM, CPUs, disk space and a lot of VMs. It's a great setup.

In January, I got a new Dell Venue 11 Pro with Windows 8.1. The thing is a bit buggy, but Dell is slowly taking care of some of those issues ... but I like having a nice small tablet for portability reasons. The resolution could be better, not so damn small for my aging eyes ... but that's why I use two external monitors!!

A few months later, I thought that now that I have a Win 8 machine, I should go ahead and load up Visual Studio 2013. I was not going to be doing any actual development on my Venue, but it's always good to have VS available locally (not on a remote VM) to be able to look at or test something quickly, while I'm away from my network (and my VMs are inaccessible). While in the process of doing that, I figured I'd go ahead and install everything. I thought that perhaps I might want to take a look at Windows Phone apps and see what that was all about ... you never know when you might come up with the next killer phone app (although I have never written any phone apps and, in fact, I do not as yet even own a smart phone). Unfortunately, when you install the stuff for Windows Phone, it also installs Hyper-V and I don't think that it asked me or warned me about that ... it just went and did it. Kinda pissed me off a little bit.

Why is that a problem, you might ask? Well, it didn't interfere with my development work at all ... all my development VMs are accessed via RDP. However, I did have a few other things virtualized that weren't work related ... like my old desktop computer that was starting to have issues. My Quicken and TurboTax were on there and it was easy enough to create a VM. I didn't want to put these types of personal VMs on our work ESXi server, so I put it on a USB drive and then I didn't care if my old desktop died or not (in fact, I shut it down and have not started it up since). I have been doing my Quicken and TurboTax from the VM ever since. But ooops! Along comes Hyper-V and now I can't open my VM with VMWare Player anymore! Damn!

So, now what? A bunch of Googling commenced and I eventually found that I could disable Hyper-V easily enough. I ended up following the advice at this link : http://empiricalmusing.com/Lists/Posts/Post.aspx?ID=25

Basically, here are the steps:

  1. Open Hyper-V manager and "stop service" on the right panel,

  2. Then at an elevated command prompt, run the following command:

          bcdedit /set hypervisorlaunchtype off

This will disable Hyper-v at an elevated command prompt

To enable Hyper-v to use Hyper-V again, at an elevated command prompt, type:

bcdedit /set hypervisorlaunchtype auto

You'll probably have to reboot in order for changes to take effect.

Sunday, June 29, 2014

Proxy Class For Consuming RESTful Services

About 2 years ago, I wrote a blog post about using generics to create an easy-to-use WCF proxy class (click here: A Generic WCF Proxy Class).

A few months ago, I had the need to consume several RESTful web services that made use of JSON. Wanting to make is as easy to use as ProxyBase, the generic WCF proxy class that I posted 2 years ago, I decided to write another base class for RESTful web service access. I call it ProxyBaseREST.

There are several things you will need to add to your project references that aren't normally added when you create a new class library project (and also remember to put using statements for them at the top of your class). One is System.Net, because we'll need to make use of the WebClient, which lives in that namespace. Since we'll also be dealing with JSON, you need a JSON library. I've made use of Json.NET (the assembly is called NewtonSoft.Json.DLL), which is widely used. It's free open-source and you can download it here: https://json.codeplex.com/ And, two more, System.Xml and System.Xml.Linq, since we'll be converting JSON to either XNode or XmlNode.

So, here's the class I wrote:

public class ProxyBaseREST
{
    #region Declarations and Constructor

    protected string BaseAddress;
    protected string Parameters = "";

    public ProxyBaseREST(string baseAddress)
    {
        this.BaseAddress = baseAddress;
    }

    #endregion

    #region Methods

    protected string GetJSON()
    {
        try
        {
            WebClient WC = new WebClient();
            WC .Headers["Content-type" ] = "application/json";
            //string CallString = this.ParseParameters();

            Stream stream = WC.OpenRead( this.BaseAddress + this .Parameters);

            StreamReader reader = new StreamReader(stream);
            string json = reader.ReadToEnd();
            stream .Close();

            if (json == "[]")
                json = "" ;
            return json;
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error in Web Service call: {0}{1}" , this.BaseAddress, this.Parameters);
            Console.WriteLine(ex.Message);
            return "" ;
        }
    }
    protected string GetDeserializedJSON(string rootNode)
    {
        string json = this.GetJSON();
        string xml = "";
        try
        {
            xml = this .DeserializeAsXNode(json, rootNode);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error Deserializing JSON RootNode '{0}' in Web Service call: {1}{2}", rootNode, this.BaseAddress, this.Parameters);
            Console.WriteLine(ex.Message);
            xml = "" ;
        }

        return xml;
    }
    protected string DeserializeAsXNode(string json, string rootNode)
    {
        if (string.IsNullOrEmpty(json)== false)
        {
            XNode node = JsonConvert.DeserializeXNode(json, rootNode);
            return node.ToString();
        }
        else
            return "" ;
    }
    /// <summary>
    /// Used for mal-formed JSON that lacks a root node
    /// </summary>
    /// <param name="json"></param>
    /// <param name="rootNode"></param>
    /// <returns></returns>
    protected string GetDeserializedJSON(string json, string rootNode)
    {
        string xml = "";
        try
        {
            if (string.IsNullOrEmpty(json) == false)
            {
                string RootAndJson = "{\"" + rootNode + "\":" + json + "}";
                System .Xml.XmlNode myXmlNode = JsonConvert.DeserializeXmlNode(RootAndJson, rootNode);
                xml = myXmlNode.OuterXml;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error Deserializing JSON RootNode '{0}' in Web Service call: {1}{2}", rootNode, this.BaseAddress, this.Parameters);
            Console.WriteLine(ex.Message);
            xml = "" ;
        }

        return xml;
    }

    #endregion
}

You'll note that the ProxyBaseREST class makes use of a couple of JsonConvert static methods to convert the JSON format to an XML string. You can change this if you'd like to return XNode or XmlNode, but I prefer strings because I typically use XML to fill a DataSet, which is easily done with an XML string. You can obviously change the methods to return whatever kind of XML you would normally use in your applications.

Now all you have to do is create a sub-class of ProxyBaseREST, add the methods you need to call and you're done. Here's a sample Proxy:

public class MyProxy : ProxyBaseREST
{
    #region Declarations and Constructor

    // constructor
    public MyProxy(string baseAddress) : base(baseAddress)
    {
    }

    #endregion

    #region Methods

    public string GetDataNoParms()
    {
        this.Parameters = "GetData";
        string xml;

        // use one or the other of these two methods
        // comment out (or remove) the one you don't want, obviously

        // this returns a string that is formatted into XML
        xml = this.GetDeserializedJSON("root"); // this "root node" can be called anything

        // this returns a string in the JSON format, just as you've received it from the web service call
        xml = this.GetJSON();

        return xml;
    }
    public string GetDataWithParms(string CustomerName, int CustomerID, bool PreferredCustomer)
    {
        string parms = string.Format("CustomerName={0} CustomerID={1} PreferredCustomer={2}", CustomerName, CustomerID, PreferredCustomer);
        this.Parameters = "GetData?params=" + parms;
        string xml;

        // same two choices as above
        xml = this.GetDeserializedJSON("root");
        xml = this.GetJSON();

        // And here's another situation. You might have mal-formed JSON returned from the web service. 
        // This is fine for just returning the JSON, maybe. But, if you need to serialize it
        // to XML, you'll need to do something extra.
        // The ProxyBaseREST class has a method for that as well, use it in conjunction with the GetJSON() method:
        xml = this.GetDeserializedJSON(this.GetJSON(), "root"); // this "root node" can be called anything

        return xml;
    }

    #endregion
}

And then, you'd make web service calls like this:

public class TestingMyProxy
{
    #region Declarations

    // In real-life, you'd get the address from the appSettings in your config file.
    protected string WebServiceAddress = @"http://192.168.1.161:7777/"; 
    protected MyProxy myProxy;

    #endregion

    #region Constructor

    public TestingMyProxy()
    {
        this.myProxy = new MyProxy(this.WebServiceAddress);
    }

    #endregion

    #region Call Proxy Methods

    public void TestProxyMethods()
    {
        Console.WriteLine("---  GetDataNoParms  ---");
        Console.WriteLine(this.myProxy.GetDataNoParms());
        Console.WriteLine("--- GetDataWithParms ---");
        Console.WriteLine(this.myProxy.GetDataWithParms("CustomerBob", 12345, true));
    }

    #endregion
}

Thursday, October 17, 2013

Easy Windows Services

I have seen a lot of questions on the Forums about Windows Services. The questions run anywhere from “How can I debug my Service?” to “How can I see the MessageBox my Service is showing?” (hint – you can’t do that last one, it’s not possible to use any UI features in a Windows Service).

So, what’s the secret to making Windows Services easy? Well, first of all, begin by hosting your Service(s) in a Console Application. The transition from tinkering with it while you’re developing, to deploying it as a Windows Service, is made a lot easier this way.

Your Console Application project will contain 4 files: app.config, Program.cs, Services.cs and ProjectInstaller.cs. You could, in a real application, have separate files for the Services and for the ServiceHost. I’ve simplified by putting it all in the same file.

The Program.cs starts everything running (as is normally the case with any Console app):

namespace ConsoleApplication1
{
    class Program
    {
        static MyServiceHost oService;

        // Be sure to add a System.ServiceProcess reference and using
        static void Main(string[] args)
        {
            if (Environment.UserInteractive == false)
            {
                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[] 
                { 
                    new MyServiceHost()
                    // others may be added as follows, we only have one
                    // , new MyOtherHost()
                };
                ServiceBase.Run(ServicesToRun);
            }
            else
            {
                if (ConfigurationManager.AppSettings.Count > 0)
                {
                    oService = new MyServiceHost();
                    oService.Start();
                    Console.ReadLine();
                    oService.Stop();
                }
                else
                {
                    Console.WriteLine("Config file is missing ...");
                    Console.ReadLine();
                }
            }
        }
    }
}

Notice in the above code we check to see whether or not we’re running interactively. A Console application would be interactive, a Windows Service would not. You should be able to see how that works from looking at the above code.

Next, the Services and ServiceHost classes:

namespace ConsoleApplication1
{
    // Service classes are just regular classes, that have only one requirement:
    // They must implement a Start and Stop method.
    public class MyServiceOne
    {
        public void Start()
        {
            // startup code here
        }
        public void Stop()
        {
            // stop code here
        }
    }
    public class MyServiceTwo
    {
        public void Start()
        {
            // startup code here

        }
        public void Stop()
        {
            // stop code here
        }
    }

    // Make sure that you add a reference to System.ServiceProcess in your project references
    // I've got threading in this class, be sure to also add a reference to System.Threading
    public partial class MyServiceHost : System.ServiceProcess.ServiceBase
    {
        // This Windows Service can host as many Service classes as you want
        static MyServiceOne ServiceOne;
        static MyServiceTwo ServiceTwo;

        private Thread SqlThread;
        private bool EndLoop = false;
        private string ConnectionString;

        public MyServiceHost()
        {
            this.CanStop = true;
            this.CanShutdown = true;
            this.CanPauseAndContinue = false;
        }
        protected override void OnStart(string[] args)
        {
            // In the case of my Services, I use SqlServer. I need to be sure it's up and running
            // before my Services start. How could this not be the case? Well, machines could have been
            // rebooted because of Windows Updates or for other kinds of maintenance. Whether or not 
            // SqlServer is on the same machine as your Services really doesn't matter. Your Services
            // could start before SqlServer starts. I handle this possiblity by waiting for SqlServer
            // to start first. This is done in the DoWork() method.
            ThreadStart threadStart = new ThreadStart(DoWork);
            this.SqlThread = new Thread(threadStart);
            this.SqlThread.Start();
        }
        protected override void OnStop()
        {
            if (this.EndLoop == false)
                this.EndLoop = true;
            
            // Notice this interesting tidbit (it applies to my app, but depending on what 
            // your services do, it may also apply to yours ... so, consider this just an FYI):
            // When I start my services (in the StartService() method), I start ServiceOne and then ServiceTwo
            // When I stop them, I stop them in the opposite order, first stop ServiceTwo and then ServiceOne.
            if (ServiceTwo != null)
                ServiceTwo.Stop();

            // Sleep for a second if you need a bit of time between service's stopping
            System.Threading.Thread.Sleep(1000);

            if (ServiceOne != null)
                ServiceOne.Stop();
        }
        protected override void OnShutdown()
        {
            // There may be a bug in the .NET Framework in that this method
            // is not being called on system shutdown for SYSTEM account services.
            // Not sure when/if it will be fixed, but I'm putting code here to stop
            // stuff on the off-chance that it will be called eventually.
            if (ServiceTwo != null)
                ServiceTwo.Stop();
            System.Threading.Thread.Sleep(1000);
            if (ServiceOne != null)
                ServiceOne.Stop();
        }
        protected void DoWork()
        {
            this.ConnectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString; ;
            if (string.IsNullOrEmpty(this.ConnectionString))
            {
                Console.WriteLine("No MyConnectionString or No Config File.");
                return;
            }

            while (this.EndLoop == false)
            {
                if (this.SqlServerIsRunning())
                {
                    this.StartService();
                    EndLoop = true;
                }
                else
                {
                    if (Environment.UserInteractive)
                        Console.WriteLine("Waiting for SQL Server ...");
                    Thread.Sleep(30000); // 30 seconds
                }
            }
        }
        protected bool SqlServerIsRunning()
        {
            bool IsConnected = false;

            try
            {
                using (SqlConnection conn = new SqlConnection(this.ConnectionString))
                {
                    conn.Open();
                    IsConnected = true;
                }
            }
            catch
            {
            }

            return IsConnected;
        }
        protected void StartService()
        {
            ServiceOne = new MyServiceOne();
            ServiceTwo = new MyServiceTwo();

            ServiceOne.Start();
            ServiceTwo.Start();
        }

        // These 2 methods are only used when not runnning as a Service, for testing from a Console window.
        public void Start()
        {
            this.OnStart(null);
            Console.WriteLine("Services Started");
        }
        public void Stop()
        {
            Console.WriteLine("Services Stopping ...");
            this.OnStop();
        }
    }
}

OK, well, that was pretty painless, right? Go ahead and run this Console application. If you’d like to expand on ServiceOne and ServiceTwo to actually do something, go ahead and spin off some new threads or something … whatever your services might have to do. You can set breakpoints in Visual Studio and debug to your heart’s content. You’ll notice that as soon as you hit the Enter key in the Console window, the service will stop.

Now, that’s all there is to hosting a Service in a Console Application. Once you’ve got it all debugged and you’re ready to go, you’re going to want to install your service as a Windows Service. This is also not too difficult. You’ll have to add an Installer class to your project. You can right-click your project, “Add New Item” and choose “Installer Class” … however, that adds some stuff that you’ll just have to take out anyway (it adds a Designer.cs class and you really don’t need that). Instead, just right-click and add a new class and copy my Installer class as a starting point and it’s much easier. Here it is:

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;

namespace ConsoleApplication1
{
    [RunInstaller(true)]
    public partial class MyServiceInstaller : System.Configuration.Install.Installer
    {
            #region Declarations

        private System.ServiceProcess.ServiceProcessInstaller serviceProcessInstaller1;
        private System.ServiceProcess.ServiceInstaller serviceInstaller1;
        private System.ServiceProcess.ServiceInstaller serviceInstaller2;

        public string ServiceName
        {
            get { return this.serviceInstaller1.ServiceName; }
            set { this.serviceInstaller1.ServiceName = value; }
        }
        public string ServiceAccount
        {
            set
            {
                switch (value.ToLower())
                {
                    case "user" :
                        this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.User;
                        break;
                    case "localservice" :
                        this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalService;
                        break;
                    case "networkservice" :
                        this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.NetworkService;
                        break;
                }
            }
        }
        public override string HelpText
        {
            get
            {
                return base.HelpText + 
                    "\r\n\r\nSpecific to My Messaging: \r\n\r\n" +
                    "/ServiceName=[servicename] \r\n" + 
                    " Use if installing multiple My Messaging Services. \r\n" +
                    " Defaults to My.MessagingService if switch not used.\r\n\r\n" +
                    "/ServiceAccount [User] |  [LocalService] | [NetworkService] \r\n" + 
                    " Use if not installing under the System account. \r\n\r\n";
            }
        }
        private bool DebugIt = false;

        #endregion

        #region Constructor

        public MyServiceInstaller()
        {
            //InitializeComponent(); // do our own

            this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
            this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();
            this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Manual;
            this.serviceInstaller1.ServicesDependedOn = new string[] { "Message Queuing", "Distributed Transaction Coordinator" };
            // 
            // serviceProcessInstaller1
            // 
            this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
            this.serviceProcessInstaller1.Password = null;
            this.serviceProcessInstaller1.Username = null;
            // 
            // ProjectInstaller
            // 
            this.Installers.AddRange(new System.Configuration.Install.Installer[] {
                this.serviceProcessInstaller1,
                this.serviceInstaller1});
        }

        #endregion

        #region Methods

        protected override void OnBeforeInstall(IDictionary savedState)
        {
            base.OnBeforeInstall(savedState);
            this.SetPropertiesFromCommandLineSwitches();
            this.SetDebugService();
        }
        protected override void OnBeforeUninstall(IDictionary savedState)
        {
            base.OnBeforeUninstall(savedState);
            this.SetPropertiesFromCommandLineSwitches();
            this.SetDebugService();
        }
        private void SetPropertiesFromCommandLineSwitches()
        {
            // command line switches: /ServiceName= /ServiceAccount= (and /debug= but not really using debug right now)
            // See HelpText property in the Declarations and the ServiceName and Service account properties

            string name = this.Context.Parameters["ServiceName"];
            if (string.IsNullOrEmpty(name))
                this.ServiceName = "My.MessagingService";
            else
                this.ServiceName = name;

            string account = this.Context.Parameters["ServiceAccount"];
            if (string.IsNullOrEmpty(account) == false)
                this.ServiceAccount = account;

            if (this.Context.Parameters.ContainsKey("debug"))
                this.DebugIt = true;
        }
        private void SetDebugService()
        {
            if (this.DebugIt)
            {
                this.serviceInstaller2 = new System.ServiceProcess.ServiceInstaller();
                this.serviceInstaller2.ServiceName = "My.Debug.Service";
                this.Installers.Add(this.serviceInstaller2);
            }
        }

        #endregion
    }
}

Next, we’ll need just a few lines of code to execute via a Command line. It’s easiest to create two batch files, one for installing and one for uninstalling. The .NET Framework has an Install Utility called “InstallUtil.exe”, located in the c:\Windows\Microsoft.NET\Framework folder. If you have multiple versions of the .NET Framework installed on a machine, you must make sure you use the correct InstallUtil, depending on the .NET version you’ve targeted in your project properties. It’s easy to do with batch files. Here’s a batch file to install the above Service:

@echo off

REM change if yours is a different path
set INSTALL_UTIL_HOME=C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319

set PATH=%PATH%;%INSTALL_UTIL_HOME%


echo .
echo .
echo Installing Service My.MessagingService
echo .
echo .
installutil My.MessagingService.exe

echo .
echo Done.
echo .
pause

To uninstall, your batch file will be essentially the same except you’d echo Uninstalling Service, and you’d use the /u parameter:

@echo off

REM change if yours is a different path
set INSTALL_UTIL_HOME=C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319

set PATH=%PATH%;%INSTALL_UTIL_HOME%


echo .
echo .
echo Uninstalling Service My.MessagingService
echo .
echo .
installutil /u My.MessagingService.exe

echo .
echo Done.
echo .
pause

That’s all there is to it. Have fun and happy coding!  =0)

Saturday, September 28, 2013

Double vs Decimal

I ran into an interesting issue when doing some math with a double rather than a decimal. I’m maintaining some existing code and since part of the original code used doubles, I continued writing my new code using doubles as well. The original author had created a string.ToDouble(defaultVal) extension method to use for such purposes (data is being retrieved from a TextBox.Text, even though it’s numeric data), but NO string.ToDecimal(defaultVal) extension method existed. So I didn’t really give it any thought … and just continued to use the double.

I know that there’s a difference as to when you should use double and when you should use decimal … but it seems that I can never remember which is which. And, all along I thought one was floating point and one was not … but that’s not quite true either. It seems that double (and float also) are floating binary point types, whereas decimal is a floating decimal point type.

I found a really good reply that explains this quite nicely in a StackOverflow thread: Difference Between Decimal Float and Double The very first reply is the one I’m referring to and the gist of it is the following:

A double represent a number like this: 10001.10010110011

Whereas a decimal represents a number like this: 12345.65789

As for what to use when:

  • For values which are "naturally exact decimals" it's good to use decimal. This is usually suitable for any concepts invented by humans: financial values are the most obvious example, but there are others too. Consider the score given to divers or ice skaters, for example.

  • For values which are more artifacts of nature which can't really be measured exactly anyway, float/double are more appropriate. For example, scientific data would usually be represented in this form. Here, the original values won't be "decimally accurate" to start with, so it's not important for the expected results to maintain the "decimal accuracy". Floating binary point types are much faster to work with than decimals.

Read the reply in the linked thread, which has a little more to it than what I excerpted above.

Luckily for me, in my testing I used numbers that would cause this difference to be apparent , otherwise I might never have noticed it, which would have been bad once it was in production! Here’s where I went wrong:

Using Double.TryParse("14.19", out Large) and Double.TryParse("10.00", out Small) ... yields the correct numbers if you look just at Large (14.19) and Small (10.0). However, if you do math on the two, such as Large - Small, you don't get what you'd expect. You'd expect 4.19, but what you get is 4.1899999999999995. Usually not a problem, because it would most likely get rounded along the way … and, in fact does correctly display in the TextBox as 4.19. No harm, no foul … unless you happen to be checking to see if 4.19 <= Large - Small ... it should be true (if rounded), but it won't because it doesn't round at that point (4.19 is definitely NOT less than or equal to 4.1899999999999995)!!! But, cast Large and Small to a decimal before even doing the math and everything is fine.

I immediately wrote my own string.ToDecimal(defaultVal) extension method

Maybe after this little fiasco I won’t forget anymore. ;0)

Monday, August 12, 2013

Persisting A Dictionary By Serialization

I recently helped out a guy on the MSDN forums who wanted to be able to persist his data to an XML file, to be able to be retrieved and restored by his application at application startup. He needed to store his data in a Dictionary. All sounds good so far except he couldn’t figure a good way to serialize the data to XML and then deserialize it in order to load it into a Dictionary.

When I first read his post, my first thought was to serialize the entire dictionary to XML, rather than try and serialize just the data parts. But guess what … a Dictionary cannot be serialized with the XmlSerializer. But, there is a way to do it, and that’s with the DataContractSerializer … turns out that it works just fine! And we don’t even have to decorate our Dictionary with a [DataContract] attribute. Let’s see how to do that:

First, let’s get some test data loaded in a Dictionary:

Dictionary<string, List<string>> Layers = new Dictionary<string, List<string>>();
Layers.Add("ourlayer1", new List<string>());
Layers["ourlayer1"].Add("somerandomthing");
Layers["ourlayer1"].Add("anotherrandomthing");

Layers.Add("ourlayer2", new List<string>());
Layers["ourlayer2"].Add("whatisthis");
Layers["ourlayer2"].Add("whoisthis");

Next, we’ll serialize the Layers Dictionary and write it out to an XML file.

DataContractSerializer dc = new DataContractSerializer(typeof(Dictionary<string, List<string>>));

using (StringWriter sw = new StringWriter())
using (var writer = new XmlTextWriter(sw))
{
    writer.Formatting = Formatting.Indented; // indent the Xml so it's human readable
    dc.WriteObject(writer, Layers);
    writer.Flush();
    File.WriteAllText("Layers.xml", sw.ToString());
}

Here’s what the Layers.xml file looks like:

<ArrayOfKeyValueOfstringArrayOfstringty7Ep6D1 xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
  <KeyValueOfstringArrayOfstringty7Ep6D1>
    <Key>ourlayer1</Key>
    <Value>
      <string>somerandomthing</string>
      <string>anotherrandomthing</string>
    </Value>
  </KeyValueOfstringArrayOfstringty7Ep6D1>
  <KeyValueOfstringArrayOfstringty7Ep6D1>
    <Key>ourlayer2</Key>
    <Value>
      <string>whatisthis</string>
      <string>whoisthis</string>
    </Value>
  </KeyValueOfstringArrayOfstringty7Ep6D1>
</ArrayOfKeyValueOfstringArrayOfstringty7Ep6D1>

And, last but not least, let’s read the file back into the Dictionary:

Layers.Clear();
string s = File.ReadAllText("Layers.xml");
using (StreamReader sr = new StreamReader("Layers.xml"))
{
    Layers = dc.ReadObject(sr.BaseStream) as Dictionary<string, List<string>>;
}

Take a look at your Layers Dictionary in the debugger when this process is done and you’ll see it’s been reserialized correctly. It’s a pretty easy process I think. Here’s the link to the MSDN forum question, if you’re interested:

http://social.msdn.microsoft.com/Forums/en-US/3f1897ab-12a3-4da3-acfe-4b08c2cd74db/trying-to-write-a-simple-program-to-gather-strings-and-save-in-xml-file