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

Saturday, June 29, 2013

Inheritance and Constructors

I see frequent questions on the Forums where code doesn’t seem to work right and it comes down to the poster’s lack of understanding about the order in which the constructors are executed for the base class and a sub-class.

Here's a common scenario: say you have a base class that does some work (in the example I'll show, it is a generic class to fill a DataSet from SQL, based on the TableName property of the class). Each sub-class of this base class will provide it's own TableName property, because each sub-class will be filling it's own table.

The first attempt at creating these two classes, looks like this:

public class BizObj
{
    protected string TableName = "";
    private DataSet oData;

    public BizObj()
    {
        LoadData();
    }

    public void LoadData()
    {
        SqlConnection oConn = new SqlConnection("...");
        SqlDataAdapter oAdapter = new SqlDataAdapter("SELECT * FROM " + this.TableName, oConn);
        oAdapter.Fill(oData);

    }
}

public class AuthorBizObj : BizObj
{
    public AuthorBizObj()
    {
        this.TableName = "Authors";
    }
}

However, this does not work. Why? Because the BizObj (base class) constructor fires before the AuthorBizObj (sub-class) constructor, not the other way around. And then it's too late to set the TableName at that point.

The trick to fixing this is to use a virtual Property, rather than a member, and to override that Property in each sub-class:

public class BizObj
{
   public string m_TableName="";

   protected virtual string TableName
   {
      get {return this.m_TableName;}
      set {this.m_TableName = value;}
   }

   private DataSet oData;

   public BizObj()
   {
      LoadData();
   }

   public void LoadData()
   {
      SqlConnection oConn = new SqlConnection("...");
      SqlDataAdapter oAdapter = new SqlDataAdapter("SELECT * FROM "+this.TableName,oConn);
      oAdapter.Fill(oData);

   }
}

public class AuthorBizObj : BizObj
{
    protected override string TableName
    {
        get { return "Authors"; }
    }
}

Sunday, May 26, 2013

Comparing Original To Modified In A DataSet

We can easily determine which DataRows in a DataTable have changed. In fact, there are a couple of ways to do that, but it depends on what you intend to do when processing those changes. We can also determine which column of data has changed, but we'll tackle that topic second.

First thing I'll show are two ways to determine DataRow changes.

First option: you can loop through the every row, and determine it’s RowState, which will tell you if the DataRow has been modified or added:

foreach (DataTable dt in MyDataSet.Tables)
{
    foreach (DataRow row in dt.Rows)
    {
        if (row.RowState == DataRowState.Modified || row.RowState == DataRowState.Added)
        {
            // These are the actual rows that have some kind of changes
        }
    }
}

Second Option: If you’re not actually going to do anything with the actual rows, you just need to do some other kind of processing or validation or whatever, you can make use of the DataSet.GetChanges() method. This returns a DataSet containing only the changes (Modified or Added) from your original DataSet. Keep in mind that this is a new DataSet ( a new object) and has no “connection” to your original DataSet. Your code would then look like this:

DataSet dsChanged = MyDataSet.GetChanges();

foreach (DataTable dt in dsChanged.Tables)
{
    foreach (DataRow row in dt.Rows)
    {
        // these are copies of the rows that have some kind of changes
        // either Modified or Added (not the deleted rows)
    }
}

But what about columns that have changed?

Sometimes we want to know which columns have data that has changed. In this case, knowing that the DataRow has changed is not sufficient. That’s a different kettle of fish, but also quite easy to determine. We need to make use of something called a DataRowVersion. My example below will use the dsChanged DataSet from the above example, but the same logic can be applied to the actual MyDataSet object as well (keeping in mind that you need to test the RowState, as I show above).

foreach (DataTable dt in dsChanged.Tables)
{
    foreach (DataRow row in dt.Rows)
    {
        for (int i = 0; i < dt.Columns.Count; i++)
        {
            if (!row[i, DataRowVersion.Current].Equals(row[i, DataRowVersion.Original]))
            {
                // This particular Column has some kind of changes 
            }
        }
    }
}

And that’s it! Hope this helps someone!

Saturday, April 27, 2013

Project item '4294967294' does not represent a file.

Wow, that’s a pretty non-descriptive error message, isn’t it? And the funny thing is, that particular item number is always the same! What the heck is this?

This is an error message you can get in Visual Studio. I don't know if this is specific to SSRS report projects or not, but I suspect it is. I ran into the error when trying to open a solution with a .rptproj.

Googling finds all sorts of stuff about deleting a line out of the rptproj file and rebinding to source control (most mention Source Safe, but I use TFS and still had the issue). Also, this was in VS2005 (because we're using SSRS 2005 … and the reason for that is a story for another day).

It turns out, this guy had the answer all along and it didn't involve mucking about with the .rptproj file!

http://followtheheard.blogspot.com/2008/03/error-opening-reporting-services.html

The issue is caused because someone checked in their .rptproj.user file. That's the only thing wrong! The .user file is specific to a particular user and should never be checked in (I don't know why it was to begin with). The solution is easy ... check out the .user file and then delete it. I couldn't delete it from TFS (because other people had done the same thing and you can't delete a file from TFS if it has pending changes). But, you can just delete it from your own folder, then re-open your solution and all will be fixed!

Saturday, March 30, 2013

Code Snippets

Today I’m going to write about code snippets. Code Snippets have been in use since Visual Studio 2005. I knew about them then, but didn’t really have a need to create my own, so I eventually forgot about them until about 4 months ago, when I found I had a really, really, really good use for them!

But, let’s back up a bit … what is a code snippet? Surely you have taken advantage of them without realizing it. Think about loops: just type the word for and hit tab twice. Voila, the entire for loop is stubbed out for you to fill in the details:

for (int i = 0; i < length; i++)
{
    
}

Likewise, try foreach and hit tab twice. Here’s what you get:

foreach (var item in collection)
{
    
}

If you haven’t already discovered this feature, you’re in for a treat. Try it yourself right now, you’ll love it! The “for” and the “foreach” are called shortcuts. If you don’t know a shortcut, or can never remember the one you want or you simply want to explore, all you have to do is position your mouse in your code where you want to insert a code snippet, then right-click and choose “Insert Snippet …” and find what you’re looking for or something else that looks interesting.

Now for the good part … you can create your own code snippets to do simple “templates” (like those for loops above) or more complicated “templates'”. I had big chunks of semi-repetitive code; groups of methods that needed to be put into each new module written (a new module to interface with each different vendor product, so each bit of code would use different parameters in the methods).

I wrote a big long snippet for that use (and it works beautifully) and after that I was hooked on creating snippets! I regularly use 4 or 5 that I created in every new module I have to write. It speeds up my coding tremendously, not to mention gets rid of any possibilities for screwing up and leaving out something important.

First, here’s a link for future reference if you need to know more than I can tell you in this short blog:

http://msdn.microsoft.com/en-us/library/vstudio/ms165393(v=vs.100).aspx

Next, let me show you what the file looks like for those simple snippet examples I showed above. Let’s just do the “foreach” one. Here’s the entire foreach.snippet file … it’s just XML:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>foreach</Title>
            <Shortcut>foreach</Shortcut>
            <Description>Code snippet for foreach statement</Description>
            <Author>Microsoft Corporation</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
                <SnippetType>SurroundsWith</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>type</ID>
                    <ToolTip>Type of object in the collection to iterate through</ToolTip>
                    <Default>var</Default>
                </Literal>
                <Literal>
                    <ID>identifier</ID>
                    <ToolTip>Identifier that represents the element in the collection</ToolTip>
                    <Default>item</Default>
                </Literal>
                <Literal>
                    <ID>collection</ID>
                    <ToolTip>Name of collection or array to iterate through</ToolTip>
                    <Default>collection</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp"><![CDATA[foreach ($type$ $identifier$ in $collection$)
    {
        $selected$ $end$
    }]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

So, how does this work? Notice the very last thing in the XML, this is the part that contains the code “template” that will become the snippet (all the stuff contained within the CDATA).

foreach ($type$ $identifier$ in $collection$)
{
    $selected$ $end$
}

All the things delimited by the “$” are what will get replaced in the IDE when you hit tab twice. The Declarations in the beginning of the XML describe what each of these literals should be, along with the defaults that are initially displayed in your IDE. The $selected$ and $end$ are special literals. Here’s what MSDN has to say about them:

Two reserved words are available for use in the text of the Code element: $end$ and $selected$. $end$ marks the location to place the cursor after the code snippet is inserted. $selected$ represents text selected in the document that is to be inserted into the snippet when it is invoked. For example, if you had:

$selected$ is a great color. I love $selected$.

and the word "Blue" was selected when you invoked the template, you would get:

Blue is a great color. I love Blue.

All other $ keywords are dynamically defined in the <Literal> and <Object> tags.

What they mean by “selected text” is when you highlight some text in your code, then right-click and choose “Surround With …” and then pick a snippet to use.

Here’s something I wrote to help out a guy on the MSDN forums (see the thread here, if you’re interested: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/3198baaa-0250-49c6-bad5-f5242a2b5852). He wanted to have a static property that was set by calling a method … but, he didn’t want to have to run that method every time he used the property. And, he used these types of properties everywhere, so he didn’t want to have to type the same monotonous stuff over and over again. To me, it sounded like the perfect use for a code snippet.

Here’s the GetPropOnce.snippet I wrote for that:

<?xml version= "1.0" encoding="utf-8" ?>
<CodeSnippets xmlns = "http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format ="1.0.0">
    <Header >
        <Title>GetOnce Property</Title>
        <Description>Property that is only gotten once, checking backing variable for null</Description>
        <Shortcut>propgetonce</Shortcut>
    </Header>
    <Snippet>
        <Declarations>
            <Literal>
                <ID>type</ID>
                <Default>int</Default>
            </Literal>
            <Literal>
                <ID>PropertyName</ID>
                <Default>MyProperty</Default>
            </Literal>
            <Literal>
                <ID>MethodName</ID>
                <Default>DoSomething</Default>
            </Literal>
            <Literal>
                <ID>DefaultValue</ID>
                <Default>DefaultForNull</Default>
            </Literal>
        </Declarations>
        <Code Language="CSharp">
            <![CDATA[
                private $type$? m_$PropertyName$ = null;
                public $type$ $PropertyName$
                {
                    get
                    {
                        if (m_$PropertyName$ == null)
                        {
                            m_$PropertyName$ = $MethodName$();
                        }
                        return m_$PropertyName$ ?? $DefaultValue$;
                    }
                }
             ]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

A lot of stuff, but still pretty easy. The code template part of it is pretty straightforward:

private $type$? m_$PropertyName$ = null;
public $type$ $PropertyName$
{
    get
    {
        if (m_$PropertyName$ == null)
        {
            m_$PropertyName$ = $MethodName$();
        }
        return m_$PropertyName$ ?? $DefaultValue$;
    }
}

Cool, huh? But, it was time-consuming to write all those literals and everything in XML. Now, I just wrote this last week (which is what made me think I should write a blog post about it), but I thought at the time that there had to be an easier way to write the .snippet file. I didn’t get around to looking for anything to make it easier until I started researching for writing this blog post. I found a decent Snippet editor/designer on CodePlex:

http://snippetdesigner.codeplex.com/

This designer is a plug-in for Visual Studio (download it, double-click what you downloaded, and it adds it to Visual Studio for you). Basically, with this plug-in you only have to write the template (without all the $ delimiters), and indicate which parts of that template should be the literals and it does a lot of the grunt work for you. And, what’s even better is you can use existing code in the IDE (or write some new code just for this purpose) … just select the code, right-click and choose “Export As Snippet” and you’re in the designer with your selected code all set to make it into a template. Couldn’t be easier … I wish I had discovered this plug-in a few months back when I was writing some heavy-duty snippets!

Enjoy!

Saturday, January 19, 2013

Watch Out For DateTime.TryParse()

You’ve heard all kinds of good things about the various .TryParse() methods, and rightly so. They’re a good way to convert an object to the appropriate data type, such as int, long, decimal, DateTime, etc., without having to worry about the conversion throwing an exception if the object cannot be converted to the appropriate data type. For example, you could get an exception if you simply tried to cast the object:

int x = (int)MyObject; // could throw an exception

or if you used the Convert methods:

int x = Convert.ToInt32(MyObject); // could throw an exception

But, the .TryParse() methods avoid all that and simply do the conversion if possible. If the string can be converted to the data type, the value is put into the out parameter and the method returns true. If it cannot be converted, a default value is put into the out parameter and the method returns false.

int x;

// You can choose to check the bool value that's returned
if (int.TryParse(MyObject.ToString(), out x))
{
    // We have a valid value, do something
}

// Or don't bother checking the boolean, if you're OK with the default
// if MyObject cannot be converted. In this case, int, the default is 0.
int.TryParse(MyObject.ToString(), out x);

Now, let me say that the DateTime.TryParse() works fine too, but there is one gotcha to look out for. If the DateTime object that you wish to Parse comes from a database and you need the entire precision of that value, then you can’t use .TryParse(). In other words, more precision than down to the second. Let’s look at a DateTime value that I retrieve from a SQL Server database table, that was put into a column via GETDATE() in a SQL Stored Procedure:  09:31:45.333  Note that this is a bit more precise than down to 45 seconds. There’s that decimal value of .333 after it. Why would you care about that?

Here’s the scenario that bit me: Rows are entered in a database table every time an activity occurs, which could be as often as 30 seconds. Periodically, I need to retrieve the data for the most recent activity. So, I use “SELECT MAX(StatusTime) FROM etc...”  that returns the most recent DateTime from the above mentioned table, which I retrieve by running command.ExecuteScalar(). The only datatype that .ExecuteScalar() returns is an object. In order to then make use of this newly retrieved date, I need to convert it to a DateTime variable. I had been so enamored of using TryParse() for this type of  thing, that I just went ahead and used it here too.

command.CommandText = "SELECT MAX(StatusDate) FROM MyTable GROUP BY ActivityID";
DateTime LastStatusDate;
DateTime.TryParse(command.ExecuteScalar().ToString(), out LastStatusDate);

The only time that the value returned from the query will be DBNull is at the very start, when the app is first used and the database contains no data or when it’s the first time using that particular ActivityID. In either case, I was ok with the default value, which is DateTime.MinValue.

So, in my testing, when retrieving activity within a date range, I never got the very last set of activity records. I would get everything before 09:31:45.000, but I knew that there was also activity “posted” at 09:31:45.333 which wasn’t being retrieved.

The culprit? The .ToString()!! The time portion of my date went from being 09:31:45.333 in the database, to being 09:31:45 in my LastStatusDate variable because the .ToString() doesn’t “recognize” the decimal portion of the time. Consequently, any activity that had the time of 09:31:45.333 was not being retrieved!!

The obvious solution to this dilemma is to check that the object returned from the .ExecuteScalar() is of the DateTime datatype and then cast the object to my LastStatusDate variable. I could see that potentially I may want to use this functionality more than just this one place, so I decided to write an extension method for object data types to handle this. I actually wrote two of them and they work perfectly!

// Extension methods for Dates
public static DateTime ToDate(this object o)
{
    if (o is DateTime)
        return (DateTime)o;
    else
        return DateTime.MinValue;
}
public static bool TryParseDate(this object o, out DateTime date)
{
    if (o is DateTime)
    {
        date = (DateTime)o;
        return true;
    }
    else
    {
        date = DateTime.MinValue;
        return false;
    }
}

The reason I wrote two different extension methods is that sometimes you need to test the boolean return value of a TryParse() kind of method and sometimes you don’t. Here’s how to use both extension methods:

DateTime LastStatusDate;
if (command.ExecuteScalar().TryParseDate(out LastStatusDate))
{
    // do something with the LastStatusDate variable
}

Or, if you don’t  wish to check the boolean, such as maybe adding a date to a List<DateTime>:

MyDateList.Add(command.ExecuteScalar().ToDate());

Or just setting the variable:

LastStatusDate = command.ExecuteScalar().ToDate();

Obviously these two extension methods can be used with any type of object (for example, a DataRow column in a DataTable), I just showed it here using the same object (the result returned from the ExecuteScaler() method) for consistency in my example.

They are pretty handy extension methods … I highly recommend adding them to your bag of tricks!