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:
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:
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 } }
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.
And I found my answer! My project properties were set to Windows App instead of Console App. DOH! (Project Properties > Application Tab > Output type:)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With