Click here to Skip to main content
15,907,687 members
Articles / Desktop Programming / Windows Forms

The Anti-Service, Persistence sans System.ServiceModel

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
9 Sep 2010CPOL2 min read 21.6K   160   7   6
When you want an application to trigger on an event (timer, system, file, etc.), but you don't want the overhead of the service manager
Image 1


I was asked to create a small reminder application for an organization I belong to. Ever hour it would prompt with a quote. My "work" answer for something like this would be to create a Windows service, make it self installing, easy peazy. But I wanted to be adventurous, because this is mostly U/I and I didn't want to mess with the service user account, how could this be done without a service? This article outlines this adventure...


The basic components to this project are:

  • Windows (WinForms in this case, but WPF will work too), OnClose and Timers
  • Sockets/Listeners for forcing single instance and "killing" the application
  • InnoSetup Script

Using the Code

  • Create a new Windows project (New Project... Windows)
  • Create a timer. Drag and drop a timer object, set the parameters, create a timer handler. Your project may not be on a timer, that's ok, if an event triggers the window to show/hide, that's all you want
  • Create a "Force Close" mechanism, I created a checkbox called "CanClose"
  • Override FormClosing
    private void TheMessage_FormClosing(object sender, FormClosingEventArgs e)
        e.Cancel = !CanClose.Checked;
  • Create a separate ForceClose() method which sets CanClose and calls "Close"
    public void ForceClose()
       CanClose.Checked = true;
  • Sockets and threading. This is where it gets interesting. So I wanted the behavior that the application should be single instance. There are several good ways to do that, the mutex here on CodeProject is great. But, I also needed it to install/uninstall cleanly, which means it needs to force itself closed. To do that, I used sockets listener/client on a dedicated port. It sounds counter intuitive, but I created the client first (is that the chicken or the egg?!)
    public void Main(string[] args){
        bool killStream = args.Length > 0 && args[0] == "-kill";
            using (TcpClient clnt = new TcpClient())
                clnt.Connect("localhost", 7231);
                if (clnt.Connected)
                    clnt.GetStream().Write(new byte[] 
    		{ (byte)(killStream ? 0 : 1) }, 0, 1); // 0 - kill or 1 - show
        // I really hate catching an exception as logic, but there's no other way
        catch (SocketException) { } // nothing listening, not already running
        if (killStream) // if it's a kill... don't start

    Finally the listener...

    TcpListener lstn = new TcpListener
            (System.Net.IPAddress.Parse(""), 7231);
    // So, we start a long loop listening for incoming messages
    while (true)
        using (TcpClient clnt = lstn.AcceptTcpClient())
            byte[] buff = new byte[1];
            if (1 == clnt.GetStream().Read(buff, 0, 1))
                switch (buff[0])
                    case 0: // Kill request
                    case 1: // Show request
  • And finally, you need an InnoSetup Script that will invoke this before attempting to re-install/uninstall, that looks like this...
    Source: "{Your Project}\bin\Release\AntiService.exe"; DestDir: "{app}"; 
    	Flags: ignoreversion; BeforeInstall: StopLBApp
    procedure StopLBApp();
      FileName : String;
      ResultCode: Integer;
      Log('Asking any existing processes to stop now');
      FileName := ExpandConstant('{app}\AntiService.exe');
      if FileExists(FileName) then
        if not ShellExec('', FileName, '-kill', '', 
    	SW_SHOWNORMAL, ewNoWait, ResultCode) then
          MsgBox('DeinitializeSetup:' #13#13 'Execution of ''' + 
    	FileName + ''' failed. ' + SysErrorMessage(ResultCode) + '.', 
    		mbError, MB_OK);


So what you have is an application that once it's started, will stay running, and will attempt to show a window every time it's launched or on some event. Timer in my case. I hope you have enjoyed!


  • 9th September, 2010: Initial post


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Written By
Engineer Big Company
United States United States
My professional career began as a developer fixing bugs on Microsoft Word97 and I've been fixing bad habits ever since. Now I do R&D work writing v1 line of business applications mostly in C#/.Net.

I've been an avid pilot/instructor for 13+ years, I've built two airplanes and mostly fly gliders now for fun. I commute in an all-electric 1986 BMW 325 conversion.

I'd like to get back to my academic roots of programming 3D analysis applications to organize complex systems.

Comments and Discussions

GeneralMight be handy Pin
bigRahn14-Sep-10 8:40
bigRahn14-Sep-10 8:40 
GeneralThoughts Pin
PIEBALDconsult8-Sep-10 16:53
mvePIEBALDconsult8-Sep-10 16:53 
GeneralRe: Thoughts Pin
CodingBruce9-Sep-10 3:08
CodingBruce9-Sep-10 3:08 
GeneralRe: Thoughts Pin
PIEBALDconsult9-Sep-10 4:01
mvePIEBALDconsult9-Sep-10 4:01 
GeneralRe: Thoughts Pin
pzand9-Sep-10 19:11
pzand9-Sep-10 19:11 
GeneralRe: Thoughts Pin
Pete O'Hanlon14-Sep-10 7:57
mvePete O'Hanlon14-Sep-10 7:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.