Running a Windows Service in Console mode?

25,163

Solution 1

And I found my answer! My project properties were set to Windows App instead of Console App. DOH! (Project Properties > Application Tab > Output type:)

Solution 2

Also.. instead of using -console arg, you can identify its console by using Environment.UserInteractive, which will be false when running as service, but true when running the EXE directly.

Share:
25,163
Keith Barrows
Author by

Keith Barrows

Keith lives in Florida and specializes in Information Technology applications utilizing web technologies. He has been working in software ever since high school and stepped forward as a professional in the early 1990s. He is very good at figuring out new things on the fly. Technology is always changing. What is hot today is a memory tomorrow. Realizing this early on he spent his time becoming a Self-Sufficient Developer, somebody who can learn new things as they arise. He has demonstrated a passion to be highly proficient in any project he tackles. With over 20 years of experience Keith has consulted on all aspects of the software development life cycle from design and development to quality assurance and maintenance. He has worked in both the Agile and Water Fall methodologies of software creation, to include Scrum, Kan-ban and XP. Keith has a broad set of skills in the web sphere from light UI design to a deeper server-side knowledge of .NET including Core, Entity Framework, Web Forms, MVC, Web API, C#, VB as well as T-SQL and NoSql. Some of Keith's highlights include: Designed and built a Web Forms based system to replace a highly manual and error prone process that ended up saving the client over $10 million in governmental fines. Worked on updating a legacy system that could no longer handle the client load allowing the system to go from 100 clients with 100 users each to 500 clients with 250 users each. Experience leading 3 to 10 member development teams. Volunteered to be part of a 4 man team to self lead the development teams consisting of 26 developers and 8 QA personnel as the company was missing a CTO. Currently, Keith is an independent consultant with 20+ years of industry experience actively pursuing an even deeper understanding of .NET, cloud based security and web development. He is active on Stack Overflow, was a former ASP.NET MVP and a founding member of the ASPInsiders.

Updated on May 06, 2020

Comments

  • Keith Barrows
    Keith Barrows almost 4 years

    I found some sample code posted at https://groups.google.com/group/microsoft.public.dotnet.languages.csharp/browse_thread/thread/4d45e9ea5471cba4/4519371a77ed4a74?hl=en&pli=1 for self installing a Windows Service. I am in C# on fx 4.0. Trying to figure out where I went off the rails...

    My questions:

    1. I created a Win Service project. In program.cs / main() I pretty much copied the code example. It appears most everything is working except launching a console window if I am in DEBUG mode (passing in - c of course). For some reason the console window never opens.
    2. The other challenge I had was the call to StartUp() / ShutDown() in the console portion would not compile. I ended up have to initialize my service object and then call it.
    3. I am getting the following error when the Console.ReadKey() method is called:

    Cannot read keys when either application does not have a console or when console input has been redirected from a file. Try Console.Read.

    My code and stuff:

    An image of my project structure:

    http://screencast.com/t/zVjqkmoED

    NOTE: I was duplicating the startup sequence in the TestHarness when in DEBUG mode. If/when I get this working I will be dropping that from the solution. The Library project is where the majority of my code lives.

    PROGRAM.CS

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ServiceProcess;
    using System.Text;
    using System.ComponentModel;
    using System.Configuration.Install;
    using System.Collections;
    using RivWorks.FeedHandler.Service;
    
    namespace RivWorks.FeedHandler
    {
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            static int Main(string[] args)
            {
                bool install = false, uninstall = false, console = false, rethrow = false;
    
                try
                {
                    foreach (string arg in args)
                    {
                        switch (arg)
                        {
                            case "-i":
                            case "-install":
                                install = true; break;
                            case "-u":
                            case "-uninstall":
                                uninstall = true; break;
                            case "-c":
                            case "-console":
                                console = true; break;
                            default:
                                Console.Error.WriteLine("Argument not expected: " + arg);
                                break;
                        }
                    }
                    if (uninstall)
                    {
                        Install(true, args);
                    }
                    if (install)
                    {
                        Install(false, args);
                    }
                    if (console)
                    {
                        Console.WriteLine("Starting...");
                        FeedListener fl = new FeedListener();
                        fl.StartUp();
                        Console.WriteLine("System running; press any key to stop");
                        Console.ReadKey(true);
                        fl.ShutDown();
                        Console.WriteLine("System stopped");
                    }
                    else if (!(install || uninstall))
                    {
                        rethrow = true; // so that windows sees error...
                        ServiceBase[] services = { new Service.FeedListener() };
                        ServiceBase.Run(services);
                        rethrow = false;
                    }
                    return 0;
                }
                catch (Exception ex)
                {
                    if (rethrow) throw;
                    Console.Error.WriteLine(ex.Message);
                    return -1;
                }
            }
            static void Install(bool undo, string[] args)
            {
                try
                {
                    Console.WriteLine(undo ? "uninstalling" : "installing");
                    using (AssemblyInstaller inst = new AssemblyInstaller(typeof(Program).Assembly, args))
                    {
                        IDictionary state = new Hashtable();
                        inst.UseNewContext = true;
                        try
                        {
                            if (undo)
                            {
                                inst.Uninstall(state);
                            }
                            else
                            {
                                inst.Install(state);
                                inst.Commit(state);
                            }
                        }
                        catch
                        {
                            try
                            {
                                inst.Rollback(state);
                            }
                            catch { }
                            throw;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine(ex.Message);
                }
            }
        }
    
    
        [RunInstaller(true)]
        public sealed class MyServiceInstallerProcess : ServiceProcessInstaller
        {
            public MyServiceInstallerProcess()
            {
                this.Account = ServiceAccount.NetworkService;
            }
        }
    
        [RunInstaller(true)]
        public sealed class MyServiceInstaller : ServiceInstaller
        {
            public MyServiceInstaller()
            {
                this.Description = "Provides a service to listen for, then import, feed files from various sources.";
                this.DisplayName = "RIVWorks Feed Handler (.NET 4.0)";
                this.ServiceName = "FeedListener";
                this.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
            }
        }
    }
    

    FEEDLISTENER.CS

    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.IO;
    using sysIO = System.IO;
    using RivWorks.FeedHandler;
    using System.Collections;
    using RivWorks.FeedHandler.Library;
    using System.Threading;
    
    namespace RivWorks.FeedHandler.Service
    {
        public partial class FeedListener : ServiceBase
        {
            #region Declarations
            static private List<string> _keys = new List<string>();
            static private System.Threading.Timer _clock = null;
            static private FileSystemWatcher _watcher;
            static private RivWorks.FeedHandler.Library.QueueHandler _qHandler = null;
            static private bool _isDequeueing = false;
            #endregion
    
            #region Constructor
            public FeedListener()
            {
                InitializeComponent();
            }
            #endregion
    
            #region Internal Methods
            internal void StartUp() {...}
            internal void ShutDown() {...}
            #endregion
    
            #region Start/Stop
            protected override void OnStart(string[] args)
            {
                StartUp();
            }
            protected override void OnStop()
            {
                ShutDown();
            }
            #endregion
    
            #region Event Handlers
            static void qHandler_QueuesGrew() {...}
            static void qHandler_QueuesShrunk() {...}
            static void qHandler_QueuesChanged() {...}
            static void fileCreatedOrChanged(object sender, sysIO.FileSystemEventArgs e) {...}
            #endregion
    
            #region Private Methods
            private static void Tick(object state) {...}
            private static void WriteToEventLog(Exception ex, EventLogEntryType eventLogEntryType) {...}
            private static void WriteToEventLog(string message, EventLogEntryType eventLogEntryType) {...}
            #endregion
        }
    }
    
  • buddybubble
    buddybubble almost 9 years
    Seems to be down, do you have a copy?
  • Paul Mitchell
    Paul Mitchell almost 7 years
    This link actually takes you to a page of adverts for window installers.