Is there an easier way to step through the code than to start the service through the Windows Service Control Manager and then attaching the debugger to the thread? It's kind of cumbersome and I'm wondering if there is a more straightforward approach.
If I want to quickly debug the service, I just drop in a Debugger.Break() in there. When that line is reached, it will drop me back to VS. Don't forget to remove that line when you are done.
UPDATE: As an alternative to #if DEBUG pragmas, you can also use Conditional("DEBUG_SERVICE") attribute.
[Conditional("DEBUG_SERVICE")]
private static void DebugMode()
{
Debugger.Break();
}
On your OnStart, just call this method:
public override void OnStart()
{
DebugMode();
/* ... do the rest */
}
There, the code will only be enabled during Debug builds. While you're at it, it might be useful to create a separate Build Configuration for service debugging.
I also think having a separate "version" for normal execution and as a service is the way to go, but is it really required to dedicate a separate command line switch for that purpose?
Couldn't you just do:
public static int Main(string[] args)
{
if (!Environment.UserInteractive)
{
// Startup as service.
}
else
{
// Startup as application
}
}
That would have the "benefit", that you can just start your app via doubleclick (OK, if you really need that) and that you can just hit F5 in Visual Studio (without the need to modify the project settings to include that /console Option).
Technically, the Environment.UserInteractive checks if the WSF_VISIBLE Flag is set for the current window station, but is there any other reason where it would return false, apart from being run as a (non-interactive) service?
When I set up a new service project a few weeks ago I found this post. While there are many great suggestions, I still didn't find the solution I wanted: The possibility to call the service classes' OnStart and OnStop methods without any modification to the service classes.
The solution I came up with uses the Environment.Interactive the select running mode, as suggested by other answers to this post.
static void Main()
{
ServiceBase[] servicesToRun;
servicesToRun = new ServiceBase[]
{
new MyService()
};
if (Environment.UserInteractive)
{
RunInteractive(servicesToRun);
}
else
{
ServiceBase.Run(servicesToRun);
}
}
The RunInteractive helper uses reflection to call the protected OnStart and OnStop methods:
static void RunInteractive(ServiceBase[] servicesToRun)
{
Console.WriteLine("Services running in interactive mode.");
Console.WriteLine();
MethodInfo onStartMethod = typeof(ServiceBase).GetMethod("OnStart",
BindingFlags.Instance | BindingFlags.NonPublic);
foreach (ServiceBase service in servicesToRun)
{
Console.Write("Starting {0}...", service.ServiceName);
onStartMethod.Invoke(service, new object[] { new string[] { } });
Console.Write("Started");
}
Console.WriteLine();
Console.WriteLine();
Console.WriteLine(
"Press any key to stop the services and end the process...");
Console.ReadKey();
Console.WriteLine();
MethodInfo onStopMethod = typeof(ServiceBase).GetMethod("OnStop",
BindingFlags.Instance | BindingFlags.NonPublic);
foreach (ServiceBase service in servicesToRun)
{
Console.Write("Stopping {0}...", service.ServiceName);
onStopMethod.Invoke(service, null);
Console.WriteLine("Stopped");
}
Console.WriteLine("All services stopped.");
// Keep the console alive for a second to allow the user to see the message.
Thread.Sleep(1000);
}
This is all the code required, but I also wrote walkthrough with explanations.
Sometimes it is important to analyze what's going on during the start up of the service. Attaching to the process does not help here, because you are not quick enough to attach the debugger while the service is starting up.
The short answer is, I am using the following 4 lines of code to do this:
#if DEBUG
base.RequestAdditionalTime(600000); // 600*1000ms = 10 minutes timeout
Debugger.Launch(); // launch and attach debugger
#endif
These are inserted into the OnStart method of the service as follows:
protected override void OnStart(string[] args)
{
#if DEBUG
base.RequestAdditionalTime(600000); // 10 minutes timeout for startup
Debugger.Launch(); // launch and attach debugger
#endif
MyInitOnstart(); // my individual initialization code for the service
// allow the base class to perform any work it needs to do
base.OnStart(args);
}
For those who haven't done it before, I have included detailed hints below, because you can easily get stuck. The following hints refer to Windows 7x64 and Visual Studio 2010 Team Edition, but should be valid for other (newer) environments, too.
Important: Deploy the service in "manual" mode (using either the InstallUtil utility from the VS command prompt or run a service installer project you have prepared). Open Visual Studio before you start the service and load the solution containing the service's source code - set up additional breakpoints as you require them in Visual Studio - then start the service via the Service Control Panel.
Because of the Debugger.Launch code, this will cause a dialog "An unhandled Microsoft .NET Framework exception occured in Servicename.exe." to appear. Click Yes, debug Servicename.exe as shown in the screenshot:
Afterwards, Windows UAC might prompt you to enter admin credentials. Enter them and proceed with Yes:
After that, the well known Visual Studio Just-In-Time Debugger window appears. It asks you if you want to debug using the delected debugger. Before you click Yes, select that you don't want to open a new instance (2nd option) - a new instance would not be helpful here, because the source code wouldn't be displayed. So you select the Visual Studio instance you've opened earlier instead:
After you have clicked Yes, after a while Visual Studio will show the yellow arrow right in the line where the Debugger.Launch statement is and you are able to debug your code (method MyInitOnStart, which contains your initialization).
Pressing F5 continues execution immediately, until the next breakpoint you have prepared is reached.
Hint: To keep the service running, select Debug -> Detach all. This allows you to run a client communicating with the service after it started up correctly and you're finished debugging the startup code. If you press Shift+F5 (stop debugging), this will terminate the service. Instead of doing this, you should use the Service Control Panel to stop it.
Note that
If you build a Release, then the debug code is automatically removed and the service runs normally.
I am using Debugger.Launch(), which starts and attaches a debugger. I have tested Debugger.Break() as well, which did not work, because there is no debugger attached on start up of the service yet (causing the "Error 1067: The process terminated unexpectedly.").
RequestAdditionalTime sets a longer timeout for the startup of the service (it is not delaying the code itself, but will immediately continue with the Debugger.Launch statement). Otherwise the default timeout for starting the service is too short and starting the service fails if you don't call base.Onstart(args) quickly enough from the debugger. Practically, a timeout of 10 minutes avoids that you see the message "the service did not respond..." immediately after the debugger is started.
Once you get used to it, this method is very easy because it just requires you to add 4 lines to an existing service code, allowing you quickly to gain control and debug.
What I usually do is encapsulate the logic of the service in a separate class and start that from a 'runner' class. This runner class can be the actual service or just a console application. So your solution has (atleast) 3 projects:
/ConsoleRunner
/....
/ServiceRunner
/....
/ApplicationLogic
/....
This YouTube video by Fabio Scopel explains how to debug a Windows service quite nicely... the actual method of doing it starts at 4:45 in the video...
Here is the code explained in the video... in your Program.cs file, add the stuff for the Debug section...
namespace YourNamespace
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
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
}
}
}
In your Service1.cs file, add the OnDebug() method...
public Service1()
{
InitializeComponent();
}
public void OnDebug()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
// your code to do something
}
protected override void OnStop()
{
}
How it works
Basically you have to create a public void OnDebug() that calls the OnStart(string[] args) as it's protected and not accessible outside. The void Main() program is added with #if preprocessor with #DEBUG.
Visual Studio defines DEBUG if project is compiled in Debug mode.This will allow the debug section(below) to execute when the condition is true
Service1 myService = new Service1();
myService.OnDebug();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
And it will run just like a console application, once things go OK you can change the mode Release and the regular else section will trigger the logic
UPDATE
This approach is by far the easiest:
http://www.codeproject.com/KB/dotnet/DebugWinServices.aspx
I leave my original answer below for posterity.
My services tend to have a class that encapsulates a Timer as I want the service to check at regular intervals whether there is any work for it to do.
We new up the class and call StartEventLoop() during the service start-up. (This class could easily be used from a console app too.)
The nice side-effect of this design is that the arguments with which you set up the Timer can be used to have a delay before the service actually starts working, so that you have time to attach a debugger manually.
p.s. How to attach the debugger manually to a running process...?
using System;
using System.Threading;
using System.Configuration;
public class ServiceEventHandler
{
Timer _timer;
public ServiceEventHandler()
{
// get configuration etc.
_timer = new Timer(
new TimerCallback(EventTimerCallback)
, null
, Timeout.Infinite
, Timeout.Infinite);
}
private void EventTimerCallback(object state)
{
// do something
}
public void StartEventLoop()
{
// wait a minute, then run every 30 minutes
_timer.Change(TimeSpan.Parse("00:01:00"), TimeSpan.Parse("00:30:00");
}
}
Also I used to do the following (already mentioned in previous answers but with the conditional compiler [#if] flags to help avoid it firing in a Release build).
I stopped doing it this way because sometimes we'd forget to build in Release and have a debugger break in an app running on a client demo (embarrasing!).
#if DEBUG
if (!System.Diagnostics.Debugger.IsAttached)
{
System.Diagnostics.Debugger.Break();
}
#endif
static void Main()
{
#if DEBUG
// Run as interactive exe in debug mode to allow easy
// debugging.
var service = new MyService();
service.OnStart(null);
// Sleep the main thread indefinitely while the service code
// runs in .OnStart
Thread.Sleep(Timeout.Infinite);
#else
// Run normally as service in release mode.
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]{ new MyService() };
ServiceBase.Run(ServicesToRun);
#endif
}
You can also start the service through the command prompt (sc.exe).
Personally, I'd run the code as a stand-alone program in the debugging phase, and when most bugs are ironed out, change to running as service.
What I used to do was to have a command line switch which would start the program either as a service or as a regular application. Then, in my IDE I would set the switch so that I could step through my code.
With some languages you can actually detect if it's running in an IDE, and perform this switch automatically.
What language are you using?
Use the TopShelf library.
Create a console application then configure setup in your Main
class Program
{
static void Main(string[] args)
{
HostFactory.Run(x =>
{
// setup service start and stop.
x.Service<Controller>(s =>
{
s.ConstructUsing(name => new Controller());
s.WhenStarted(controller => controller.Start());
s.WhenStopped(controller => controller.Stop());
});
// setup recovery here
x.EnableServiceRecovery(rc =>
{
rc.RestartService(delayInMinutes: 0);
rc.SetResetPeriod(days: 0);
});
x.RunAsLocalSystem();
});
}
}
public class Controller
{
public void Start()
{
}
public void Stop()
{
}
}
To debug your service, just hit F5 in visual studio.
To install service, type in cmd "console.exe install"
You can then start and stop service in the windows service manager.
I think it depends on what OS you are using, Vista is much harder to attach to Services, because of the separation between sessions.
The two options I've used in the past are:
Use GFlags (in the Debugging Tools for Windows) to setup a permanent debugger for a process. This exists in the "Image File Execution Options" registry key and is incredibly useful. I think you'll need to tweak the Service settings to enable "Interact with Desktop". I use this for all types of debugging, not just services.
The other option, is to separate the code a bit, so that the service part is interchangable with a normal app startup. That way, you can use a simple command line flag, and launch as a process (rather than a Service), which makes it much easier to debug.
Hope this helps.
I like to be able to debug every aspect of my service, including any initialization in OnStart(), while still executing it with full service behavior within the framework of the SCM... no "console" or "app" mode.
I do this by creating a second service, in the same project, to use for debugging. The debug service, when started as usual (i.e. in the services MMC plugin), creates the service host process. This gives you a process to attach the debugger to even though you haven't started your real service yet. After attaching the debugger to the process, start your real service and you can break into it anywhere in the service lifecycle, including OnStart().
Because it requires very minimal code intrusion, the debug service can easily be included in your service setup project, and is easily removed from your production release by commenting out a single line of code and deleting a single project installer.
Details:
1) Assuming you are implementing MyService, also create MyServiceDebug. Add both to the ServiceBase array in Program.cs like so:
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService(),
new MyServiceDebug()
};
ServiceBase.Run(ServicesToRun);
}
2) Add the real service AND the debug service to the project installer for the service project:
Both services (real and debug) get included when you add the service project output to the setup project for the service. After installation, both services will appear in the service.msc MMC plugin.
3) Start the debug service in MMC.
4) In Visual Studio, attach the debugger to the process started by the debug service.
5) Start the real service and enjoy debugging.
When I write a service I put all the service logic in a dll project and create two "hosts" that call into this dll, one is a Windows service and the other is a command line application.
I use the command line application for debugging and attach the debugger to the real service only for bugs I can't reproduce in the command line application.
I you use this approach just remember that you have to test all the code while running in a real service, while the command line tool is a nice debugging aid it's a different environment and it doesn't behave exactly like a real service.
When developing and debugging a Windows service I typically run it as a console application by adding a /console startup parameter and checking this. Makes life much easier.
static void Main(string[] args) {
if (Console.In != StreamReader.Null) {
if (args.Length > 0 && args[0] == "/console") {
// Start your service work.
}
}
}
How about Debugger.Break() in the first line?
To debug Windows Services I combine GFlags and a .reg file created by regedit.
Run GFlags, specifying the exe-name and vsjitdebugger
Run regedit and go to the location where GFlags sets his options
Choose "Export Key" from the file-menu
Save that file somewhere with the .reg extension
Anytime you want to debug the service: doubleclick on the .reg file
If you want to stop debugging, doubleclick on the second .reg file
Or save the following snippets and replace servicename.exe with the desired executable name.
debugon.reg:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\servicename.exe]
"GlobalFlag"="0x00000000"
"Debugger"="vsjitdebugger.exe"
debugoff.reg:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\servicename.exe]
"GlobalFlag"="0x00000000"
Use Windows Service Template C# project to create a new service app https://github.com/HarpyWar/windows-service-template
There are console/service mode automatically detected, auto installer/deinstaller of your service and several most used features are included.
Here is the simple method which I used to test the service, without any additional "Debug" methods and with integrated VS Unit Tests.
[TestMethod]
public void TestMyService()
{
MyService fs = new MyService();
var OnStart = fs.GetType().BaseType.GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
OnStart.Invoke(fs, new object[] { null });
}
// As an extension method
public static void Start(this ServiceBase service, List<string> parameters)
{
string[] par = parameters == null ? null : parameters.ToArray();
var OnStart = service.GetType().GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
OnStart.Invoke(service, new object[] { par });
}
Just put your debugger launch anywhere and attach Visualstudio on startup
#if DEBUG
Debugger.Launch();
#endif
Also you need to start VS as Administatrator and you need to allow, that a process can automatically be debugged by a different user (as explained here):
reg add "HKCR\AppID{E62A7A31-6025-408E-87F6-81AEB0DC9347}" /v AppIDFlags /t REG_DWORD /d 8 /f
For routine small-stuff programming I've done a very simple trick to easily debug my service:
On start of the service, I check for a command line parameter "/debug". If the service is called with this parameter, I don't do the usual service startup, but instead start all the listeners and just display a messagebox "Debug in progress, press ok to end".
So if my service is started the usual way, it will start as service, if it is started with the command line parameter /debug it will act like a normal program.
In VS I'll just add /debug as debugging parameter and start the service program directly.
This way I can easily debug for most small kind problems. Of course, some stuff still will need to be debugged as service, but for 99% this is good enough.
#if DEBUG
System.Diagnostics.Debugger.Break();
#endif
I use a variation on JOP's answer. Using command line parameters you can set the debugging mode in the IDE with project properties or through the Windows service manager.
protected override void OnStart(string[] args)
{
if (args.Contains<string>("DEBUG_SERVICE"))
{
Debugger.Break();
}
...
}
For trouble-shooting on existing Windows Service program, use 'Debugger.Break()' as other guys suggested.
For new Windows Service program, I would suggest using James Michael Hare's method http://geekswithblogs.net/BlackRabbitCoder/archive/2011/03/01/c-toolbox-debug-able-self-installable-windows-service-template-redux.aspx
static class Program
{
static void Main()
{
#if DEBUG
// TODO: Add code to start application here
// //If the mode is in debugging
// //create a new service instance
Service1 myService = new Service1();
// //call the start method - this will start the Timer.
myService.Start();
// //Set the Thread to sleep
Thread.Sleep(300000);
// //Call the Stop method-this will stop the Timer.
myService.Stop();
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
#endif
}
}
Just paste
Debugger.Break();
any where in you code.
For Example ,
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
private static void Main()
{
Debugger.Break();
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
It will hit Debugger.Break(); when you run your program.
You have two options to do the debugging.
create a log file : Personally i prefer a separate log file like text file rather using the application log or event log.But this will cost you a lot on behalf of time, because its still hard to figure our where the exact error location is
Convert the application to console application : this will enable you, all the debugging tools which we can use in VS.
Please refer THIS blog post that i created for the topic.
The best option is to use the 'System.Diagnostics' namespace.
Enclose your code in if else block for debug mode and release mode as shown below to switch between debug and release mode in visual studio,
#if DEBUG // for debug mode
**Debugger.Launch();** //debugger will hit here
foreach (var job in JobFactory.GetJobs())
{
//do something
}
#else // for release mode
**Debugger.Launch();** //debugger will hit here
// write code here to do something in Release mode.
#endif
I was able to debug a windows service easily following this official documentation from Microsoft - https://learn.microsoft.com/en-us/dotnet/framework/windows-services/how-to-debug-windows-service-applications#how-to-run-a-windows-service-as-a-console-application.
It tells to run the windows service as a console app for debugging.
Related
#if DEBUG
MainService service1 = new MainService();
service1.onDebug();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
ConfigurationSync.logDebugMessage(logMessageType.message, "Starting main service thread");
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MainService()
};
ServiceBase.Run(ServicesToRun);
ConfigurationSync.logDebugMessage(logMessageType.message, "Starting main service thread");
#endif
I have created my first windows service and I am wondering what the correct way is to start the service in the Program.cs file.
The code supplied above is what was suggested to me by an online tut, #if debug running while testing in Visual Studio and the else block running when built in release mode and installed on the server.
The problem is, it doesn't seem to run on the server after install if I don't use the code in the #if debug code block.
If i run the code as supplied above it says the service has started but nothing seems to happen, while if I only run what's in the debug block the service runs but I get an error on the server "Service failed to start in a timely manner"
Any help would be appreciated
Update:
In my mainservice I have a function that kicks off all the features of the service, this function is startSoftwareUpdates();
These are the functions I have in MainService:
public MainService()
{
startSoftwareUpdates();
public void onDebug()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
startSoftwareUpdates();
}
Update 3:
So I have reshuffled MainService as follows:
public MainService()
{
InitializeComponent();
}
public void onDebug()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
startSoftwareUpdates();
}).Start();
}
What kind of problems might I run into with this approach? I'd like the Thread to run infinitely too...
Nothing looks wrong with your code. If you could post some more of the code that is inside of your MainService() constructor, that'd be helpful considering that could be where the issue is.
However, when I build these services, instead of the #if DEBUG route, I generally do something like this
if (Environment.UserInteractive)
{
//**** this is for debugging in console mode
}
else
{
//*** this is for running as a Windows service
var ServicesToRun = new ServiceBase[]
{
new ServiceHome()
};
ServiceBase.Run(ServicesToRun);
}
To be clear, I don't expect this to resolve your issue as the code you posted above seems to do the same thing, just in a different manner. I'm posting this to give you a different way to accomplish what you did above.
If I had to guess, I'd say the issue is in your MainService constructor.
Edit
I don't believe the issue is with any of the code that you've written. The error you're getting is caused by a number of potential issues, so it's tough to tell you exactly what it is. Here is a link that has some solutions for you to try. Also, you should try to find the error in the Event Log, assuming you're on a windows machine. That will have a bit more detail to the issue most of the time.
So basically I'm trying to program a Windows Service in C# under Visual Studio 2017. As the service didn't do what i wanted to do i made a test service with a very rudimentary logic to test if it even does what i want in the OnStart() Method. The reason why i chose to manually write a string into the event log is because i want to make sure that there is no writing permission issue. I mean if the service is installed and started, it should write the line into the log shouldn't it?
So:
namespace WindowsService3
{
public class Program : System.ServiceProcess.ServiceBase
{
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
protected override void OnStart(string[] args)
{
this.EventLog.WriteEntry("Hello");
}
protected override void OnStop()
{
}
}
}
I added a ProjectInstaller, added the service name to it as well as specifying it for LocalSystem. Then i used the following line to install it:
C:\Windows\system32>sc \\10.10.0.122 create TESTService binPath= "C:\temp\service\WindowsService1.exe"
The service can now be seen in the service manager and even started. Without problems... In the eventlog though i don't see the specified line. So it seems the service is correctly started, but it doesn't user the logic in the OnStart() method. I have no idea why. I also tried things like creating a text file via the OnStart() method at first... Also no success. What am i doing wrong? Again, the service IS installed and IS started as the Event log and the service manager suggest.
Edit: My problem is that no code is executed in OnStart at all. I can't write a file, i can't write a log, nothing. The service is just installed and can be started, but i doesn't do anything that is put into OnStart() and i don't know why. My coworkers can't figure it out either.
Edit2: The VS2017 template tells me to make the Program class static. But then I can't use OnStart() in it. But maybe this is my missunderstanding? In my example i made the Program class just public to implement OnStart() but maybe that was the mistake?
You have written your service code in the class Program, but your service that is started is named Service1, probably defined by the template in another file.
Either edit Service1.cs to include your startup code, or edit your Program.cs to start your class:
ServicesToRun = new ServiceBase[]
{
new Program() // <----
};
Putting your service and Program.cs in the same class is uncommon, it's indeed a good approach to keep them separate and have a separate Service class.
Try logging this way and then check in event logger under Application errors:
using (EventLog eventLog = new EventLog("Application"))
{
eventLog.Source = "Application";
eventLog.WriteEntry("Message", EventLogEntryType.Error);
}
The service installs correctly but when attempting to start it via net start or from the services window it doesn't start at all, not even getting to the OnStart handler.
If I use an administrator account, the service starts and works correctly. This seems to suggest something in the service requires admin privileges but this is purely an on-demand style service with nothing executing until requested. With this type of service I'd assume that is should at least start and then fail later when a request is made to it that requires admin privileges?
It's impossible to debug as I can't even get it to start and nothing is appearing on the event logs apart from an Information log stating that the service stopped. There's too much code in the service to add it all here but the entry point is a fairly standard Unity style service:
partial class MyServiceHost : UnityServiceBase
{
private Bootstrapper _bootstrapper;
public MyServiceHost()
{
InitializeComponent();
}
protected override void OnStart( string[] args )
{
TextWriter tw = new StreamWriter( "ServiceTestLog.txt" );
tw.Write( "Date: " + DateTime.Now + "\n" );
try
{
base.OnStart( args );
_bootstrapper = new Bootstrapper( UnityContainer );
_bootstrapper.Run();
}
catch ( Exception ex )
{
tw.Write( ex.ToString() );
}
tw.Close();
}
protected override void OnStop()
{
_bootstrapper.Teardown();
base.OnStop();
}
}
For business reasons I can't just make the user account it uses an administrator so I'd appreciate any suggestions on how to fix this issue.
Writing to "ServiceTestLog.txt" may require local admin rights.
Make sure your user account has the "Log on as a Service" privilege. This won't work without that, and it's not on by default for users, though it would be for administrator. Instructions here.
Run the Visual Studio Debugger and attach to the service and you can step through it and see what's going on.
You can add this before initializecomponent() and add WAITFORDEBUGGER in the Service Control Panel "Start parameters" textbox for your service.
C#:
foreach (string arg in args) {
if (arg == "WAITFORDEBUGGER") {
while (!Debugger.IsAttached) {
Threading.Thread.Sleep(1000);
}
}
}
VB.Net:
For Each arg As String In args
If arg = "WAITFORDEBUGGER" Then
While Not Debugger.IsAttached
Threading.Thread.Sleep(1000)
End While
End If
Next
The service will then wait for you to fire up Visual Studio and attach the debugger, at which point you can trace through the entire initialization and run sequence and see what's broken.
If it never hits the WAITFORDEBUGGER code, it's probably having trouble loading a dependency, in which case Sysinternals Process Monitor (https://technet.microsoft.com/en-us/sysinternals/bb896645) can tell you what it's getting hosed on.
A common nuisance we have is having to switch this code below depending on whether we are testing locally or committing code for the build server.
/// <summary>
/// Main entry point to the application.
/// </summary>
public static void Main()
{
// Don't forget to uncomment this if committing (!)
//var servicesToRun = new ServiceBase[] {new myservice()};
//ServiceBase.Run(servicesToRun);
// and re-comment this
RunAsConsoleApp();
}
It would be really useful if there was a way to test in the code to tell the output type i.e, and avoid all the 'oh-no I committed and broke the build' time wasting.
if (IsConsoleApp)
{
Using(var host= new ServiceHost(typeof(myservice))
{
host.Open();
etc....
}
}
else
{
var servicesToRun = new ServiceBase[] {new myservice()};
ServiceBase.Run(servicesToRun);
}
Have you tried using the Environment.UserInteractive property in place of IsConsoleApp?
Environment.UserInteractive does not detect if we have a console running, it only detects if the user can have some kind of interaction possibility to the running process.
If you want to check if the application is a console application I found this working:
bool is_console_app = Console.OpenStandardInput(1) != Stream.Null;
All credits to Glen here.
If you're all definitely not going to commit Debug builds.. then as long as there is a DEBUG constant defined under Project Properties > Build tab, you can try:
#if DEBUG
RunAsConsoleApp();
#else
RunNormally();
#endif
But then, this is still just as error prone if someone accidentally commits a Debug build.
You could setup a separate build configuration (e.g. Release - Service) and have a conditional compilation statement to switch between code blocks.
See here for more:
http://msdn.microsoft.com/en-us/library/aa691095(v=vs.71).aspx
So, in your Release - Service configuration, define a constant e.g. RELEASESERVICE. Then use this like:
#if RELEASESERVICE
etc
Usually, I get this error:
(The "service name" service on Local Computer started and then stopped. Some services stop automatically if they are not in use by other service or programs) when there's something wrong with my code, like non-existing drive paths, etc. The windows service will not start.
I have a windows service that backs up folder/files, to a location if it reached the size limit. Details are all provide by an XML Configuration that the windows service reads on start. I have a separate windows forms that has a button that does exactly what my windows service's onstart is doing. I use my windows forms for debugging the code before I put it in my windows service.
When I start my windows forms. It does what it suppose to do. When I put my code in the windows service OnStart() method the error showed up.
Here's my code:
protected override void OnStart(string[] args)
{
private static string backupConfig = #"D:\LogBackupConfig\backupconfig.xml";
private static string serviceStat = #"D:\LogBackupConfig\Status.txt";
private static string fileFolderStat = #"D:\LogBackupConfig\FileFolderStat.txt";
protected override void OnStart(string[] args)
{
if (File.Exists(backupConfig))
{
FileSystemWatcher watcher = new FileSystemWatcher();
XmlTextReader reader = new XmlTextReader(backupConfig);
XmlNodeType type;
List<string> listFile = new List<string>();
string fileWatch = "";
//this loop is for reading XML elements and assigning to variables
while (reader.Read())
{
type = reader.NodeType;
if (type == XmlNodeType.Element)
{
if (reader.Name == "File")
{
reader.Read();
fileWatch = reader.Value;
}
else if (reader.Name == "Folder")
{
reader.Read();
fileWatch = reader.Value;
}
}
}
reader.Close();
watcher.Path = fileWatch;
watcher.Filter = "*.*";
//this loop reads whether the service will watch a file/folder
XmlTextReader reader1 = new XmlTextReader(backupConfig);
while (reader1.Read())
{
type = reader1.NodeType;
if (type == XmlNodeType.Element)
{
if (reader1.Name == "File")
{
watcher.IncludeSubdirectories = false;
watcher.Changed += new FileSystemEventHandler(OnChangedFile);
}
else if (reader1.Name == "Folder")
{
watcher.IncludeSubdirectories = true;
watcher.Changed += new FileSystemEventHandler(OnChangedFolder);
}
}
}
reader1.Close();
watcher.EnableRaisingEvents = true;
}
else
{
StreamWriter sw = new StreamWriter(serviceStat, true);
sw.WriteLine("File not found. Please start the Log Backup UI first.");
sw.Close();
}
}
I don't know what keeps the windows service not starting, the windows form simulator worked fine. What seems to be the problem?
UPDATE:
After many trials I've noticed that using only a folder directory (w/out file), the windows service doesn't work. When I replaced the fileWatch variable with a specific file (including its directory), the windows service started. When I changed it back to a folder location, it didn't work. What I think is that folder locations doesn't work in a filewatcher.
When I tried creating a new windows service that watches a folder location, it worked.. However, when I tried the same location in my original windows service, it didn't work! I was mindf$#*ed! It seems that I have to create a new windows service and build the installer everytime I place a new code/function.. This way I can keep track where I get an error.
If the service starts and stops like that, it means your code is throwing an unhandled exception. This is pretty difficult to debug, but there are a few options.
Consult the Windows Event Viewer. Normally you can get to this by going to the computer/server manager, then clicking Event Viewer -> Windows Logs -> Application. You can see what threw the exception here, which may help, but you don't get the stack trace.
Extract your program logic into a library class project. Now create two different versions of the program: a console app (for debugging), and the windows service. (This is a bit of initial effort, but saves a lot of angst in the long run.)
Add more try/catch blocks and logging to the app to get a better picture of what's going on.
Not sure this will be helpful, but for debugging a service you could always use the following in the OnStart method:
protected override void OnStart(string[] args)
{
System.Diagnostics.Debugger.Launch();
...
}
than you could attach your visual studio to the process and have better debug abilities.
hope this was helpful,
good luck
I have found it very handy to convert your existing windows service to a console by simply changing your program with the following. With this change you can run the program by debugging in visual studio or running the executable normally. But it will also work as a windows service. I also made a blog post about it
program.cs
class Program
{
static void Main()
{
var program = new YOUR_PROGRAM();
if (Environment.UserInteractive)
{
program.Start();
}
else
{
ServiceBase.Run(new ServiceBase[]
{
program
});
}
}
}
YOUR_PROGRAM.cs
[RunInstallerAttribute(true)]
public class YOUR_PROGRAM : ServiceBase
{
public YOUR_PROGRAM()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Start();
}
protected override void OnStop()
{
//Stop Logic Here
}
public void Start()
{
//Start Logic here
}
}
Please check that you have registered all HTTP endpoints in the local mahcine's Access Control List (ACL)
http://just2thepoint.blogspot.fr/2013/10/windows-service-on-local-computer.html
EventLog.Log should be set as "Application"
Meanwhile, another reason : accidentally deleted the .config file caused the same error message appears:
"Service on local computer started and then stopped. some services stop automatically..."
Use Timer and tick event to copy your files.
On start the service, start the time and specify the interval in the time.
So the service is keep running and copy the files ontick.
Hope it help.
You may want to unit test the initialization - but because it's in the OnStart method this is near to impossible. I would suggest moving the initialization code out into a separate class so that it can be tested or at least re-used in a form tester.
Secondly to add some logging (using Log4Net or similar) and add some verbose logging so that you can see details about runtime errors. Examples of runtime errors would be AccessViolation etc. especially if your service is running without enough privileges to access the config files.
The account which is running the service might not have mapped the D:-drive (they are user-specific). Try sharing the directory, and use full UNC-path in your backupConfig.
Your watcher of type FileSystemWatcher is a local variable, and is out of scope when the OnStart method is done. You probably need it as an instance or class variable.
I came across the same issue. My service is uploading/receiving XMLS and write the errors to the Event Log.
When I went to the Event Log, I tried to filter it. It prompt me that the Event Log was corrupted.
I cleared the Event Log and all OK.
In our case, nothing was added in the Windows Event Logs except logs that the problematic service has been started and then stopped.
It turns out that the service's CONFIG file was invalid. Correcting the invalid CONFIG file fixed the issue.