How to debug OnStop in Windows Service - c#

I have written that is attaching the adding the new task schedular. The code able to register task scheduler on Onstart and the code is working perfectly and able to debug the code. But i want to do some task onStop but i am not able to debug. What is the option and what i need to do to debug the onStop code. Because when i press stop button in visual studio the program stop but not onStop code part can debug.
protected override void OnStart(string[] args)
{
// System.Diagnostics.Debugger.Launch();
try
{
// Other code where i am able to debug
}
catch (Exception ie)
{
StreamWriter sw;
sw = File.AppendText("D:\\DvrService.txt");
sw.WriteLine(ie.Message);
sw.Close();
}
}
protected override void OnStop()
{
try
{
System.Diagnostics.Debugger.Launch();
foreach (string key in System.Configuration.ConfigurationManager.AppSettings)
{
var chromeDriverProcesses = Process.GetProcesses().Where(pr => pr.ProcessName == key.ToUpper()); // without '.exe'
foreach (var process in chromeDriverProcesses)
{
process.Kill();
StreamWriter sw;
sw = File.AppendText("E:\\DvrService.txt");
sw.WriteLine("Trying to kill Service" + key);
sw.Close();
}
}
}
catch (Exception ex)
{
//TODO: Log this error
StreamWriter sw;
sw = File.AppendText("E:\\DvrService.txt");
sw.WriteLine("Trying to kill Service");
sw.Close();
}
}
Program.CS
static void Main()
{
#if DEBUG
Service1 myService = new Service1();
myService.onDebug();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
#endif
}

Pressing the "Stop" button in Visual Studio is not the same as stopping a Windows Service.
If you want to debug OnStop in a Windows Service you have to register the service and have Windows start the service (via GUI or command line). When you register the service make sure that you are pointing to the debug build.
Then, in Visual Studio, attach to the running process, set a breakpoint in OnStop and then, use the GUI or command line to stop the service.

Related

C#: Windows Console Application to Windows Service

I have a console application that tracks the performance of the computer, and I am trying to make it into a Windows Service. The service installs fine, however when I go into task manager and try to run the service I get Error 1053: the service did not respond to the start or control request in a timely fashion. In the task manager the service sometimes has a "starting" status, but it will not run.
On top of that, when I run the console app, I also get an error stating that: Cannot start service from the command line or a debugger. A windows service must first be installed - which I have done.
This is my program class:
public static string ServiceName = "performanceService";
static void Main(string[] args)
{
if (!Environment.UserInteractive)
{
PerformanceCounter ramCount = new PerformanceCounter("Memory", "Available MBytes");
PerformanceCounter cpuCount = new PerformanceCounter("Processor", "% Processor Time", "_Total");
Console.WriteLine("Press any key to view other information...\n");
Console.WriteLine("CPU and RAM information");
while (!Console.KeyAvailable)
{
double perf = cpuCount.NextValue();
Console.WriteLine("CPU Performance: " + perf + " %");
... Code continues on that calculates the performance and displays it in the console...
}
else
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new ServiceControl()
};
ServiceBase.Run(ServicesToRun);
}
}
This is my ServiceControl class:
public ServiceControl()
{
ServiceName = Program.ServiceName;
InitializeComponent();
}
public void Start()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
base.OnStart(args);
}
protected override void OnStop()
{
base.OnStop();
}
private void InitializeComponent()
{
//
// ServiceControl
//
this.ServiceName = "performanceService";
}
To install the service I have used both the Project Installer and manual install, just out of curiosity to be honest.
I changed the time limit through regedit, and that did not help.
Please let me know if you need to see additional code.
My question is, am I missing something from the code, that will not allow my service to start?
Thanks for your help.
Thank you for all your help.
The problem was that I had the Start() method in the ServiceControl class and I had my code the other way around in the Program class.
I was supposed to have the code to start the service in the if statement and the performance logic in the else, so that the start method executes quickly, like one of the comments suggested. After clicking start on the service in the task manager, the status changes to "running".
Thank you again.

Self-Hosted SignalR service won't work (start)

I have SignalR server as Class Library Project and i referenced it in Console application (to simulate Windows service)
Here is code for SignalR
public void Start()
{
try
{
string url = #"http://*:8081";
using (WebApp.Start<Startup>(url))
{
Logger.Info(string.Format("Server running at {0}", url));
}
}
catch (Exception ex)
{
Logger.Exception(ex, "Signalr start");
}
Run = true;
Logger.Info("Starting Worker");
workerThread = new Thread(() =>
{
Worker();
});
workerThread.Start();
}
And here is Startup class
public class Startup
{
Microsoft.AspNet.SignalR.HubConfiguration hubconfiguration = null;
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
hubconfiguration = new HubConfiguration();
hubconfiguration.EnableDetailedErrors = true;
app.MapSignalR(hubconfiguration);
}
}
So, it is in one thread, and worker is in another. That seems fine since i did it in other project where it works. Worker thread isn't problem, it's just empty loop, not related to server in any way.
Problem is that server seems to "stop" - when i look with Netstat, nobody is listening on port 8081. There is no exception, it just silently fails.
I referenced Owin.Cors (and Owin.Host.HttpListener) in console project that actually runs this server but as I said, server just stops.
When I try to connect, client says "connection actively refused" and Putty (telnet) also says "can't connect".
Where is the problem? In a nutshell, i have Class Library with SignalR server that is referenced in Console project that runs it but server just wont work.
[edit]
And there is code of Console app that starts service
static void Main(string[] args)
{
ServiceEngine Engine = new ServiceEngine();
Engine.Start();
Console.ReadKey();
Engine.Stop();
}
P.S. Sorry for my bad English.
Well, i solved it. Here was a problem:
public static void Start()
{
try
{
string url = #"http://127.0.0.1:8081";
WebApp.Start<Startup>(url);
Logger.Info(string.Format("Server running at {0}", url));
}
catch (Exception ex)
{
Logger.Exception(ex, "signalr start");
}
Run = true;
Logger.Info("Starting Worker");
workerThread = new Thread(() =>
{
Worker();
});
workerThread.Start();
}
As you can see, using statement was removed and now it works fine! Interesting note - you can also make Singleton implementation of this "Engine", and it will also work.
I got Solution after doing lot of R & D. And Its a Simple change related to Account and Access Rights.
Use LocalSystem Account instead of LocalService Account in Service Installer.
You can do this either from doing below change in design view of your service installer:
Properties of Service Process Installer -> Set Account to LocalSystem.
or by doing below change in in designer.cs file of your service installer:
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;

C# Windows Service -- the service on local computer started and then stopped?

I am trying to create my first Windows Service, but so sad... after I started the service manually from services.msc, the message 'the service on local computer started and then stopped. some services stop automatically is they have no work to do'
I am sure there must be some mistake in my code...
namespace ConvertService
{
public partial class Service1 : ServiceBase
{
public Service1()
{
this.ServiceName = "ConvertService";
this.EventLog.Log = "Application";
}
static void main()
{
ServiceBase.Run(new Service1());
}
protected override void OnStart(string[] args)
{
Process pMP3 = new Process();
pMP3.StartInfo.UseShellExecute = false;
pMP3.StartInfo.RedirectStandardOutput = true;
pMP3.StartInfo.FileName = #"d:\...path...\converter.exe";
pMP3.StartInfo.Arguments = #"d:\...path...\tempamr.amr " + #"d:\...path...\tempmp3.mp3 " + #"-cmp3";
pMP3.Start();
pMP3.WaitForExit();
Process pWAV = new Process();
pWAV.StartInfo.UseShellExecute = false;
pWAV.StartInfo.RedirectStandardOutput = true;
pWAV.StartInfo.FileName = #"d:\...path...\converter.exe";
pWAV.StartInfo.Arguments = #"d:\...path...\tempmp3.mp3 " + #"d:\...path...\tempwav.wav " + #"-cwav";
pWAV.Start();
pWAV.WaitForExit();
}
protected override void OnStop()
{
}
}
}
Forgive me if i did silly mistakes. This is my very very first Windows Service.
PS. I have already ticked 'Allow service to interact with desktop'
You didn't create a running thread for the OnStart method. Basically, the service manager calls OnStart to start the service, and that call needs to finish in about 15 seconds or so. Internally, you should create a thread with a loop that actually calls your code over time. Like so:
protected CancellationTokenSource _tokenSource = null;
protected Task _thread = null;
protected override void OnStart(string[] args)
{
_tokenSource = new CancellationTokenSource();
_thread = Task.Factory.StartNew(() => DoMyServiceLogic(), TaskCreationOptions.LongRunning, _tokenSource);
}
protected override void OnStop()
{
_tokenSource.Cancel();
}
protected void DoMyServiceLogic()
{
while(!_tokenSource.Token.IsCancellationRequested)
{
// Do Stuff
}
}
Your service doesn't really follow the pattern; you're not doing things continuously, and that should be more of a console program.
Effectively, it's because your service stopped doing anything as soon as you finished the OnStart method. It's like what happens when you finish Main in a console program - the application just exited.
Check to make sure the account your service runs under can access those files (including write access for the .wav and .mp3 files).
Your code might also be causing an unhandled exception. I'm not sure, but that might be visible in the event log. You can also get your service to write out messages explicitly to the event log (like in the case of an exception); check out this link: http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx
Open eventvwr.msc. There you will see exception details on why your windows service has stopped working. By the way you should as quickly as possible leave the OnStart method because you only
have 30 seconds to finish the OnStart method.
There is a excellent article on MSDN describing "how to debug" Windows Services.

Process.Start is blocking

I'm calling Process.Start, but it blocks the current thread.
pInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe");
// Start process
mProcess = new Process();
mProcess.StartInfo = pInfo;
if (mProcess.Start() == false) {
Trace.TraceError("Unable to run process {0}.");
}
Even when the process is closed, the code doesn't respond anymore.
But Process.Start is really supposed to block? What's going on?
(The process start correctly)
using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
namespace Test
{
class Test
{
[STAThread]
public static void Main()
{
Thread ServerThread = new Thread(AccepterThread);
ServerThread.Start();
Console.WriteLine (" --- Press ENTER to stop service ---");
while (Console.Read() < 0) { Application.DoEvents(); }
Console.WriteLine("Done.");
}
public static void AccepterThread(object data)
{
bool accepted = false;
while (true) {
if (accepted == false) {
Thread hThread = new Thread(HandlerThread);
accepted = true;
hThread.Start();
} else
Thread.Sleep(100);
}
}
public static void HandlerThread(object data)
{
ProcessStartInfo pInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe");
Console.WriteLine("Starting process.");
// Start process
Process mProcess = new Process();
mProcess.StartInfo = pInfo;
if (mProcess.Start() == false) {
Console.WriteLine("Unable to run process.");
}
Console.WriteLine("Still living...");
}
}
}
Console output is:
--- Press ENTER to stop service ---
Starting process.
Found it:
[STAThread]
Makes the Process.Start blocking. I read STAThread and Multithreading, but I cannot link the concepts with Process.Start behavior.
AFAIK, STAThread is required by Windows.Form. How to workaround this problem when using Windows.Form?
News for the hell:
If I rebuild my application, the first time I run application work correctly, but if I stop debugging and restart iy again, the problem araise.
The problem is not raised when application is executed without the debugger.
No, Process.Start doesn't wait for the child process to complete... otherwise you wouldn't be able to use features like redirected I/O.
Sample console app:
using System;
using System.Diagnostics;
public class Test
{
static void Main()
{
Process p = new Process {
StartInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe")
};
p.Start();
Console.WriteLine("See, I'm still running");
}
}
This prints "See, I'm still running" with no problems on my box - what's it doing on your box?
Create a ProcessStartInfo and set UseShellExecute to false (default value is true). Your code should read:
pInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe");
pInfo.UseShellExecute = false;
// Start process
mProcess = new Process();
mProcess.StartInfo = pInfo;
if (mProcess.Start() == false) {
Trace.TraceError("Unable to run process {0}.");
}
I had the same issue and starting the executable creating the process directly from the executable file solved the issue.
I was experiencing the same blocking behavior as the original poster in a WinForms app, so I created the console app below to simplify testing this behavior.
Jon Skeet's example uses Notepad, which only takes a few milliseconds to load normally, so a thread block may go unnoticed. I was trying to launch Excel which usually takes a lot longer.
using System;
using System.Diagnostics;
using static System.Console;
using System.Threading;
class Program {
static void Main(string[] args) {
WriteLine("About to start process...");
//Toggle which method is commented out:
//StartWithPath(); //Blocking
//StartWithInfo(); //Blocking
StartInNewThread(); //Not blocking
WriteLine("Process started!");
Read();
}
static void StartWithPath() {
Process.Start(TestPath);
}
static void StartWithInfo() {
var p = new Process { StartInfo = new ProcessStartInfo(TestPath) };
p.Start();
}
static void StartInNewThread() {
var t = new Thread(() => StartWithPath());
t.Start();
}
static string TestPath =
Environment.GetFolderPath(Environment.SpecialFolder.Desktop) +
"\\test.xlsx";
}
Calls to both StartWithPath and StartWithInfo block my thread in a console app. My console does not display "Process Started" until after the Excel splash screen closes and the main window is open.
StartInNewThread will display both messages on the console immediately, while the splash screen for Excel is still open.
We had this problem when launching a .bat script that was on a network drive on a different domain (we have dual trusted domains). I ran a remote C# debugger and sure enough Process.Start() was blocking indefinitely.
When repeating this task interactively in power shell, a security dialog was popping up:
As far as a solution, this was the direction we went. The person that did the work modified domain GPO to accomplish the trust.
Start server via command prompt:
"C:\Program Files (x86)\IIS Express\iisexpress" /path:\Publish /port:8080
This take access to sub-threads of the tree process of OS.
If you want to launch process and then make the process independent on the "launcher" / the originating call:
//Calling process
using (System.Diagnostics.Process ps = new System.Diagnostics.Process())
{
try
{
ps.StartInfo.WorkingDirectory = #"C:\Apps";
ps.StartInfo.FileName = #"C:\Program Files\Microsoft Office\Office14\MSACCESS.EXE"; //command
ps.StartInfo.Arguments = #"C:\Apps\xyz.accdb"; //argument
ps.StartInfo.UseShellExecute = false;
ps.StartInfo.RedirectStandardOutput = false;
ps.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized;
ps.StartInfo.CreateNoWindow = false; //display a windows
ps.Start();
}
catch (Exception ex)
{
MessageBox.Show(string.Format("==> Process error <=={0}" + ex.ToString(), Environment.NewLine));
}
}

Running a windows service in a console

What is the best way to run a windows service as a console?
My current idea is to pass in an "/exe" argument and do the work of the windows service, then calling Application.Run().
The reason I'm doing this is to better debug a windows service and allow easier profiling of the code. The service is basically hosting .NET remoted objects.
This is how I do it. Give me the same .exe for console app and service. To start as a console app it needs a command line parameter of -c.
private static ManualResetEvent m_daemonUp = new ManualResetEvent(false);
[STAThread]
static void Main(string[] args)
{
bool isConsole = false;
if (args != null && args.Length == 1 && args[0].StartsWith("-c")) {
isConsole = true;
Console.WriteLine("Daemon starting");
MyDaemon daemon = new MyDaemon();
Thread daemonThread = new Thread(new ThreadStart(daemon.Start));
daemonThread.Start();
m_daemonUp.WaitOne();
}
else {
System.ServiceProcess.ServiceBase[] ServicesToRun;
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new Service() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}
}
The Code Project site had a great article showing how to run a Windows Service in the Visual Studio debugger, no console app needed.
Or
C:\> MyWindowsService.exe /?
MyWindowsService.exe /console
MyWindowsService.exe -console

Categories

Resources