h1

Installing Windows Services programmatically pt. 2

September 25, 2008

[An update of this post].

After a few problems with using the ManagedInstallerClass (passing arguments in), and noticing that the MSDN docs say it’s not meant to be used in any case, I moved to using this sort of code instead:

using System;
using System.Configuration.Install;
using System.ServiceProcess;
using System.Threading;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Collections.Generic;

namespace SimpleWindowsServiceManager
{
    class Program
    {
        static void Main(string[] args)
        {
            string fullpath = args[0];
            string[] arguments = args[1].Split(' ');
            string servicename = Path.GetFileNameWithoutExtension(Path.GetFileName(args[0]));
            foreach (string arg in arguments)
            {
                if (arg.Contains("name"))
                {
                    string[] bits = arg.Split(new char[] { '=' });
                    servicename = bits[1];
                }
            }

            #region Test to see if it's a service
            try
            {
                AssemblyInstaller.CheckIfInstallable(fullpath);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Assembly's not installable");
                return;
            }
            #endregion

            #region install
            Assembly assembly = null;
            try
            {
                assembly = Assembly.LoadFrom(fullpath); // LoadFrom probes path for dependencies -- LoadFile does not.
            }
            catch (Exception ex)
            {
                Console.WriteLine("Couldn't load assembly: " + ex.Message);
                return;
            }
            AssemblyInstaller installer = new AssemblyInstaller(assembly, null);
            Dictionary state = new Dictionary();
            try
            {
                installer.Install(state);
                installer.Rollback(state);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Trouble pre-installing assembly");
                return;
            }
            #endregion

            installer = new AssemblyInstaller(assembly, arguments);
            state = new Dictionary();

            #region Install service
            try
            {
                installer.Install(state);
            }
            catch (InvalidOperationException iex)
            {
                Console.WriteLine("Install not applicable for this assembly:\n" + iex.Message);
                return;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            #endregion

            Console.WriteLine("Getting service controller for " + servicename);
            ServiceController controller = new ServiceController(servicename);

            #region Start service
            try
            {
                Console.WriteLine("Starting service");
                controller.Start();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            #endregion

            Thread.Sleep(10000);

            #region Stop service
            try
            {
                Console.WriteLine("Stopping service");
                controller.Stop();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            #endregion

            Thread.Sleep(10000);

            #region Uninstall service
            try
            {
                installer.Uninstall(state);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            #endregion
        }
    }
}
h1

Installing Windows services programmatically

June 5, 2008

[updated in this post.]

using System;
using System.Configuration.Install;
using System.ServiceProcess;
using System.Threading;
using System.Diagnostics;
using System.IO;
using System.Reflection;

namespace SimpleWindowsServiceManager
{
    class Program
    {
        static void Main(string[] args)
        {
            string fullpath = args[0];
            string servicename = Path.GetFileNameWithoutExtension(Path.GetFileName(args[0]));

            #region Test to see if it's a service
            Assembly assembly = null;
            try
            {
                assembly = Assembly.LoadFile(fullpath);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Couldn't load assembly: " + ex.Message);
                return;
            }
            AssemblyInstaller installer = new AssemblyInstaller(assembly, null);
            if (installer.Installers.Count == 0)
            {
                Console.WriteLine("Assembly apparently doesn't contain a service");
                return;
            }
            #endregion

            #region Install service
            try
            {
                // For options here take a look at installutil in the framework directory
                Console.WriteLine("Installing " + fullpath);
                ManagedInstallerClass.InstallHelper(new string[] { fullpath });
            }
            catch (InvalidOperationException iex)
            {
                Console.WriteLine("Install not applicable for this assembly:\n" + iex.Message);
                return;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            #endregion

            Console.WriteLine("Getting service controller for " + servicename);
            ServiceController controller = new ServiceController(servicename);

            #region Start service
            try
            {
                controller.Start();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            #endregion

            Thread.Sleep(10000);

            #region Stop service
            try
            {
                controller.Stop();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            #endregion

            Thread.Sleep(10000);

            #region Uninstall service
            try
            {
                ManagedInstallerClass.InstallHelper(new string[] { "/LogToConsole=false", "/u", args[0] });
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            #endregion
        }
    }
}
h1

The Craftsman by Richard Sennett

June 3, 2008

The Craftsman, Richard Sennett

Review in the Guardian by Fiona McCarthy

http://books.guardian.co.uk/review/story/0,,2254702,00.html

Does Sennett go too far in praising the Linux system of “open-source” computer software as a modern example of a public craft employable and adaptable by anyone, which users themselves donate time to improve? The best known Linux application is Wikipedia, the encyclopedia to which any user can contribute. But, as we all know, many Wikipedia entries are just rubbish. Linux workshops are still grappling with an underlying and often inflammatory problem in all communal craft workshops, that of quality control.

It strikes me that this is wrong. This partly, superficially, because Wikipedia is not a Linux application in the sense she means, and so a comparison of Linux and Wikipedia is flawed.

But partly also because what is missing is utility. Linux is an operating system: its effectiveness and quality can be determined becaused it is used, and good craftsmanship eases that use. Wikipedia is a good source of practical technical information because again, that information can be used. Where the information contained is more nebulous, or open to discussion,  or less easy to apply or use, then it falls down.

h1

Double buffer in C#

September 29, 2007

Don’t do anything other than copy a back buffer to the control in the controls paint method.Don’t necessarily call Refresh() from event handlers that modify the image — it’s inefficient to call Refresh from a mouse movement handler that handles dragging of an object across the control, for example.

Draw on a back buffer then Refresh() at set points in time (<= 250 ms) using a System.Windows.Forms.Timer.

Code snippets here as a reminder:

private System.Windows.Forms.Timer timer;
private BufferedGraphicsContext context;
private BufferedGraphics gfx; 

private System.Windows.Forms.Panel panel1; 

public Form()
{
    this.panel1.Paint += new System.Windows.Forms.PaintEventHandler(this.panel1Paint); 

    this.SetStyle(ControlStyles.AllPaintingInWmPaint ControlStyles.UserPaint, true);
    this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 

    context = BufferedGraphicsManager.Current;
    context.MaximumBuffer = new Size(this.panel1.Width + 1, this.panel1.Height + 1); 

    gfx = context.Allocate(this.panel1.CreateGraphics(),
        new Rectangle(0, 0, this.panel1.Width, this.panel1.Height)); 

    timer = new System.Windows.Forms.Timer();
    timer.Interval = 100;
    timer.Tick += new EventHandler(this.OnTimer);
    timer.Start();
} 

private void OnTimer(object sender, EventArgs e)
{
    DrawToBuffer(gfx.Graphics);
    gfx.Render(Graphics.FromHwnd(this.panel1.Handle));
} 

void panel1Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
    gfx.Render();
} 

private void panel1Resize(object sender, EventArgs e)
{
    context.MaximumBuffer = new Size(this.panel1.Width + 1, this.panel1.Height + 1);
    if (gfx != null)
    {
        gfx.Dispose();
        gfx = null;
    }
    gfx = context.Allocate(this.CreateGraphics(),
        new Rectangle(0, 0, this.panel1.Width, this.panel1.Height));
    DrawToBuffer(gfx.Graphics);
    this.Refresh();
}