none
Code is not working in Windows Service but Working in WinForm RRS feed

  • Question

  • Hi,

    I have below code which is working perfectly in WinForm Button Click but when I put as Windows Service it was successfully installed and started but not working and not throwing any error.. in fact it's updating with 

    BlueFile Attendance Service is updating.

    every 10 minutes as per the interval set in my application which means from my understanding everything is fine but why no rows were updated?

    private void timerAttendance_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        eventLogAttendance.WriteEntry("BlueFile Attendance Service is updating.", EventLogEntryType.Information);
    
        sql_connection_attendance = new SqlConnection(serverClass.connectionstring("BlueFile", "BlueFile", "BioStarWindowsAuthentication"));
    
        // save the contact;
        sql_connection = new MySqlConnection(serverClass.connectionstring("BlueFile", "BlueFile", "Server"));
    
        try
        {
            sql_connection_attendance.Open();
            sql_connection.Open();
    
            sql_command_attendance = new SqlCommand("SELECT nReaderIdn AS device_id, nUserId AS employee_number, DATEADD(s, nDateTime, '1970-01-01') AS attendance FROM [BioStar].[dbo].[TB_EVENT_LOG] WHERE nEventIdn = 55;", sql_connection_attendance);
            sql_reader_attendance = sql_command_attendance.ExecuteReader();
    
            while (sql_reader_attendance.Read())
            {
                sql_command = new MySqlCommand("sp_update_employee_attendance", sql_connection);
                sql_command.CommandType = CommandType.StoredProcedure;
    
                sql_command.Parameters.AddWithValue("param_employee_number", Convert.ToInt32(sql_reader_attendance["employee_number"])).MySqlDbType = MySqlDbType.Int32;
                sql_command.Parameters.AddWithValue("param_device_id", Convert.ToString(sql_reader_attendance["device_id"])).MySqlDbType = MySqlDbType.VarChar;
                sql_command.Parameters.AddWithValue("param_attendance", Convert.ToDateTime(sql_reader_attendance["attendance"]).ToString("yyyy-MM-dd HH:mm:ss")).MySqlDbType = MySqlDbType.VarChar;
    
                int result_rows = sql_command.ExecuteNonQuery();
            }
    
            eventLogAttendance.WriteEntry("BlueFile Attendance Service update completed", EventLogEntryType.Information);
        }
        catch (Exception exp)
        {
            eventLogAttendance.WriteEntry("Failed. ERROR: " + exp.Message, EventLogEntryType.Error);
        }
        finally
        {
            if (sql_reader != null) { sql_reader.Close(); sql_reader.Dispose(); }
            if (sql_connection != null) { if (sql_connection.State == ConnectionState.Open) { sql_connection.Close(); sql_connection.Dispose(); } }
    
            if (sql_reader_attendance != null) { sql_reader_attendance.Close(); sql_reader_attendance.Dispose(); }
            if (sql_connection_attendance != null) { if (sql_connection_attendance.State == ConnectionState.Open) { sql_connection_attendance.Close(); sql_connection_attendance.Dispose(); } }
        }
    }
    

    Thanks,

    Jassim

    Thursday, January 14, 2016 9:44 AM

Answers

  • Thanks Guys,

    My issue is resolved. It was related to login and I used SQL authentication.

    I have two more questions please..

    1. Why authentication was failed but no log in the event log?
    2. What do you mean guys by not using timer in windows service? what if I want to make the application as windows service and make it to perform an action every 15 minutes or 30 minutes?

    Thanks,

    Jassim

    Wednesday, January 20, 2016 8:09 PM
  • 1) Because the structure of your code is not optimal. But I already said that.

    2) It is simpler to write a console application and use Scheduled Tasks. Why? Because, when you follow a clean code (OOP) approach for developing a service, a console application is a free side-product. So the question is why going further for simple scheduling? Scheduled Tasks implement everything you need. Especially all the security (AD) relevant stuff. And security is always hard to get right.

    For example, you need to communicate with your service to change (maybe even add or remove) jobs. Do you want to do this via a REST API, some IPC like named pipes or have you considered restarting the service when the configuration changes? All approaches have pros and cons and after all some risks, but all require some implementation.

    Thursday, January 21, 2016 9:21 AM

All replies

  • Don't use timers in services. It's imho a bad practice.

    I'm using wait for multiple objects and a time out or a sleeping thread.

    Also decouple your code. It mixes the (business) logic with the UI/service code. Your timer elapsed event should call a single method to execute your code.

    Instead of using finally use the using statement for all classes implementing IDisposable.

    Also updating one row after another is slow. Use a temporary or staging table to do a bulk insert, then call on stored procedure, which does the entire update. This reduces the server round-trips drastically.

    Don't catch generic exception in the logic code part. Do this only on the top-level of your service to keep it stable.

    Thursday, January 14, 2016 9:56 AM
  • Add some more logging and clarify if your SELECT returns any data. Is ExecuteNonQuery executed successfully?

    Are you perhaps using “Windows Authentication” mode to access the database? Probably you will have to consider the authentication based on explicit username and password. (You will need to create new database users having appropriate access rights).



    • Edited by Viorel_MVP Thursday, January 14, 2016 1:08 PM
    Thursday, January 14, 2016 1:06 PM
  • My SELECT for sure returns rows because the same code works fine when I use on WinForm. Also the timer is working and I am getting the log every 10 minutes
    Thursday, January 14, 2016 3:13 PM
  • is it necessary to use user ID and password? but whole windows is using Windows Authentication by defaults. I don't mind using it but only if it's must
    Thursday, January 14, 2016 3:14 PM
  • one thing I forgot to mention.. This line:

    eventLogAttendance.WriteEntry("BlueFile Attendance Service update completed", EventLogEntryType.Information);

    is never logged in my event log! why?!


    Thursday, January 14, 2016 3:31 PM
  • It's about OOP, clean code and the SOLID principles...

    btw, I think Viorel is right. Windows Authentication could be the problem. Because you normally run a service under a different account. Which is normally not configured for SQL access.

     
    Thursday, January 14, 2016 6:57 PM
  • I tried with servre authenitication but it's still the same, working perfectly on WinForm but in Windows Service, it's just running with no error and no result as well.

    This is my event log for the windows service:

    http://www.jassimrahma.com/temp/eventlog.png

    all are updating.. event but no completed nor error. I am not sure why?!

    Monday, January 18, 2016 3:33 PM
  • Hi Jassim,

    >>one thing I forgot to mention.. This line:

    eventLogAttendance.WriteEntry("BlueFile Attendance Service update completed", EventLogEntryType.Information);

    is never logged in my event log! why?!

    I suspect that your service start as an abnormal state or something wrong with your logic.

    The timer approach is the most common method and is probably the simplest to write and understand. You create a timer in the OnStart event and attach your worker function to the timer. For more details,  please have a look at the first sample that marked  as an answer 

    Windows service with timer

    Here is also a thread that tells you how to use a timer in windows service

    I think the other way is try to debug on your windows service.

    Please refer to the following bolgs that could help you.

    http://blogs.msdn.com/b/field_notes/archive/2008/07/21/how-to-debug-windows-service-onstart.aspx

    http://blogs.msdn.com/b/yaleeyangmsblog/archive/2007/05/02/three-ways-debugging-net-windows-service.aspx

    http://blog.bitcollectors.com/adam/2014/09/debugging-windows-service-projects-c/Good luck!

    Kristin


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    • Edited by Kristin Xie Wednesday, January 20, 2016 8:24 AM
    Wednesday, January 20, 2016 8:23 AM
  • The timer approach is the most common method and is probably the simplest to write and understand.

    I slightly disagree. 90% of the code, I've seen, using timers in services were reinvented versions of scheduled tasks.

    Also in the OP's use-case I would prefer a console application to do the task. Benefit: I can start the task anytime I want, without reprogramming the service.

    Wednesday, January 20, 2016 11:39 AM
  • I suggest you write a quick log to a file (and try to log something after each line), the only thing from the presented code that could go wrong here seems to be the initiation of the Connection. I dont see a try catch around them and those are the only lines which could cause an exception before your next log (since of the "greedy"-catch caluse).

    You could also try to use the "AttatchToProcess" from the "Debug" menu (in VisualStudio) and select the file your service is running. You should be able to debug it right there step by step.

    hope it helps


    Please be so kind to close your Threads when you found an answer, these Threads should help everyone with similar issues.
    You can close a Thread via the"Mark as Answer" link below posts. You can mark your own posts as answers if you were not helped out but found a solution, in such a case, please provide the answer.
    Happy coding
    PS: I assure everyone that I did not ever had the desire to offend anyone.


    • Edited by MDeero Wednesday, January 20, 2016 2:52 PM
    Wednesday, January 20, 2016 2:51 PM
  • I disagree.

    The first step would be refactoring the code to get a clean separation of logic and service code.

    Cause you need to levels of logging: messages from the service about its state or health and messages from the logic itself.

    But in the current state, there is everything cluttered in one method instead of a separate logic class.

    Wednesday, January 20, 2016 3:02 PM
  • Hi Jassim,

    could you move the first EventLogWriteEntry underneath the sqlConnection.Open call and check if this part of the codes actually gets invoked? Maybe something is blocking the execution due to too high timeout settings when opening a new connection, etc..

    Please also make sure not to use global fields or properties within the timerAttendance_Elapsed eventhandler. I am not to sure about the actual Timer implementation, but i guess each eventhandler invocation will take place in a seperate thread and this could cause havoc if one event handling takes longer than the defined Timer.Interval.

    Mark



    • Edited by M.Roach Wednesday, January 20, 2016 4:30 PM
    Wednesday, January 20, 2016 4:28 PM
  • Thanks Guys,

    My issue is resolved. It was related to login and I used SQL authentication.

    I have two more questions please..

    1. Why authentication was failed but no log in the event log?
    2. What do you mean guys by not using timer in windows service? what if I want to make the application as windows service and make it to perform an action every 15 minutes or 30 minutes?

    Thanks,

    Jassim

    Wednesday, January 20, 2016 8:09 PM
  • 1) Because the structure of your code is not optimal. But I already said that.

    2) It is simpler to write a console application and use Scheduled Tasks. Why? Because, when you follow a clean code (OOP) approach for developing a service, a console application is a free side-product. So the question is why going further for simple scheduling? Scheduled Tasks implement everything you need. Especially all the security (AD) relevant stuff. And security is always hard to get right.

    For example, you need to communicate with your service to change (maybe even add or remove) jobs. Do you want to do this via a REST API, some IPC like named pipes or have you considered restarting the service when the configuration changes? All approaches have pros and cons and after all some risks, but all require some implementation.

    Thursday, January 21, 2016 9:21 AM