Implementing Delegate In .NET SAP Connector - c#

Quite a specific question and probably basic on some levels. I have a gap in my knowledge of delegates and event handling in general so I'm not surprised that I am a bit stuck. But using Autofac is complicating matters in my understanding even more. I'll try and explain below.
I am connecting to SAP using the .NET V3 SAP connectors and implementing what's known as an RFC Server. As part of that the good people at SAP have exposed an RfcServerErrorEventHandler:
public delegate void RfcServerErrorEventHandler(object server, RfcServerErrorEventArgs errorEventData);
I start my server in a class library in which I have what we'll call a server manager. It is to start the server, stop it and everything inbetween. What I am stuck with is how on earth I can go about using the above delegate in my server manager class, which is injected using AutoFac to my main program with the implementation as below:
public IServerManagerService _ServerManager;
public ApplicationLogic(IServerManagerService serverManager)
{
_ServerManager = serverManager;
}
_ServerManager.StartServer(ServerName);
The above goes to the server manager class and runs the StartServer method obviously. I have attempted to try and register the event (this is where I am hazy) as below in the server manager class:
public void ErrorHandler(object sender, RfcServerErrorEventHandler e)
{
throw new Exception("The method or operation is not implemented.");
}
But can I for the life of me figure out how to either get the delegate hooked up to this or figure out how to do it via autofac. I have had some attempts but I just cant find any examples of this anywhere online. It seems that SAP .NET Connectors are quite a niche thing. The connector documentation provides only very basic code samples also.
I think my problem as mentioned is just a lack of basic event handling techniques possibly or esp when using with DI. I have done a fair amount of reading before posting but just not getting it.
Thanks in advance

This should be explained in any good C# book: see the topics "delegate" and "event". Basically, you can register an event handler at a certain event simply by using the += operator. ("=" should also work, if you are the only one using the RfcServer, but with "+=" you can have more than one subscriber for the event.)
So for example in your case
myServer.RfcServerError += new RfcServer.RfcServerErrorEventHandler(ErrorHandler);
But note, that your defintion of the event handler (method ErrorHandler) is wrong! The second argument should be of type RfcServerErrorEventArgs, not RfcServerErrorEventHandler!
public void ErrorHandler(object sender, RfcServerErrorEventArgs e)
{
// Do something with "e" here. Throwing an exception is probably
// not a good idea...
throw new Exception("The method or operation is not implemented.");
}

Related

Dispose object instance(s) on application exit/crash with WPF / Prism

I'm using the prism framework for my WPF application with DryIoc, but maybe I don't quite understand some of it's uses. (Self-taught) or best practises.
I have a class library (MyLibrary) that follows a disposable pattern as it needs to do some clean-up.
I have a module that uses MyLibrary in its view model.
If the application is closed or even on an application crash, I would like to call dispose on this library, just in case it isn't already disposed of correctly at this time (otherwise it will leave third party apps open in the background)
There is currently only 1 instance, but could be more than 1 in the future.
So far, this is what I have come up with:
When my view model first requires MyLibrary it will register an instance, like so:
this.ce.RegisterInstance<MyLibrary>(this.myLibrary, "MyLibraryName"); where ce is Prism.Ioc.IContainerExtension
and then in the protected override void OnExit(ExitEventArgs e) method in my App.xaml.cs I will do: this.Container.Resolve<MyLibrary>("MyLibraryName")?.Dispose();
This successfully disposes my library object (and closes the 3rd party windows as i expect it to), however, it just seems a bit off to me (Code smell?)
Is there a better way to do it? I don't feel like the App.xaml.cs should have to know about the instance name that my module's view model came up with for example. Is there a way to just call Dispose on all MyLibrary types in the container without the name string?
I was hoping I could iterate over all MyLibrarys in the container and call Dispose?
If there isn't a better way then I'm ok with it I suppose.
But just as important: How can I attempt to call Dispose in a similar fashion on any unhandled exceptions that would otherwise crash the app? Can I access the container somehow and dispose of any MyLibrarys?
I wouldn't intend to try and save the app from crashing, just make sure that MyLibrary calls its Dispose method.
Comment response (Too many characters):
Click UI button> Delegate command> code written in method in VM.
The Library has an overhead to start up(sign in).
There are multiple input steps on the UI that requires use of the library.
Wrapping it in a using at each stage (button click) is not impossible, but it is inefficient because of the libraries startup overhead.
I want to:
- Instantiate library
- User inputs data, library does work, returns results, requires more input etc
- Several more of these data input stages / library work / results
- Dispose
Problem:
- User exits application before library object is disposed
- How/Where to dispose?
Attempted solution:
- Use the container so that i can dispose in App.xaml.cs `OnExit`
- This solution works, but feels incorrect?
Question: What can I do better/different in this situation?
Additional question: How do I handle disposing this upon a fatal crash in a prism app?
It's important that it gets disposed of so that instances of 3rd party apps that the library utilises are not left running in the background.
Ok, I changed it to register an instance in app.xaml.cs now and I can avoid the .Resolve call. Would you do it like this? If not then how? When it was registered as a singleton I had no idea how to get it in OnExit without the .Resolve
Cut-down/simplified example of my app.xaml.cs now:
namespace MyNamespace
{
public partial class App
{
public App()
{
// Crash handling
this.Dispatcher.UnhandledException += this.OnDispatcherUnhandledException;
}
// My library provider that contains a dictionary of library instances.
public IMyProvider MyProvider { get; set; } = new MyProvider();
// Dispose provider on crash
public void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
this.MyProvider.Dispose();
MessageBox.Show("Unhandled exception occurred: \n" + e.Exception.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
protected override Window CreateShell()
{
return this.Container.Resolve<MainWindow>();
}
// Register as an instance?
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterInstance<IMyProvider>(this.MyProvider);
}
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
// Add modules here...
}
protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
// Dispose my provider (and all contained instances in its dictionary)
this.MyProvider.Dispose();
}
}
}
Comment character limit preventing me from writing too much again.
#Haukinger: tl;dr: You got me on the right track.
I didn't quite follow your example exactly to the letter (not using Lazy, library doesnt have an interface), but you got me on the right track.
Overall, I'm struggling to wrap my head around: DI, IoC, Interfaces and how they all relate.
Your line about abusing the container got me to look a little closer at it.
First, I removed all instances of containerExtension.resolve from view models and instead injected into the constructor as it should have always been.
I created a provider similar to what you suggested and a provider interface for my library.
The provider implementation keeps a dictionary of named library instances in case I require multiple.
I still call this.Container.Resolve<IMyProvider>().Dispose(); in the application's OnExit but it feels better because I don't have to name an instance any more.
Just having a provider interface still doesn't stop anyone from new-ing up library instances themselves though?
Library interface is registered like so:
containerRegistry.RegisterSingleton<IMyProvider, MyProvider>();
Other than my library:
I'm currently registering a few application wide instances for a few things like application theme in the container like so: containerRegistry.RegisterInstance<MyThing>(this.MyThing);
Still not using interfaces here. Still trying to understand them, but an application wide instance for theme in the container is working just fine.
From examples I've seen where IAnimal interface can have a Dog and a Cat implementation, my objects don't have multiple implementation requirements. (Besides unit testing which I'm yet to attempt to learn and I assume I will benefit from interfaces in this situation) I just need access to some things from different modules/assemblies and was using the container to do so.
One of my biggest problems was that I have parameters to construct some instances like my library and the parameters are not known until run time, so I couldn't register an instance in app.xaml.cs when the app starts.
If I have to construct something with parameters that are only known at runtime (credentials for example) Do I need to follow a sort of factory pattern with an interface to be able to register them or am I missing something?
I guess I could register an instance with the container extension at the time they get created (in assembly A's view model A)? but then I would need to use .Resolve later if I want them in a different module (Assembly B's view model X)?
Which doesn't feel right, and creating a factory and a factory interface for a simple credentials object feels overkill?
I think I'm just not fully understanding interfaces, as examples I've seen often dont have parameters for the implementation or they focus on discussing the benefits of different implementations when I will only have 1 implementation.
Or examples have nothing to do with IoC or DI.
As far as handling disposing on application crash event I did the following:
public App()
{
this.Dispatcher.UnhandledException += this.OnDispatcherUnhandledException;
}
public void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
// Dispose provider
this.Container.Resolve<IMyProvider>().Dispose();
// Unhandled exception messagebox:
MessageBox.Show("Unhandled exception occurred: \n" + e.Exception.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
I'm still tearing my hair out over interfaces / factory pattern / DI / Ioc / General design, but you got me on the right track.
I'm injecting stuff into constructors better, I can manage my library instances with the provider and dispose on exit and on crash is working.
Thanks.
I suggest you do not try to abuse the container here.
Instead, create a manager for your library yourself and clean that one up at shutdown:
public interface ILibraryProvider : IDisposable
{
ILibrary GetLibrary();
}
internal class LibraryProvider : ILibraryProvider
{
public LibraryProvider( Lazy<ILibrary> library )
{
_library = library;
}
#region ILibraryProvider
public ILibrary GetLibrary() => _library.Value;
public void Dispose()
{
if (_library.IsValueCreated)
_library.Value.Dispose();
}
#endregion
#region private
private readonly Lazy<ILibrary> _library;
#endregion
}
In Application.OnExit, dispose the LibraryManager.
If you need multiple, distinct libraries, add a string parameter to Get, inject a Func instead of a Lazy and store the instances in a Dictionary.

How to make a listener of a service on android

I have this code to check if a service is active, but I would like to know if there is any way for an EditText to show the status of the service, without making this query per second, or in a separate thread, or linking it in some way? that it is possible to detect if the service stopped
private bool MiServicioEstaCorriendo(Class #class, Context contexto)
{
ActivityManager manager = (ActivityManager)contexto.GetSystemService(Context.ActivityService);
foreach (ActivityManager.RunningServiceInfo service in manager.GetRunningServices(Integer.MaxValue))
{
if (#class.Name.Equals(service.Service.ClassName))
{
Log.Info(typeof(BroadcastGps).Name, "MiServcicioEstaCorriendo: true");
return true;
}
}
Log.Info(typeof(BroadcastGps).Name, "MiServcicioEstaCorriendo: false");
return false;
}
You are basically in need of a way to pass events/messages among classes within your application. So this question probably goes down to Android & C# implementation of such a pattern. Xamarin.Forms has a MessagingCenter class, but since you are using Xamarin.Native, you would have to create something yourself
There's nothing actually already baked in to Android or C#, but so you can implement one of the most common ways to let a class spread an event/message using the "Listener" (term used in Android) or "Delegate" (term used in C#) technique.
There are frameworks too like PubNub that you can use as Nuget packages that simplify everything for you.
Some more resources to understand the concept: Wikipedia, IBM.
And Some Android resources: Handlers, AsyncTasks, Parcelables.
Don't forget that your event to update your EditText may not be fired on the Main UIThread so you won't be able to see the changes unless you force that update line to be Run on UI Thread.

C# Windows Service, Timer won't tick

I have poked around here to try and find a resolved issue to help me solve my problem. Unfortunately I don't know enough about C# and Forms/Services to be able to interpret many of the answers, so I thought I'd post my issue here, in it's uniqueness, and see if I can get a sufficient answer.
I recently got an internship for a local company, learning C# and SQL to manage their shipping/inventory logistics.
I have gotten pretty good at creating windows forms with VisualStudios2017, and my knowledge of Java helps me pick up C# pretty quickly.
However, recently I was given the task of developing a Windows Service, which will run in the background, and do some repetitive task every minute or so.
Since I am familiar with the "Drag and Drop" techniques of adding features to windows forms, My supervisor suggested I use a Timer in my service, so, that's what I did, I did a "Drag and Drop" to add the timer component to my service, and renamed it "timerMainTick"
Here is My code. I want to start simple, all this code does is move to some local directory (henceforth referred to as $DIR), create a folder $DIR/GabbServiceDir, and make a text file $DIR/GabbServiceDir/AnotherTest.txt". However, every time the timer ticks, it is supposed to create (if it does not already exist) a new text document "$DIR/GabbServiceDir/Test.txt" and append the date-time to it every 2.5 seconds. This does not happen.
namespace GabbService
{
public partial class GabbService : ServiceBase
{
public string dir = "../../Users/Tyler/GabbServiceDir";
public GabbService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Directory.CreateDirectory(dir);
timerMainTick.Interval = 2500; //miliseconds = 2.5seconds
File.AppendAllText(dir + "/AnotherTest.txt","asdiofbhjasdflikjbasdf\r\n");
timerMainTick.Enabled = true;
timerMainTick.Start();
}
protected override void OnStop()
{
}
private void timerMainTick_Tick(object sender, EventArgs e)
{
timerMainTick.Enabled = false;
File.AppendAllText(dir + "/Test.txt", DateTime.Now.ToString() + "\r\n");
timerMainTick.Enabled = true;
}
}
}
And a picture of the directory and it's contents after the service was started.
This is in Powershell, in $DIR/GabbServiceDir
PS C:\Users\Tyler\GabbServiceDir> ls
Directory: C:\Users\Tyler\GabbServiceDir
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 6/23/2017 9:54 PM 72 AnotherTest.txt
PS C:\Users\Tyler\GabbServiceDir> cat .\AnotherTest.txt
asdiofbhjasdflikjbasdf
timerMainTick is Windows.Forms.Timer, and many of the solutions provided indicate to use a different kind of timer, the System.Timers.Timer.
This is all well and good, and may fix my problem, but the issue comes when trying to do something when this new type of timer ticks. When I double click the Windows.Forms.Timer in the Service Designer, it automagically writes a bunch of source, and gives me a method to begin writing code in, that magically executes when the timer ticks. I am not yet familliar with all of the magic that is going on in the backround, because I've only begun to learn C# as of the day I got this internship. I don't know what to name the methods for custom objects so that the "backround magic" will work, thus I am unable to interperate some of the solutions provided for problems similar to mine.
Perhaps someone could enlighten me.
For instance. Say I go into the Designer Source Code, and add a component
private System.Timer.Timer timerSystemTimer;
Then, in the Service source code and alter the method that was previously
private void timerMainTick_Tick(object sender, EventArgs e)
To
private void timerSystemTimer_Tick(object sender, EventArgs e)
I get an error immediately:
The more reading I do the more I see lots of event handlers being passed around and I have yet to comprehend what they do. Perhaps what I need is a link to some good literature. I am capable of looking for this on my own but I imagine many people here may have links to other bits of good literature more specific to what I want to comprehend here.
*Something I have found so far that may be useful to people in my situation:
https://msdn.microsoft.com/en-us/library/aa288459(v=vs.71).aspx
Error in VS - You added timerSystemTimer but did not remove timerMainTick component which still references timerMainTick_Tick as handler of it's Tick event. Compiler does not find this handler method anymore since you changed it to timerSystemTimer_Tick.
Adding different timer - Never modify designer file code. You could add a System.Timers.Timer instance to your class code, instantiate it in OnStart and provide handler for Elapsed event. Here's a sample for you.

Executing UI Code from ViewModel on MVVMCross

I have just started using MvvmCross, but i didn't find any info about to how i can execute UI code from a ViewModel.
On Caliburn there are coroutine so i can access the view and keep the ui code separated from the viewmodel code.
on my first case i need to open a dialow from a command inside a ViewModel, what is the correct way?
Right now i'm developing a WinRT app.
Thanks
There isn't any hard/fast rule on this within MvvmCross.
Generally, when I need to do this I use the Messenger plugin.
This answer assumes you are using the latest Alpha v3 code. For older vNext code you'll have to do some translation - see notes below.
To use this approach:
I reference Cirrious.MvvmCross.Plugins.Messenger.dll from both Core and UI projects.
Then I add a line somewhere in Setup.cs (e.g. in InitializeLastChance) to:
Cirrious.MvvmCross.Plugins.Messenger.PluginLoader.Instance.EnsureLoaded();
Then in the Core project I add a message:
public class InputIsNeededMessage : MvxMessage
{
public InputIsNeededMessage(object sender) : base(sender) {}
}
In the ViewModel I can get the Messenger by constructor injection or by:
var messenger = Mvx.Resolve<IMvxMessenger>();
and I can send messages by calling:
messenger.Publish(new InputIsNeededMessage(this));
In the View I can again get to the messenger and subscribe to messages using:
var messenger = Mvx.Resolve<IMvxMessenger>();
_token = messenger.SubscribeOnMainThread<InputIsNeededMessage>(OnInputIsNeeded);
where _token must be a member variable - if it isn't then the subscription won't persist - the subscription itself is weak by default (so you never have to unsubscribe)
and where OnInputIsNeeded is something like:
private void OnInputIsNeeded(InputIsNeededMessage message)
{
if (message.Sender != ViewModel)
return;
// do stuff here - you are already on the UI thread
}
The above sequence is what I normally do for 'proper code'
To start with using a Messenger/EventAggregator can feel uncomfortable - it certainly took me a while to get used to it - but after I did get used to it, then I now use it everywhere - the pub/sub Message decoupling is very flexible for testing and for future maintenance of code (IMO)
As alternatives to this approach above I do sometimes take shortcuts:
sometimes I fire normal C# events from the ViewModel and have the View respond to these
sometimes I have special marker properties and fire the UI code from them
Sorry for using v3 syntax - but the changeover is coming and it's what I'm now coding in...
To switch back to vNext I think you might need to:
use IMessenger instead of IMvxMessenger
use BaseMessage instead of the MvxMessage
use Subscribe instead of SubscribeOnMainThread - but then you will need to marshall the message onto the UI thread yourself.
There exists an easier way. Here is the method I use for executing any action on the main
thread:
protected void RunOnUIThread(Action action) {
var dispatcher = Mvx.Resolve<IMvxMainThreadDispatcher>();
dispatcher.RequestMainThreadAction(action);
}
Hope it helps. Cheers.

Detect/listen for service start and stop state changes

I have a C# application that uses a Windows service that is not always on and I want to be able to send an email notification when the service starts and when it shuts down. I have the email script written, but I cannot seem to figure out how to detect the service status changes.
I have been reading up on the ServiceController class and I think that the WaitForStatus() method might be what I need, but I haven't been able to find an example with it being used on a service that is not yet started. EDIT: Due to the fact that the WaitForStatus() method busy-waits and I need to be executing the rest of the program run by the service while listening for the service to start/stop, I don't think that this is the method for me, unless someone has a solution that uses this method combined with multithreading and is clean and efficient.
More:
the service will not be started by the application - the application user will be starting that directly from the Services window in the Administrative Tools.
the service used is not a default Windows service - it is a custom service designed for use with this application
Thanks for your help!
P.S. please note that I'm fairly new to C# and am learning as I go here.
UPDATE:
I have managed to get the alert email to send each time the service starts: As I continued to read through the code that I have (which I, unfortunately, cannot post here), I noticed that the class used to create the service was extending the ServiceBase class and that someone made a custom OnStart() method to override the default one. I added the necessary method calls to the new OnStart() method and it successfully sent the notifications.
I attempted to do the same thing for the OnStop() method, but that did not work out so well for me - before I continue, I would like to add that I have been programming in Java for several years, and I am very familiar with Java design patterns.
What I attempted to do, which would have worked in Java, was override the ServiceBase class's OnStop() method with one that calls the email notification, cast MyService to be of type ServiceBase and then re-call the ServiceBase class's Stop() method (NOTE: OnStop() is a protected method so it could not be called directly - the Stop() method calls OnStop() and then continues with the necessary code to stop the service). I thought that casting to type ServiceBase would force the default OnStop() method to be called, instead of my custom one.
As you may imagine, I ended up with just under 10,000 emails successfully sent to my inbox before I managed to force my computer into a hard shutdown.
What I need now is a way to either use my overridden OnStop() method and then have it call the default method, or another solution to this problem. Any and all help is much appreciated. Thanks so much.
FOR THOSE OF YOU WITH MULTITHREADING SOLUTIONS:
protected override void OnStart(string[] args) {
string subject = "Notice: Service Started";
string body = "This message is to notify you that the service " +
"has been started. This message was generated automatically.";
EmailNotification em = new EmailNotification(subject, body);
em.SendNotification();
...INITIALIZE LISTENER FOR SERVICE STOPPING HERE...
...custom stuff to be run on start...
}
Also, remember that the class that this method is called in, let's call it Service, extends the ServiceBase class.
UPDATE TWO:
In regards the suggestion that I use NotifyServerStatusChange I have learned that it is not permitted for the solution to use system functions, due to various reasons. To clarify, only solutions that are purely within the scope of C# and .NET are viable. Thanks, again, for your help!
Here is the solution and why I could not find it before: As I said earlier, my class extended the ServiceBase class. In my first update, I posted that I attempted to solve this in the same way I would have solved it with Java: through casting. However, in C# casting apparently doesn't let you call the base method if you overrode it in the derived class. One of the things that I did not know when I first posted this question and this update (and clearly one of the things that no one thought of) was that C# includes the base constructor that can be used to call methods of the base class from a derived class. As the base constructor can be used for any class in C# it does not appear in the ServiceBase Class documentation.
Once I learned this, I was able to take my original solution and modify it to use the base class:
protected override void OnStop() {
string subject = "Notice: Service Stopped";
string body = "This message is to notify you that the service has " +
"been stopped. This message was generated automatically.";
EmailNotification em = new EmailNotification(subject, body);
em.SendNotification();
base.OnStop();
}
I figured this out when I was playing around with the code in Visual Studio and noticed base in my IntelliSense. I clicked to go to its definition and it sent me to ServiceBase (where it was obviously not defined). After noticing that base was not defined in my code and that it was an instance of the ServiceBase class I realized that it must have been some sort of constructor. After a quick Google search, I found what I was looking for. Way to go IntelliSense!
Thank you everyone for all your help!
If you want a .NET solution with no win32 api then check out my solution below. I'm inheriting from the ServiceController class and using the WaitForStatus() inside of a Task to make it non-blocking then raising events when the status changes. Perhaps it needs more testing but works for me:
CLASS DEFINITION
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.ServiceProcess; // not referenced by default
public class ExtendedServiceController: ServiceController
{
public event EventHandler<ServiceStatusEventArgs> StatusChanged;
private Dictionary<ServiceControllerStatus, Task> _tasks = new Dictionary<ServiceControllerStatus, Task>();
new public ServiceControllerStatus Status
{
get
{
base.Refresh();
return base.Status;
}
}
public ExtendedServiceController(string ServiceName): base(ServiceName)
{
foreach (ServiceControllerStatus status in Enum.GetValues(typeof(ServiceControllerStatus)))
{
_tasks.Add(status, null);
}
StartListening();
}
private void StartListening()
{
foreach (ServiceControllerStatus status in Enum.GetValues(typeof(ServiceControllerStatus)))
{
if (this.Status != status && (_tasks[status] == null || _tasks[status].IsCompleted))
{
_tasks[status] = Task.Run(() =>
{
try
{
base.WaitForStatus(status);
OnStatusChanged(new ServiceStatusEventArgs(status));
StartListening();
}
catch
{
// You can either raise another event here with the exception or ignore it since it most likely means the service was uninstalled/lost communication
}
});
}
}
}
protected virtual void OnStatusChanged(ServiceStatusEventArgs e)
{
EventHandler<ServiceStatusEventArgs> handler = StatusChanged;
handler?.Invoke(this, e);
}
}
public class ServiceStatusEventArgs : EventArgs
{
public ServiceControllerStatus Status { get; private set; }
public ServiceStatusEventArgs(ServiceControllerStatus Status)
{
this.Status = Status;
}
}
USAGE
static void Main(string[] args)
{
ExtendedServiceController xServiceController = new ExtendedServiceController("myService");
xServiceController.StatusChanged += xServiceController_StatusChanged;
Console.Read();
// Added bonus since the class inherits from ServiceController, you can use it to control the service as well.
}
// This event handler will catch service status changes externally as well
private static void xServiceController_StatusChanged(object sender, ServiceStatusEventArgs e)
{
Console.WriteLine("Status Changed: " + e.Status);
}
The ServiceController class has a WaitForStatus method. Internally it does polling, though.
If you can't PInvoke NotifyServiceStatusChange, then you'll have to poll the service. For example:
ServiceController sc = new ServiceController("Some Service");
Console.WriteLine("Status = " + sc.Status);
You can use wmi to monitor for events: technet.microsoft.com/en-us/library/ff730927.aspx
Be very carefull with the use of NotifyServiceStatusChange(), because it is only supported on Windows Vista/Windows 2008 (and above). If you target any platforms below, you can't use that API. (There are still lots of XP/Windows 2000-2003 systems out there.)
To make it even worse, polling will not be always reliable in case of service restarts, because if you are polling a service on a very fast system (SSD-drives or pre-buffered I/O on virtual machines), the service might restart between two polls.

Categories