1

I have managed to get the Service working, along with the FileSystemEventHandler inserting into a text file, but this now needs to be changed to insert into a database and a text file.

using System;  
using System.Collections.Generic;  
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;  
using System.IO;  
using System.Linq;  
using System.ServiceProcess;  
using System.Text;  
using System.Threading.Tasks;  
using System.Timers;  
namespace WindowsServiceTest
{
    public partial class Service1 : ServiceBase
    {
        Timer timer = new Timer(); // name space(using System.Timers;)  
        public static string path = ConfigurationManager.AppSettings["findpath"];
        public Service1()
        {
            InitializeComponent();
        } 

        protected override void OnStart(string[] args)
        {
            WriteToFile("Service is started at " + DateTime.Now);
            timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
            timer.Interval = 10000; //number in milisecinds  
            timer.Enabled = true;
            FileSystemWatcher watcher = new FileSystemWatcher
            {
                Path = path,
                NotifyFilter = NotifyFilters.LastWrite,
            };
            watcher.Created += new FileSystemEventHandler(FileSystemWatcher_Changed);
            watcher.Renamed += new RenamedEventHandler(FileSystemWatcher_Renamed);
            watcher.Changed += new FileSystemEventHandler(FileSystemWatcher_Changed);
            watcher.EnableRaisingEvents = true;
        }

        public static void FileSystemWatcher_Changed(object source, FileSystemEventArgs e)
        {
            using (SqlConnection con = new SqlConnection("Data Source=localhost\\SQLEXPRESS;Database=ServiceTest;Integrated Security=True;"))
            {
                try
                {
                    con.Open();
                    var command = new SqlCommand("Insert into test(URL, Location) values(@URL, @agendaname);", con);
                    command.Parameters.Add("@URL", System.Data.SqlDbType.VarChar, 100).Value = e.Name;
                    command.Parameters.Add("@agendaname", System.Data.SqlDbType.VarChar, 100).Value = "Case History";
                    command.ExecuteNonQuery();
                }
                catch
                {
                    WriteToFile($"Failed to insert: {e.Name} into the database");
                }
            }
        }
        public static void FileSystemWatcher_Renamed(object source, RenamedEventArgs e)
        {
            WriteToFile($"File Renamed: {e.OldFullPath} renamed to {e.FullPath}");
        }
        private void OnElapsedTime(object source, ElapsedEventArgs e)
        {
            WriteToFile("Service is recalled at " + DateTime.Now);
        }
        protected override void OnStop()
        {

            WriteToFile("Service is stopped at " + DateTime.Now);
        }

        public static void WriteToFile(string Message)
        {
            string path = AppDomain.CurrentDomain.BaseDirectory + "\\Logs";
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            string filepath = AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\ServiceLog_" + DateTime.Now.Date.ToShortDateString().Replace('/', '_') + ".txt";
            if (!File.Exists(filepath))
            {
                // Create a file to write to.   
                using (StreamWriter sw = File.CreateText(filepath))
                {
                    sw.WriteLine(Message);
                }
            }
            else
            {
                using (StreamWriter sw = File.AppendText(filepath))
                {
                    sw.WriteLine(Message);
                }
            }
        }
    }
}

I think that I've done the database insert wrong because the catch block is being inserted into the text file. However, I've run the code by itself in a separate project and was inserting into the database in a Console Application.

Any help is appreciated, kind regards.

Adam
  • 62
  • 6
  • change your catch to catch(Exception ex) and then WriteToFile the exception (the ex variable in your catch block) – Daniel Feb 26 '19 at 13:27
  • @Daniel Thanks - Error message is coming up as: Cannot open database "dbname" requested by the login. The login failed. - I know this seems like quite straight forward, but in my console app I was using the exact code and it was doing it. Any ideas what I need to change? – Adam Feb 26 '19 at 13:32
  • Great! so the culprit is your connection string. Are you maybe pulling this from another location in your console app, maybe the app config? – Daniel Feb 26 '19 at 13:34
  • Nope, I want to change it to that way after I get it working though. Issue is definitely with the connection string, getting this error for the connection string showed in the code above: System.Data.SqlClient.SqlException (0x80131904), did a quick Google and tried one of the solutions but then I got this error: System.Data.SqlClient.SqlException (0x80131904) – Adam Feb 26 '19 at 13:43
  • You're using your windows credentials to authenticate with the sql server "IntegratedSecurity=true" the windows service is likely running under a service account. In services.msc you can right click your service and choose the logon tab to run as your local user and you should be able to authenticate with the sql server. That's why it works in console app but fails in win service. Or simply create a user account in sql and use that in your connection string rather than integrated security. – Daniel Feb 26 '19 at 13:47
  • Made it run from my local account in Services and fixed the issue, thank you so much for the quick responses! – Adam Feb 26 '19 at 13:53

1 Answers1

0

Windows services run under a different security context than console apps. As the comments have disclosed, the exception is related to your connection string. If we analyze the connectiong string we can see that you are authenticating with IntegratedSecurity="True". Because your windows service is running under a service account authentication is failing. I've specified 2 options for resolving this.

Option 1: Have Service run as windows account (Not recommended but will work for testing)

  1. Open run box (Win Flag + R)
  2. Type Services.MSC
  3. Locate your service and right click properties
  4. Choose the logon tab
  5. Enter your windows auth username and password for service to run as

Option 2: Create SQL Server account

  1. Create username and password in SQL for database
  2. Update connection string to specify new username and password created
Daniel
  • 976
  • 5
  • 14