A pleasant walk through computing

Comment for me? Send an email. I might even update the post!

Create an Easily Debuggable Windows Service

In a previous job, I needed to create Windows services. One thing that had tripped me up in the past was being able to debug the service. I figured someone (or ones) had solved this, so I did a bunch of research, consolidated what I found, documented it, and am finally (three years later?) posting it.

With the setup, below, you’ll have a Windows service that:

Runs in debug mode as you’d expect, without having to set unnecessary breakpoints.

Can run as a console app, allowing you to simply double-click the exe. This is useful for many things:

  • Output running messages to the console (the same info you’re logging, most likely).
  • Perform one-off runs for things like integration services that run on a schedule.
  • Easily run elsewhere without having to install as a service.

In addition, my steps include Nice-to-Dos like file and service naming, startup type, etc. These are more for me than you, so that I don’t have to look them up again, so think of them as a bonus.

The example below creates a sample FileImport service. Note that Visual Studio Express doesn’t have a Service project, but you can still create a service. (Sadly, I’m not covering that here, but might do so in a future post.)

Create a new Windows Service project.

image

Change the Assembly output type to Console Application (for debugging).  This, in my opinion, is the big deal. I can now write my program just like I would a console application, which is how I want to think of a service.

This is also a good time to change the assembly information (title, company, etc.).

image

Select Servic1.cs. Rename the Service1.cs file/class name, e.g. to FileImport.cs.

imageimage

image

Select FileImport.cs and view the designer (Shift F7), change ServiceName, e.g. FileImport

image

Rick-click design surface and choose Add Installer

image

Open ProjectInstaller.cs designer, select ServiceInstaller1 and edit:

image

  • Description
  • DisplayName, e.g. “Sample File Import”
  • ServiceName. Should be correct from Service1 designer change, otherwise FileImport
  • StartType, e.g. Automatic

image

If desired, in ProjectInstaller designer, select ServiceProcessInstaller and edit

  • Account = User (set to NetworkService or LocalService if desired.)

image

image

Open FileImport.cs code view, create a public member Start() for debugging.

namespace FileImport
{
    public partial class FileImport : ServiceBase
    {
        public FileImport()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
        }

        protected override void OnStop()
        {
        }

        public void Start(string[] args)
        {
            OnStart(args);
        }

    }
}

Change Program.Main() to this (or similar).

namespace FileImport
{
    static class Program
    {
        /// 
        /// The main entry point for the application.
        /// 
        static void Main()
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new FileImport()
            };
            // If you don’t want the exe to run as console when double-clicked, then use:
            //   if (System.Diagnostics.Debugger.IsAttached)
            if (Environment.UserInteractive)
            {
                Console.WriteLine("Service running, press  to stop.");
                ((FileImport)ServicesToRun[0]).Start(null);
                Console.ReadLine();
                ((FileImport)ServicesToRun[0]).Stop();
            }
            else
            {
                ServiceBase.Run(ServicesToRun);
            }
        }
    }
}

At this point, you can run the project. It will open a console window and wait.

image

If you install the service, when the service is started it behaves like any other service, i.e. doesn’t display the console window.

Our service isn’t doing anything, so let’s see what the benefit is to creating a service as a console app instead of the default Windows app. We’re not going to do anything fancy like multithreading, I just want to give a flavor. In FileImport.cs, use the following code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace FileImport
{
    public partial class FileImport : ServiceBase
    {
        Timer _timer = new Timer(5000);

        public FileImport()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            _timer.Elapsed += OnTimerElapsed;
            _timer.Start();
        }

        private void OnTimerElapsed(object sender, ElapsedEventArgs e)
        {
            Console.WriteLine("The time is--or, to be precise, was: " + DateTime.Now.ToString());
        }

        protected override void OnStop()
        {
            Console.WriteLine("Stopping. Here's one method where you'd handle processes that shouldn't be interrupted, gracefully stop them, then end the service. Press  to finish stopping.");
            _timer.Stop();
            _timer.Dispose();
            //etc.
            Console.ReadLine();
        }

        public void Start(string[] args)
        {
            OnStart(args);
        }

    }
}

Run the program and it will output something like this.

image

Now, if you were to install and run this as a service, you still wouldn’t see anything. But you can imagine adding appending text to a file (for example) in the OnTimerElapsed event.

        private void OnTimerElapsed(object sender, ElapsedEventArgs e)
        {
            string msg = "The time is--or, to be precise, was: " + DateTime.Now.ToString() + "\r\n";
            System.IO.File.AppendAllText(Environment.ExpandEnvironmentVariables("%USERPROFILE%\\TestFileImport.txt"),msg);
            Console.WriteLine(msg);
        }

Of course, I can drop into the debugger as expected.

image

There you go! A simple way to build better Windows services.

References

http://einaregilsson.com/run-windows-service-as-a-console-program/

(Underrated) Work Skills

I’m not sure what “underrated” means. Or even whether these are truly “skills.” But, this article was interesting, so I synthesized and summarized what the (supposed) CEOs were looking for.

10 CEOs Answer The Question, What Are The Most Underrated Skills Most Employees Lack?

The one “skill” I take exception to was related to email. The CEO argued that a person should be able to find an email--without searching—in under thirty seconds. While I think it’s good and valuable to keep a clean inbox, I think it’s dumb to shortchange searching like that. By searching, I can find an email I need in under five seconds. Isn’t that a better use of my time?

My area for improvement: Organize and lead a team.

  1. Be succinct
  2. Be reliable (manage tasks/deliverables without reminders).
  3. Use elegant humor
  4. Write well
  5. Reduce chatter (inbox zero)
  6. Use lists effectively
  7. Golden Skill Triangle:
    • Figure out what to do (next)
    • Write effective goals (with due dates).
    • Organize and lead a team to execute large scale plans.
  8. Own the job

VB.Net Windows Project to C# Conversion Tools Quick Review

If you’re looking for a thorough comparative review, this isn’t it! But, here are a few tools I looked at for converting a complex VB.NET project to C#.

Convert.NET by fish’s dotNET

  • Cannot be used commercially with buying the (reasonably priced) license.
  • Stand-alone, but can be added as Tool.
  • Other features besides converting.
  • Conversion of project had the most problems of any tool.

SharpDevelop

  • Only 4.4 can convert from VB to C#. Feature does not exist in version 5.
  • Project isn’t very active, because free versions of Visual Studio are much more readily available.
  • Conversion fidelity will work better with .NET 4.5 or older.
  • Better conversion that Convert.NET
  • Free for commercial use.

VBConversions

Instant C#

  • Commercial tool, expensive $159. (But worth it for a paid contract.)
  • Claims near-perfect fidelity.
  • Has free edition for smaller projects, 2000 line project conversion limit.

My choice: VBConversions, because of the better post conversion tools that show where errors are. However, one thing Instant C# did that I like is automatically generate a variable copy when a VB.NET for…each manipulated the iterating variable.

foreach (string field in fields)
{
   string fieldCopy = field;
   fieldCopy = fieldCopy.Trim();
   ...
}

VBConversions marked it with an error, essentially leaving the code with a bug. If I weren’t to check the errors, this could be a problem because the code would still compile.

foreach (string field in fields)
{
   // field = field.Trim(); VBConversions Warning: A foreach variable can't be assigned to in C#.
   string fieldType = "";
   ...
}

In both cases, it would be wise to set up Visual Studio to treat their comments as Tasks, assuming they consistently start with “VBConversions” or  “INSTANT C#”. Then, go through each comment and remove it after evaluation.

Regardless of the tool, professional diligence says to review every error/message the conversion reports.

References

Get rid of the ‘Missing XML comment for publicly visible type or member’ warning