Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running a Windows Service in Console mode?

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     } } 
like image 470
Keith Barrows Avatar asked May 19 '11 21:05

Keith Barrows


People also ask

How do I run a Windows service in Debug mode?

In the Application tab of the project's properties, set the Output type to Console Application. Choose Start Debugging (F5). To run the program as a Windows Service again, install it and start it as usual for a Windows Service.


2 Answers

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

like image 148
Keith Barrows Avatar answered Sep 24 '22 00:09

Keith Barrows


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.

like image 37
Yogev Smila Avatar answered Sep 20 '22 00:09

Yogev Smila