I am making a service to put on my kid's computer, to make sure that they can't stop Qustodio, and they are quite tech-savvy. They know how to stop a service by going to Run >> services.msc, and I need to make the service NOT_STOPPABLE, like Kaspersky. But when I add the line: CanStop = false;, I can't start the service and it gives me an error. This is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
namespace MyFirstService
{
public partial class Service1 : ServiceBase
{
Timer timer = new Timer();
ServiceController qengine = new ServiceController("qengine");
protected override void OnStart(string[] args)
{
WriteToFile("Service is started at " + DateTime.Now);
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 5000; //number in milisecinds
timer.Enabled = true;
CanStop = false;
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
qengine.Start();
WriteToFile("qengine attemped start at: " + DateTime.Now);
}
public 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);
}
}
}
}
}
Related
So I created a service to run on a server and look at different folder shares and put them in a database table for a customized search but it pulls a datatable of search locations in and iterates through them one at a time which worked great with small test folders. Now that I tried to use it for real it does not make it through the first folder path before my timer restarts it. I could make it time longer but I basically want this to run constantly and start over as soon as the first one is done or not sure if I can run all paths at the same time. I had it running every 30 Minutes but definitely not long enough.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
namespace MFTSearchService
{
public partial class MFTSearchService : ServiceBase
{
Timer timer = new Timer(); // name space(using System.Timers;)
public MFTSearchService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
WriteToFile("Service is started at " + DateTime.Now);
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = TimeSpan.FromMinutes(10).TotalMilliseconds; //number in milisecinds
timer.Enabled = true;
//global::MFTSearchService.Search.SearchStart();
}
protected override void OnStop()
{
WriteToFile("Service is stopped at " + DateTime.Now);
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
WriteToFile("Service is recall at " + DateTime.Now);
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = TimeSpan.FromMinutes(30).TotalMilliseconds; //number in milisecinds
timer.Enabled = true;
global::MFTSearchService.Search.SearchStart();
}
public 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);
}
}
}
}
}
Instead of calling
global::MFTSearchService.Search.SearchStart();
in your timer, you can add a BackgroundWorker and start it in your timer. For every tick on your timer, you can check if Backgroundworker is busy or not. BackgroundWorker will not run until it's done if you check it before running it.
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
WriteToFile("Service is recall at " + DateTime.Now);
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = TimeSpan.FromMinutes(30).TotalMilliseconds; //number in milisecinds
timer.Enabled = true;
if (!backgroundWorker1.IsBusy())
{
backgroundWorker1.RunWorkerAsync();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
global::MFTSearchService.Search.SearchStart();
}
Background worker will not lock your main thread so your timer will continue looping. So you're free to put any interval to it.
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.
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)
Open run box (Win Flag + R)
Type Services.MSC
Locate your service and right click properties
Choose the logon tab
Enter your windows auth username and password for service to run as
Option 2: Create SQL Server account
Create username and password in SQL for database
Update connection string to specify new username and password created
I wrote a code to update DDNS which works fine. I now need to run this code every n minutes: how would I go doing that?
I tried using:
while (true)
{
this.DoMyMethod();
Thread.Sleep(TimeSpan.FromMinutes(1));
}
and I am still having some trouble. What is the best way to run this task every n minutes?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Windows.Forms;
using System.Timers;
namespace GoogleDDNS
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (username.Text == "")
{
System.Windows.MessageBox.Show("Please enter the username");
username.Focus();
return;
}
if (password.Text == "")
{
System.Windows.MessageBox.Show("Please enter the password");
password.Focus();
return;
}
if (subdomain.Text == "")
{
System.Windows.MessageBox.Show("Please enter the subdomain");
subdomain.Focus();
return;
}
var client = new WebClient { Credentials = new NetworkCredential(username.Text, password.Text) };
var response = client.DownloadString("https://domains.google.com/nic/update?hostname=" + subdomain.Text);
responseddns.Content = response;
Properties.Settings.Default.usernamesave = username.Text;
Properties.Settings.Default.passwordsave = password.Text;
Properties.Settings.Default.subdomainsave = subdomain.Text;
Properties.Settings.Default.Save();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
username.Text = Properties.Settings.Default.usernamesave;
password.Text = Properties.Settings.Default.passwordsave;
subdomain.Text = Properties.Settings.Default.subdomainsave;
}
}
}
Why not using System.Threading.Timer to do so?
From the Microsoft documentation, say you have the following sample class:
class StatusChecker
{
private int invokeCount;
private int maxCount;
public StatusChecker(int count)
{
invokeCount = 0;
maxCount = count;
}
// This method is called by the timer delegate.
public void CheckStatus(Object stateInfo)
{
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
Console.WriteLine("{0} Checking status {1,2}.",
DateTime.Now.ToString("h:mm:ss.fff"),
(++invokeCount).ToString());
if (invokeCount == maxCount)
{
// Reset the counter and signal the waiting thread.
invokeCount = 0;
autoEvent.Set();
}
}
}
Then you can create a Timer to run CheckStatus every n seconds, like:
// Create an AutoResetEvent to signal the timeout threshold in the
// timer callback has been reached.
var autoEvent = new AutoResetEvent(false);
var statusChecker = new StatusChecker(5);
// creates a Timer to call CheckStatus() with autoEvent as argument,
// starting with 1 second delay and calling every 2 seconds.
var stateTimer = new Timer(statusChecker.CheckStatus, autoEvent, 1000, 2000);
autoEvent.WaitOne();
i use timer,
the code is
using System;
using System.Net;
using System.Timers;
static void Main(string[] args)
{
Console.WriteLine("The system is start at {0}", DateTime.Now);
Timer t = new Timer(10000);
t.Enabled = true;
t.Elapsed += T_Elapsed;
Console.ReadKey();
}
private static void T_Elapsed(object sender, ElapsedEventArgs e)
{
//write your code
}
This is what fixed for me.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Windows.Forms;
using System.Timers;
namespace GoogleDDNS
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (username.Text == "")
{
System.Windows.MessageBox.Show("Please enter the username");
username.Focus();
return;
}
if (password.Text == "")
{
System.Windows.MessageBox.Show("Please enter the password");
password.Focus();
return;
}
if (subdomain.Text == "")
{
System.Windows.MessageBox.Show("Please enter the subdomain");
subdomain.Focus();
return;
}
var client = new WebClient { Credentials = new NetworkCredential(username.Text, password.Text) };
var response = client.DownloadString("https://domains.google.com/nic/update?hostname=" + subdomain.Text);
//MessageBox.Show(response);
responseddns.Content = response;
Properties.Settings.Default.usernamesave = username.Text;
Properties.Settings.Default.passwordsave = password.Text;
Properties.Settings.Default.subdomainsave = subdomain.Text;
//Properties.Settings.Default.intervalsave = interval.Text;
Properties.Settings.Default.Save();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
username.Text = Properties.Settings.Default.usernamesave;
password.Text = Properties.Settings.Default.passwordsave;
subdomain.Text = Properties.Settings.Default.subdomainsave;
//interval.Text = Properties.Settings.Default.intervalsave;
System.Windows.Forms.Timer MyTimer = new System.Windows.Forms.Timer();
MyTimer.Interval = (1 * 60 * 1000); // 45 mins
MyTimer.Tick += new EventHandler(MyTimer_Tick);
MyTimer.Start();
}
private void MyTimer_Tick(object sender, EventArgs e)
{
var client = new WebClient { Credentials = new NetworkCredential(username.Text, password.Text) };
var response = client.DownloadString("https://domains.google.com/nic/update?hostname=" + subdomain.Text);
//MessageBox.Show(response);
responseddns.Content = response;
//this.Close();
}
}
}
Have a look at this. I recall a colleague using it a while ago:
FluentScheduler - [Project Site]
Usage:
// Schedule an IJob to run at an interval
Schedule<MyJob>().ToRunNow().AndEvery(2).Minutes();
Will fulfill your need.
somwhere met this code
class Program
{
static void Main(string[] args)
{
int Interval = 5;
CancellationTokenSource cancellation = new CancellationTokenSource();
Console.WriteLine("Start Loop...");
RepeatActionEvery(() => Console.WriteLine("Hi time {0}",DateTime.Now), TimeSpan.FromMinutes(Interval), cancellation.Token).Wait();
Console.WriteLine("Finish loop!!!");
}
public static async Task RepeatActionEvery(Action action, TimeSpan interval, CancellationToken cancellationToken)
{
while (true)
{
action();
Task task = Task.Delay(interval, cancellationToken);
try
{
await task;
}
catch (TaskCanceledException)
{
return;
}
}
}
}
C# code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using NDde.Client;
namespace Test
{
public partial class Service1 : ServiceBase
{
System.Timers.Timer timeDelay;
int count;
public Service1()
{
InitializeComponent();
timeDelay = new System.Timers.Timer();
timeDelay.Elapsed += new System.Timers.ElapsedEventHandler(WorkProcess);
}
public void WorkProcess(object sender, System.Timers.ElapsedEventArgs e)
{
string process = "Timer Tick " + count;
LogService(process);
count++;
}
protected override void OnStart(string[] args)
{
LogService("Service is Started");
timeDelay.Enabled = true;
}
protected override void OnStop()
{
LogService("Service Stoped");
timeDelay.Enabled = false;
}
private void LogService(string content)
{
FileStream fs = new FileStream(#"C:\TestServiceLog.txt", FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
sw.BaseStream.Seek(0, SeekOrigin.End);
sw.WriteLine(content+this.GetFirefoxUrl());
sw.Flush();
sw.Close();
}
public string GetFirefoxUrl()
{
DdeClient dde = new DdeClient("Firefox", "WWW_GetWindowInfo");
dde.Connect();
string url = dde.Request("URL", int.MaxValue);
dde.Disconnect();
return url;
}
}
}
Hi, I have written the above code but I am unable to perform the task GetFirefoxUrl(). Its giving me the following error. How can I resolve this?
Service cannot be started. NDde.DdeException: The client failed to connect to "Firefox|WWW_GetWindowInfo". Make sure the server application is running and that it supports the specified service name and topic name pair. ---> NDde.Foundation.DdemlException: The client failed to connect to "Firefox|WWW_GetWindowInfo". Make sure the server application is running and that it supports the specified service name and topic name pair.
at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
at NDde.Advanced.DdeContext.DdeThread.Invoke(Delegate method, Object[] args)
at NDde.Client.DdeClient.Connect()
--- End of inner exception stack trace ---
at NDde.Client.DdeClient.Connect()
at Test.Service1.GetFirefoxUrl()
at Test.Service1.LogService(String content)
at Test.Service1.OnStart(String[] args)
at System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(Object state)
I have checked the other threads related to this none of them gave me a solution. I hope some one guide me to achieve this.
Need to zip text files from a predefined location & save the zipped files in another location of hard disk using windows services & delete the old text file (a scheduled service)
I tried the following code in which i used 'icsharpcode' for zipping the files. But after installing the service.. i am getting a message that "this services has started & then stopped..." without showing any required output.
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Diagnostics.Design;
using System.Diagnostics.Eventing;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.IO;
using System.Timers;
using ICSharpCode.SharpZipLib.Zip;
namespace createzip
{
public partial class createzip : ServiceBase
{
Timer timer1 = new Timer();
public createzip()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
timer1.Elapsed += new ElapsedEventHandler(onelapsedtime);
timer1.Enabled = true;
timer1.Interval = 60000;
}
protected override void OnStop()
{
timer1.Enabled = false;
}
private void onelapsedtime(object source, ElapsedEventArgs e)
{
string folder = "#E:\\zipped files";
Directory.SetCurrentDirectory(folder);
string output = "#E:\\output";
string outputfilename = Path.Combine(output, "this file is zipped");
using (var x = new ZipFile(output))
{
foreach (var f in Directory.GetFiles(folder))
x.Add(f);
}
string[] filenames = Directory.GetFiles(folder);
using ( ZipOutputStream s = new
ZipOutputStream(File.Create(output))) //(args[1])))
{
s.SetLevel(9);
byte[] buffer = new byte[4096];
foreach (string file in filenames)
{
ZipEntry entry = new ZipEntry(Path.GetDirectoryName(file));
//entry.DateTime = DateTime.Now;
s.PutNextEntry(entry);
using (FileStream fs = File.OpenRead(file))
{
int sourcebytes;
do
{
sourcebytes = fs.Read(buffer, 0, buffer.Length);
s.Write(buffer, 0, sourcebytes);
}
while (sourcebytes > 0);
}
}
s.Finish();
s.Close();
return;
}
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.IO;
using System.Timers;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
namespace trail2zip
{
public partial class trail2zip : ServiceBase
{
Timer timer;
string path1 = #"E:\zipped files\New Text Document.txt";
string path2 = #"E:\output\filezipname.zip";
string path3 = #"E:\zipped files\R_23122015.txt";
int timerInterval = 60000;
public trail2zip()
{
InitializeComponent();
timer = new Timer();
timer.Elapsed+=new ElapsedEventHandler(this.timer_Elapsed);
timer.Interval = timerInterval;
timer.Enabled = true;
}
protected override void OnStart(string[] args)
{
timer.Start();
}
protected override void OnStop()
{
timer.Stop();
timer.SynchronizingObject = null;
timer.Elapsed -= new ElapsedEventHandler(this.timer_Elapsed);
timer.Dispose();
timer = null;
}
public void timer_Elapsed(object sender, ElapsedEventArgs e)
{
ZipFile z = ZipFile.Create(path2); //(filezipname);
z.BeginUpdate();
z.Add(path1);
z.Add(path3);
z.CommitUpdate();
z.Close();
}
}
}