13 Replies - 765 Views - Last Post: 21 December 2016 - 07:58 AM Rate Topic: -----

#1 jcborland   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 116
  • Joined: 16-December 13

Writing a Windows Service.

Posted 20 December 2016 - 04:01 AM

Hi,
Can anyone help me with writing a Windows Service in C#. I have something I need to run in the background. I've got it working in a console program which is just scheduled to start when the PC turns on and it works OK but occasionally it gives a bit of grief. So I thought a Windows Server might me better.

I have the Windows Service written and it starts and stops properly, I can see that from the event log, but it doesn't run the code I want it to. In debug mode the code is run but not when the service runs live.

Here's what I have :

JBSSService.cs

namespace JBSS_CSVtoSQL
{
    public partial class JBSSService : ServiceBase
    {
        public JBSSService()
        {
            InitializeComponent();
            eventLog1 = new System.Diagnostics.EventLog();
            if (!System.Diagnostics.EventLog.SourceExists("JBSSService"))
            {
                System.Diagnostics.EventLog.CreateEventSource("JBSSService", "Application");
            }
            eventLog1.Source = "JBSSService";
            eventLog1.Log = "Application";


        }
        protected override void onstart(string[] args)
        {
            eventLog1.WriteEntry("Starting JBSS Service Now", EventLogEntryType.Information, 1001);
        }

        protected override void onstop()
        {
            eventLog1.WriteEntry("Stopping JBSS Service Now", EventLogEntryType.Information, 1001);
        }

        protected override void onpause()
        {
            eventLog1.WriteEntry("Pausing JBSS Service Now", EventLogEntryType.Information, 1001);
        }

        protected override void OnContinue()
        {
            eventLog1.WriteEntry("Continuing JBSS Service Now", EventLogEntryType.Information, 1001);
        }

        protected override void OnShutdown()
        {
            eventLog1.WriteEntry("Shutting down JBSS Service Now", EventLogEntryType.Information, 1001);
        }
    }
}



The above does run.

Then :

Program.cs

static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new JBSSService()
            };
            ServiceBase.Run(ServicesToRun);

            string textLine = "";
            string sqlConnectionString = "";
            string dataPath = "";
            string queryPath = "";
            string csvFilesPath = "";
            DateTime now;
            int hour;

            do
            {
                now = DateTime.Now;
                hour = now.Hour;

                textLine = "Started processing .csv files @ " + now;
                update_Progress(textLine, dataPath);

                ProcessCSVFiles(sqlConnectionString, dataPath, queryPath, csvFilesPath);

                now = DateTime.Now;

                textLine = "Finished processing .csv files @ " + now;
                update_Progress(textLine, dataPath);

                //
                //Print counter sales documents if any exist
                //

                PrintCounterSalesDocuments(sqlConnectionString, queryPath, dataPath);

                System.Threading.Thread.Sleep(2000);            //Sleep for 2 seconds.

            }
            while (hour > 7 && hour < 19);
        }



This part doesn't seem to run!

Can anyone offer some advice?

Thanks in advance.

Regards,
Jim.

Is This A Good Question/Topic? 0
  • +

Replies To: Writing a Windows Service.

#2 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6289
  • View blog
  • Posts: 21,610
  • Joined: 05-May 12

Re: Writing a Windows Service.

Posted 20 December 2016 - 05:30 AM

Your onstart() does nothing but just write to the event log. You need to start the process of scheduling the work to be done by your service at that point.

Main() is not executed in a service.
Was This Post Helpful? 0
  • +
  • -

#3 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6289
  • View blog
  • Posts: 21,610
  • Joined: 05-May 12

Re: Writing a Windows Service.

Posted 20 December 2016 - 05:55 AM

This may give you a boost forward:
Writing a Useful Windows Service in .NET in Five Minutes [Dave Fetterman]
Was This Post Helpful? 0
  • +
  • -

#4 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6289
  • View blog
  • Posts: 21,610
  • Joined: 05-May 12

Re: Writing a Windows Service.

Posted 20 December 2016 - 06:02 AM

View PostSkydiver, on 20 December 2016 - 07:30 AM, said:

Main() is not executed in a service.


Let me amend this. Main() should just be used to call ServiceBase.Run() and any one time configuration. Treat the onstart() as your real entry point.
Was This Post Helpful? 0
  • +
  • -

#5 jcborland   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 116
  • Joined: 16-December 13

Re: Writing a Windows Service.

Posted 20 December 2016 - 09:46 AM

Hi Skydiver,
Thanks I've got a service running and doing something.

Is debugging a service a bit of an art?

I found some instruction on debugging.
I've:
Started the service.
Chosen Attach to process from the debug menu.
My service shows twice, one of them greyed out, I attached to LOCAL SERVICE one.
I have hit a break point but as I'm stepping through the code it's jumping about. Kind of what I'd expect if the service is running the background but not stopping in a traditional debug mode and not much use for debugging purposes.

Am I missing something?

Thanks,
Jim.
Was This Post Helpful? 0
  • +
  • -

#6 jcborland   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 116
  • Joined: 16-December 13

Re: Writing a Windows Service.

Posted 20 December 2016 - 09:52 AM

I've found something about DebugMode / Debugger.Break()

So I'm just checking that now.
Was This Post Helpful? 0
  • +
  • -

#7 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6289
  • View blog
  • Posts: 21,610
  • Joined: 05-May 12

Re: Writing a Windows Service.

Posted 20 December 2016 - 10:03 AM

If your service is meant to run multiple threads, you'll want to freeze all the threads and only debug one thread at a time.

In general, having a good logging library helps, but even better is if you adhered strictly to TDD. With TDD you would have written tons of unit tests, and so normally when you start doing the integration tests and things start failing, you simply look at the logs to see what parameters are getting passed around. You then create another unit test to recreate the scenario using mocks with those values and you can debug that to your hearts content, and you get the bonus of having a ready may automated regression test created as a by product once you fix things.
Was This Post Helpful? 0
  • +
  • -

#8 jcborland   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 116
  • Joined: 16-December 13

Re: Writing a Windows Service.

Posted 20 December 2016 - 10:24 AM

Hi,
DebugMode didn't work for me. I've also tried Debugger.Launch() in the onstart and it worked to a degree but only in the onstart method. I couldn't get to any other code.

Is there something else I should try?

Regards,
Jim.
Was This Post Helpful? 0
  • +
  • -

#9 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6289
  • View blog
  • Posts: 21,610
  • Joined: 05-May 12

Re: Writing a Windows Service.

Posted 20 December 2016 - 11:59 AM

Once you've got the debugger attached (either through Debugger.Launch() or by attaching with VS), then set breakpoints on the methods that you are interested in.

Can you post your updated code? Presumably you followed the advice given in the link I posted above and move line 15-47 out into its own class that you instantiate and hookup in your onstart().
Was This Post Helpful? 0
  • +
  • -

#10 jcborland   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 116
  • Joined: 16-December 13

Re: Writing a Windows Service.

Posted 21 December 2016 - 03:28 AM

Hi Skydiver,
I've got it to work now doing something very simple. The debugging works to a degree also in that the source code does load up in VS and it does stop on break points. It's just that as I step through it doesn't step to the correct line on each step. It kinda jumps around in the rough vacinity. If I was doing something complex it would be no use. Well it is no use really.
I think I'm going to try and use the service just to call a standard program that way I can debug more effectively.

Here is the ammended code :
private void myEvent(object source,ElapsedEventArgs e)
        {
            //DebugMode();
            
            DateTime now;
            now = DateTime.Now;
            int hour = now.Hour;
            
            for (int i = 0; i < 10; i++)

            {
                using (StreamWriter sw = new StreamWriter("C:\\JBSoft\\log.txt", true))
                {

                    sw.WriteLine("Written by the JBSS Service. Count = {0}. The date & time is : {1}", i, now);

                }
            }
           // System.Threading.Thread.Sleep(10000);            //Sleep for 10 seconds.
            
        }
        //private static void DebugMode()
        //{
        //    Debugger.Break();
        //}

        protected override void onstart(string[] args)
        {
            
            eventLog1.WriteEntry("Starting JBSS Service Now", EventLogEntryType.Information, 1001);

            Debugger.Launch();
            Timer myTimer = new Timer();
            myTimer.Elapsed += new ElapsedEventHandler(myEvent);
            myTimer.Interval = 10000;
            myTimer.Enabled = true;

        }



Thanks,
Jim.
Was This Post Helpful? 0
  • +
  • -

#11 jcborland   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 116
  • Joined: 16-December 13

Re: Writing a Windows Service.

Posted 21 December 2016 - 03:45 AM

Hi Skydiver,
I think I've got it sorted. I think the problem was that I was running "myEvent" every 10 seconds and what was happening was that in the middle on me debugging one instance of "myEvent" a new one was started (after 10 seconds) then my debugger jumped to the start of "myEvent" again.

It actually debugs fine now.

Thanks again for your time.

Regards,
Jim.
Was This Post Helpful? 0
  • +
  • -

#12 jcborland   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 116
  • Joined: 16-December 13

Re: Writing a Windows Service.

Posted 21 December 2016 - 05:23 AM

Skydiver,

I'm using a timer to fire my event every so many seconds. Which is fine except when I want to debug. So I've called the event without the timer so it just runs once. It's not very elegant looking is there a proper way to do it?

So the time event is called thus :
            //Run the event every 10 seconds using a timer.
            Timer myTimer = new Timer();
            myTimer.Elapsed += new ElapsedEventHandler(myEvent);
            myTimer.Interval = 10000;
            myTimer.Enabled = true;


The one off event, which is easier to debug, is call thus :
            //Run the event once without a timer.
            Object source = null;
            ElapsedEventArgs e = null;

            myEvent(source, e);


And I've just added a bit of code in the event itself just to prove to myself that it works.
        private void myEvent(object source,ElapsedEventArgs e)
       
        {
            //DebugMode();
            string textLine = "Timer";
            if (e == null)
            {
                textLine = "No Timer";
            }
            DateTime now;
            now = DateTime.Now;
            int hour = now.Hour;
            
            for (int i = 0; i < 10; i++)

            {
                using (StreamWriter sw = new StreamWriter("C:\\JBSoft\\log.txt", true))
                {

                    sw.WriteLine("Written by the JBSS Service using {2}. Count = {0}. The date & time is : {1}", i, now,textLine);

                }
            }
           
        }


Was This Post Helpful? 0
  • +
  • -

#13 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6289
  • View blog
  • Posts: 21,610
  • Joined: 05-May 12

Re: Writing a Windows Service.

Posted 21 December 2016 - 06:35 AM

Based on your original code, it seems like wanted to do your work every N seconds after the last run, not necessarily every N seconds even if there is one in flight. There's several ways to achieve this:
  • Use a timer. Disable the timer while processing.
  • Create a thread in onstart() and in that thread have that same loop as your original code.
  • Use Task.Run() and Task.Delay().

Was This Post Helpful? 1
  • +
  • -

#14 jcborland   User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 116
  • Joined: 16-December 13

Re: Writing a Windows Service.

Posted 21 December 2016 - 07:58 AM

Hi Skydriver,
Thanks for the help.

I set the myTimer.AutoReset = false so it only fires once.

Then in the event I either do myTimer.Stop() or myTimer.Enable = false (don't know if it matters which!)

Process my stuff.....

Then still in the event I either do myTimer.Start() or myTimer.Enable = true

It works a treat.

Regards,
Jim.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1