 |
|
 |
I like to use System.Environment.MachineName to base my debugging on. if I'm in development environment then I do one thing else I use production resources.
|
|
|
|
 |
|
 |
In more recent versions of this project I've gone and done the same.
|
|
|
|
 |
|
 |
myFeedback = "Thank you, thank you, thank you ...";
|
|
|
|
 |
|
 |
Thanks, Lee - I love elegant and simple solutions. I am going to incorporate this into a template so the code is automatically inserted when I spin up a new service project!
-Dave Ferreira
It IS what you say, not just how you say it!
|
|
|
|
 |
|
 |
I don't know about elegant - but simple, yep I'd agree with that.
I'd also suggest reading some of the more recent comments below. Some others have made some great contributions that add the missing elegance to my code above.
Next, a XAML management console where if you highlight the rotating spotlight beam while licking the USB port on your DNS server (may require virtual tongue - that's another project) you get a mocked up terminal services window showing the state of your service in glorious surround sound.
|
|
|
|
 |
|
 |
That would only rate a 3. You should use a Firewire 800 virtual tongue instead of a USB, and while surround sound is nice in a late 80's kind of way, you should try creating a VR world using Aero. Of course, that's just my opinion - I could be wrong.
Everyone's a critic.....
-Dave Ferreira
"When everyone is out to get you, paranoia is just good thinking...."
|
|
|
|
 |
|
 |
Quite true about the surround sound vs. Aero. Although I think the firewire is overkill, after all the tongue (virtual or real) won't be doing anything as intensive as saliva streaming ( oow yuck - very bad mental imagery - anyway what's typed is typed ).
|
|
|
|
 |
|
 |
I just sat down to eat when I read that. Score one for the diet.
-Dave Ferreira
"Time flies, but never on Delta."
|
|
|
|
 |
|
 |
Perhaps I shouldn't have started that thread - in the end it was like trying to put out a flamewar by hoicking up virtual phlegm.
|
|
|
|
 |
|
 |
Until now, I've always opted for the "rip your code logic into an assembly and have both your windows service call it for deployment & a command line app call it for debugging" approach. This is much nicer!
|
|
|
|
 |
|
 |
Thanks,
The only real downside I've ever found with this approach is if you forget to do an actual release build before putting your service into production.
- But that soon shows up as something wrong...;)
|
|
|
|
 |
|
 |
You can access the command-line arguments during the service startup (just change the "static void Main()" into "static void Main(string[] args)").
My service will run as a normal command-line app, similar to what yours does in a Debug build, if you give it the "/DEBUG" argument on the command-line. This lets me run it manually inside and outside of the debugger, whether I've done a release or a debug build, and not have to worry about shipping the wrong version either.
The only additional change is to edit the project settings to add "/DEBUG" to the command-line arguments for debugging.
|
|
|
|
 |
|
 |
That was an elegant solution to the problem, even if it seems a little quick-and-dirty. What's funny is that I'm actually using this approach (with modifications) in a real-life production application at the moment. It got a little more complicated because I ended up wanting the ability to launch the service from other assemblies (e.g. from unit tests), but it works great for me... so I figured I'd share. Not like you necessarily want to use this code directly, but it shows how to mash the OnStart method, rather than calling a public method in the service. (I use it in this case because my service is so utterly short I'd rather not even bother with private methods.) using System.Reflection; using System.ServiceProcess; public static class Program { // Note that the real service has been renamed to MyService to protect the innocent. private static MyService service = new MyService(); internal static void Main() { #if (!DEBUG) ServiceBase.Run( new ServiceBase[] { service } ); #else Start(); System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite); #endif } public static void Start() { InvokeServiceMethod("OnStart"); } public static void Stop() { InvokeServiceMethod("OnStop"); } private static void InvokeServiceMethod(string methodName, params object[] parameters) { if (parameters == null || parameters.Length < 1) { parameters = new object[] { null }; } service.GetType().InvokeMember(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, service, parameters); } }
Note the use of reflection to smash the OnStart method (or, really, any instance method you would like). Might be overkill, but I like reflection. Also, you can probably scrap the compile-time test and replace it with one at runtime. I'm thinking about switching my code to do this (but be warned, it's not fully tested yet): if (System.Diagnostics.Debugger.IsAttached) { Start(); System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite); } else { ServiceBase.Run(new ServiceBase[] { service }); } Naturally, this assumes that you only want it to start this way while running in the Visual Studio (or other unmanaged) debugger. If you need to launch the service from the command line in the debugging mode, then it won't work. There -may- be some way to detect whether the app is being launched as a service (perhaps, say, through execution credentials - if you're running as LOCALSYSTEM it would be a good indicator), but I don't really need that functionality so I won't be pursuing it here.
Anyway, thanks for your help! Thought I'd try and give a little back too.
|
|
|
|
 |
|
 |
Thanks for the reply, and the suggestions, I'll give them a go myself - Yes, I use my code in production systems myself.
I've been seriously thinking about rewriting this to do things *better* - i.e. less 'crude' but still 'effective'.
PS. For those who don't know CBE stands for 'Commander of the Order of the British Empire', which ranks just below a knighthood.
|
|
|
|
 |
|
|
 |
|
 |
It works great. I did have to add a method service.OnDebugStart() that takes the place of the overridden OnStart method but with the same functionality... for debug only purposes. It makes your code: service.<Your Service's Primary Method Here>(); obsolete. the line: System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite); is still necessary I also got it to work with SQL Server... no problem -- modified at 16:37 Tuesday 25th April, 2006
|
|
|
|
 |
|
 |
This is a very quick way to debug classes which are wrapped by a windows service.
|
|
|
|
 |
|
 |
System.Diagnostics.Debugger.Break();
Is there anything wrong with this option?
|
|
|
|
 |
|
 |
It's good because it effectively fires up the "attachment to a debugger" process for you at the point you want.
However, you obviously should still put appropriate compiler directives around the call so that it doesn't get included in any release code. Also, you're still following the pattern of crank the code up first, then attach your debugger. Whereas the approach above is simply to run the code directly in debug mode.
|
|
|
|
 |
|
 |
Dude, I have spent hours trying to make the debugging work like MSDN and other sites tell you too, but your 3-liner snippet is simply the best! Thanks!!!
-ADiaz
|
|
|
|
 |
|
 |
Thanks for the tip. I found it quite useful.
I recently picked up anothers app, and it wouldn't stay running long enough to attach to it in the traditional manner. With this approach I was able to step through it just like any normal stand-alone exe, and figure out what was wrong.
I understand using this approach bypasses the OnStart() and OnStop() methods when debugging, but in my case those methods don't do much anyway. The OnStart() method starts the same mainLoop() that I am now debugging into, and the OnStop() method just cleans up and writes to a log.
Thanks again.
AJayH
-- modified at 15:46 Friday 18th November, 2005
|
|
|
|
 |
|
 |
Keep always in mind that your service may be using separate components whose correct deployment may depend on the current user profile or registry or permissions.
|
|
|
|
 |
|
 |
True enough. But this technique was always intended as a 'quick and dirty' way to debug a service. There are similar techniques that can be done under .Net to get around security/permissions for a Debug build and ensure that they are on for a Production release.
|
|
|
|
 |
|
 |
If I understand your approach correctly, this lets you run a portion of the service code as a thread when in debug mode. My questions are:
1) Doesn't this bypass the service "events" that are part of the standard service load process?
2) Doesn't this mean that all the code must be in the "threaded" method?
Tom Gueth
Knowledge Resource
Binary Star Technology, Inc
|
|
|
|
 |
|
 |
Yes it does bypass the OnStart, OnStop, etc. So if, for example, you had initialisation taking place in the OnStart, this would have to be put into a separate method then called by the OnStart and the 'DEBUG' block of code in Main() (or the 'threaded' method). So, in effect, it does mean that all of the code you want to debug has to be callable by the 'threaded' method.
The whole objective of this was to provide a crude but simple way to debug the majority of the code in a service without having to go through the rigmarole of attaching a debugging session to an executing service. For instance, this approach makes it easier to actually step through the startup activities assuming that you've done the above.
|
|
|
|
 |