MonoDroid: Unhandled Exception Recovery - c#

I'm trying to add a default handler to my application so I can recover from otherwise unhandled exceptions.
I've found three mechanisms provided by Android/MonoDroid that, as far as I can tell, should make this possible, but I cannot get any of them to work. Here's my code:
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
namespace TestApp {
[Android.App.Activity(Label = "TestApp", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity {
protected override void OnCreate(Bundle bundle) {
base.OnCreate(bundle);
SetContentView(new LinearLayout(this));
//set up handlers for uncaught exceptions:
//Java solution
Java.Lang.Thread.DefaultUncaughtExceptionHandler = new ExceptionHandler(this);
//MonoDroid solution #1
AndroidEnvironment.UnhandledExceptionRaiser += AndroidEnvironment_UnhandledExceptionRaiser;
//MonoDroid solution #2
AppDomain.CurrentDomain.UnhandledException += delegate { new Alert(this, "AppDomain.CurrentDomain.UnhandledException", "error"); };
//throw an exception to test
throw new Exception("uncaught exception");
}
void AndroidEnvironment_UnhandledExceptionRaiser(object sender, RaiseThrowableEventArgs e)
{
//found a suggestion to set the Handled flag=true, but it has no effect
new Android.Runtime.RaiseThrowableEventArgs(e.Exception).Handled = true;
new Alert(this, "AndroidEnvironment.UnhandledExceptionRaiser", "error");
}
}
public class ExceptionHandler : Java.Lang.Object, Java.Lang.Thread.IUncaughtExceptionHandler {
private Context _context;
public ExceptionHandler(Context c) { _context = c; }
public void UncaughtException(Java.Lang.Thread thread, Java.Lang.Throwable ex) {
new Alert(_context, "java exception handler");
}
}
public class Alert {
public Alert(Context c, string src, string title = "alert") {
Android.App.AlertDialog.Builder builder = new Android.App.AlertDialog.Builder(c);
builder.SetTitle(title);
builder.SetMessage(src);
builder.SetPositiveButton("Ok", delegate { });
Android.App.AlertDialog alert = builder.Create();
alert.Show();
}
}
}
Any help would be appreciated, thanks!

You can catch most of exceptions in AppDomain.CurrentDomain.UnhandledException event. But you can't call AlertDialog in this delegate, because:
1. Application is crashed.
2. UnhandledException event is called at least.
3. alert.Show() is executed async (in UI thread)
So, you should use sync operations (System.IO, for example). You shouldn't use native UI operations, because they are async.

Related

C# How to replace an Event by a Delegate?

Mac OS, VS Community, C#, Cocoa application.
The following code generates a run time error.
using AppKit;
using CoreGraphics;
using Foundation;
using System;
namespace NSTextFieldValidation
{
public partial class ViewController : NSViewController
{
public ViewController(IntPtr handle) : base(handle) { }
public override void ViewDidLoad()
{
base.ViewDidLoad();
var fm = new NSNumberFormatter { Maximum = 999, Minimum = 0 };
NSTextField Tbx1 = new NSTextField(new CGRect(10, 50, 100, 30));
View.AddSubview(Tbx1);
Tbx1.Formatter = fm;
Tbx1.Delegate = new MyTextFieldDelegate();
Tbx1.DidFailToValidatePartialString += TbxDidFailToValidatePartialString;
}
private void TbxDidFailToValidatePartialString(object sender, NSControlTextErrorEventArgs e)
{
Console.WriteLine("DidFailToValidatePartialString activated");
}
}
public class MyTextFieldDelegate : NSTextFieldDelegate
{
override public void EditingEnded(NSNotification notification)
{
Console.WriteLine("EditingEnded");
}
}
}
Here's the exception:
System.InvalidOperationException
Event registration is overwriting existing delegate. Either just use
events or your own delegate: NSTextFieldValidation.MyTextFieldDelegate
AppKit.NSTextField+_NSTextFieldDelegate
I understand that it is not correct to use event and delegate at the same time. I only ask which method I need to override in my delegate to deal with "DidFailToValidatePartialString", because I did not find it (perhaps I did not look well).
In the Delegate class, the DidFailToValidatePartialString method is not declared like others (i.e EditingEnded). We need to add an Export attribute:
[Export("control:didFailToValidatePartialString:errorDescription:")]
I would like the Xamarin documentation to explain this.

Xamarin displayalert not showing

I have xamarin form application and i connected it signalr not running my void. I searched on internet but I can't find anything about this. And this is my code
Myhub.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR.Client;
namespace PharmClient
{
class MyHub
{
string url = "https://webapplication11-co5.conveyor.cloud/";
HubConnection Connection;
IHubProxy ProxyOFServer;
public delegate void Error();
public delegate void MessageRecieved(string _data);
public event Error CoonectionError;
public event MessageRecieved OndataRecieved;
public delegate void Completed();
public event Completed OnCompleted;
public void Connect()
{
Connection = new HubConnection(url);
ProxyOFServer = Connection.CreateHubProxy("MuHub");
Start().ContinueWith(task => { if (task.IsFaulted) { CoonectionError?.Invoke(); } else { OnCompleted?.Invoke(); } });
}
public Task Start()
{
return Connection.Start();
}
public void SendData(string data)
{
ProxyOFServer.Invoke<string>("SendMessage", data);
}
public void Recive( )
{
ProxyOFServer.On<string>("Sentdata", data => { OndataRecieved?.Invoke(data); });
}
}
}
MainPage.xaml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using System.Threading;
namespace PharmClient
{
// Learn more about making custom code visible in the Xamarin.Forms previewer
// by visiting https://aka.ms/xamarinforms-previewer
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
MyHub ConnectServer = new MyHub();
public MainPage()
{
InitializeComponent();
NavigationPage.SetHasNavigationBar(this, false);
ConnectServer.OnCompleted += ConnectServer_OnCompleted;
ConnectServer.CoonectionError += ConnectServer_CoonectionError;
ConnectServer.Connect();
}
private void ConnectServer_OnCompleted()
{
DisplayAlert("Connected", "Good", "O");
}
private void ConnectServer_CoonectionError()
{
DisplayAlert("Failed", "Bad", "Ok");
}
private void SerchDrug_Clicked(object sender, EventArgs e)
{
Navigation.PushAsync(new SearchDrug());
}
}
}
When connection failed ConnectionError event run but Connection will be successfully OnCompleted event won't run. I am student. This is part of group work. What is problem my code any Help. I can't found anything. Thanks for attention
As your title suggest, you have an issue with displaying a dialog box.
Try going through the documentation (here) once for complete understanding, you have to await the process of displaying DisplayAlert.
Add await & async to your methods.
Try this -
private async void ConnectServer_OnCompleted()
{
await DisplayAlert("Connected", "Good", "O");
}
private async void ConnectServer_CoonectionError()
{
await DisplayAlert("Failed", "Bad", "Ok");
}
If you have some issues regarding, let me know.
You should await connection not fire and forget. Example:
private HubConnection connection;
private IHubProxy proxy;
public event EventHandler<ChatMessageObject> OnMessageReceived;
public async Task Connect()
{
try
{
await connection.Start();
await proxy.Invoke("Connect"); // example method in your backend
proxy.On("messageReceived", (int userId, string name, string message, DateTime messageDateTime) => OnMessageReceived(this, new ChatMessageObject
{
FromUserId = userId,
UserName = name,
MessageText = message,
MessageDateTime = messageDateTime
}));
}
catch (Exception ex)
{
//handle exceptions
}
}

Backup catching for exception thrown in EventHandler

I have a C# Program running as a Windows service doing some Network shenanigans
I thought I had last-ditch "Log Fatal Errors" handling set up. But I've come across an edge case where the Service ends up dead but dodges those catches. :(
I believe this is caused by code throwing an Exception in the EventHandler registered to a .NET library's event.
Obviously I can (andshould!) catch the Exception in my handler, but I'd like to understand how this is avoiding my fall-back error handling, and whether I can add some even more robust fall back logging, to ensure that I have some log records to analyse similar silent bugs in future.
The punchline of relevant code isn't terribly complex:
ServiceBase.Run(container.Resolve<MyProjectWindowsService>()); in a try ...catch in Program.Main()
MyProjectWindowsService : ServiceBase is the service object with an OnStop() implmentation.
NetworkChange.NetworkAvailabilityChanged += CodeThatThrows;
But when that Exception is thrown, neither OnStop() nor the try...catch trigger.
I can get it in a debugger, and it doesn't seem to go anywhere .. it just ... stops.
Fuller program details below, if you want them.
How can I catch and log unhandled exceptions in Event Handlers registered to external library events?
(Also ... Is the behaviour I've described above the expected behaviour, or is there something slightly weird happening?)
Program EXE entry point:
using System;
using System.ServiceProcess;
using Autofac;
using Autofac.Extras.NLog;
using NLog;
namespace MyProject.Service
{
internal static class Program
{
private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();
/// <summary>
/// The main entry point for the application.
/// </summary>
private static void Main()
{
try
{
// var container = ...DI Setup...
ServiceBase.Run(container.Resolve<MyProjectWindowsService>());
}
catch (Exception ex)
{
Logger.Error(ex, "Unexpected error");
}
finally
{
Logger.Info("==========================");
Logger.Info("WindowsService Stopped (2)");
Logger.Info("==========================");
}
}
}
}
Service Object
using System;
using System.ServiceModel;
using System.ServiceProcess;
using Autofac;
using Autofac.Integration.Wcf;
using NLog;
namespace MyProject.Service
{
public class MyProjectWindowsService : ServiceBase
{
private readonly ILogger _logger;
public DNSProxyWindowsService(ILogger logger)
{
ServiceName = Constants.SERVICE_NAME;
_logger = logger;
}
protected override void OnStart(string[] args)
{
_logger.Info("==============================");
_logger.Info("DNProxy WindowsService Started");
_logger.Info("==============================");
//Other Active setupsteps
}
protected override void OnStop()
{
try
{
//Other Active shutdown steps.
}
catch (Exception ex)
{
_logger.Error(ex, "Could not shut down service tidily");
}
finally
{
_logger.Info("==========================");
_logger.Info("WindowsService Stopped (1)");
_logger.Info("==========================");
}
}
}
}
EventListener Registered to and ultimately invoked:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using NLog;
using Exception = System.Exception;
namespace DNSProxy.Service
{
public class NetworkService
{
public NetworkService()
{
}
public bool NetworkDetectionEnabled
{
set
{
if (value)
{
NetworkChange.NetworkAvailabilityChanged += OnNetworkAvailabilityChanged;
NetworkChange.NetworkAddressChanged += OnNetworkAddressChanged;
}
else
{
NetworkChange.NetworkAvailabilityChanged -= OnNetworkAvailabilityChanged;
NetworkChange.NetworkAddressChanged -= OnNetworkAddressChanged;
}
}
}
private void OnNetworkAddressChanged(object sender, EventArgs e)
{
CodeThatCanApparentlyThrow();
}
private void OnNetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
CodeThatCanApparentlyThrow();
}
}
}
I unfortunately can only speculate why the exception isn't being caught by your code (and I've kept that speculation to the comments)
However 2 events that might help you are,
AppDomain.UnhandledException - this allows you to register a global handler for any unhandled exceptions in your application. Here is the documentation https://learn.microsoft.com/en-us/dotnet/api/system.appdomain.unhandledexception?view=netframework-4.8
TaskScheduler.UnobservedTaskException - I've included this as I'm not familiar with the internals of the framework libraries you are using, but there maybe some asynchronous code happening somewhere, that is potentially not observing the result of a task. If a faulted task (ie an exception was thrown) is never awaited or never has the Result property accessed and then goes out of scope so it can be garbage collected; at some indeterminate point in the future, it will get collected and an UnobservedTaskException will get thrown. Subscribing to this event, will let you handle that scenario. Documentation here
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskscheduler.unobservedtaskexception?view=netframework-4.8
A little bit dig out what catches what on a WPF application :
var domain = AppDomain.CurrentDomain;
domain.UnhandledException += (o, args) =>
{
Debug.WriteLine("Catched in UnhandledException");
Debug.WriteLine(args.ExceptionObject);
};
domain.FirstChanceException += (o, args) =>
{
Debug.WriteLine("Catched in FirstChanceException");
Debug.WriteLine(args.Exception);
};
TaskScheduler.UnobservedTaskException += (o, args) =>
{
Debug.WriteLine("Catched in UnobservedTaskException");
Debug.WriteLine(args.Exception);
};
Task.Factory.StartNew(async () =>
{
Debug.WriteLine("Workinf");
await Task.Delay(1000);
try
{
throw new Exception("oops");
}
catch (Exception exception)
{
throw new Exception("oopps catched", exception);
}
});
The output will be :
Exception thrown: 'System.Exception' in WpfApp1.exe
Catched in FirstChanceException
System.Exception: oops
at ....
Exception thrown: 'System.Exception' in WpfApp1.exe
Catched in FirstChanceException
System.Exception: oopps catched ---> System.Exception: oops
at ...
--- End of inner exception stack trace ---
at ...
So FirstChanceException will be catching everything (even the handled ones) and the rest won't be catching anything. My suggestion is modifying your example like this:
public class NetworkService
{
private readonly SynchronizationContext currContext;
public NetworkService()
{
this.currContext = SynchronizationContext.Current;
}
private void OnNetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
try
{
CodeThatCanApparentlyThrow();
}
catch (Exception exception)
{
this.currContext.Post(s => throw exception, null); // this will propagate your exception into main thread
}
}
}

Is it possible to show DisplayAlert on startup (Xamarin.Forms)

In my mobile application (xamarin forms), I'm getting data from internet so it needs internet connection. Since I have a dictionary which I initialize in App.xaml.cs and I use data from internet, I need to check for internet connection. I have seen this question where OP asks for something similar, but the answer doesn't work for me since I need to check for internet connection whenever app launches, not after MainPage is launched. For example, Clash of Clans. Whenever the app launches, the app checks for internet connection and if there's no connection, it displays a alert to user repetitively until there's a connection.
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using System.Collections.Generic;
using HtmlAgilityPack;
using System.Text.RegularExpressions;
using System;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace Multi
{
public partial class App : Application
{
static GroupStage groupstage = new GroupStage();
public static HtmlWeb web = new HtmlWeb();
public static HtmlDocument doc = LoadUrlAndTestConnection();
//The reason why I have put a method is because I wanted to try if I can use try-catch to display alert, however this didn't work.
public static HtmlDocument LoadUrlAndTestConnection()
{
bool con = true;
while (con)
{
try
{
doc = web.Load(someURL);
}
catch (Exception ex)
{
var sth = new ErrorPage();
sth.InternetErrorDisplay();
con = true;
continue;
}
con = false;
}
return docSK;
}
public static Dictionary<string, Country> _countries = new Dictionary<string, Country>
{
["Australia"] = new Country(1, "Australia", false, "AU", "ausFlag.png", 3, groupstage, GetScore("Australia", 3)),
public static string[] GetScore(string name, int GroupID)
{
//Gets the score data from internet
}
public App()
{
InitializeComponent();
TwitchClass.MainAsync().Wait();
MainPage = new OpeningPage();
}
protected override void OnStart()
{
}
protected override void OnSleep()
{
}
protected override void OnResume()
{
}
}
}
//GetScore method requires internet connection as it gets the score data from internet.
and the InternetErrorDisplay method is,
public void InternetErrorDisplay() => DisplayAlert("Connection Error", "Could not detect internet connection. This application requires access to internet.", "Retry");
Is it possible to have this behaviour in xamarin forms app? How can I achieve it?
Yes, why should it not be possible?
Here is an example which uses async/await
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using System.Threading.Tasks;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace LoadingSample
{
public partial class App : Application
{
public App()
{
InitializeComponent();
//MainPage = new MainPage();
}
protected override async void OnStart()
{
// shows Loading...
MainPage = new LoadPage();
await Task.Yield();
// Handle when your app starts
// Just a simulation with 10 tries to get the data
for (int i = 0; i < 10; i++)
{
await Task.Delay(500);
// await internet_service.InitializeAsync();
await MainPage.DisplayAlert(
"Connection Error",
"Unable to connect with the server. Check your internet connection and try again",
"Try again");
}
await Task.Delay(2000);
// after loading is complete show the real page
MainPage = new MainPage();
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}

Raising Custom Class Events In Windows Service C#

I did write a windows service that can connect to a network device using a dll. so everything works fine, but The event handler does not work in win service! here is my code :
My Custom Class Code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyNewService
{
public class zkemkeeperHandler
{
public event EventHandler OnFinger;
public event EventHandler<VerifyEventArgs> OnVerify;
private System.Diagnostics.EventLog eventLog1 = new System.Diagnostics.EventLog();
public zkemkeeper.CZKEMClass axCZKEM1 = new zkemkeeper.CZKEMClass();
private bool bIsConnected = false;
private int iMachineNumber = 1;
public zkemkeeperHandler()
{
((System.ComponentModel.ISupportInitialize)(this.eventLog1)).BeginInit();
this.eventLog1.Log = "DoDyLog";
this.eventLog1.Source = "DoDyLogSource";
((System.ComponentModel.ISupportInitialize)(this.eventLog1)).EndInit();
eventLog1.WriteEntry("zkemkeeperHandler constructor");
}
public void startService()
{
eventLog1.WriteEntry("start service for (192.168.0.77:4370)");
bIsConnected = axCZKEM1.Connect_Net("192.168.0.77", Convert.ToInt32("4370"));
if (bIsConnected == true)
{
eventLog1.WriteEntry("bIsConnected == true !");
iMachineNumber = 1;
if (axCZKEM1.RegEvent(iMachineNumber, 65535))
{
this.axCZKEM1.OnFinger += new kemkeeper._IZKEMEvents_OnFingerEventHandler(axCZKEM1_OnFinger);
this.axCZKEM1.OnVerify += new zkemkeeper._IZKEMEvents_OnVerifyEventHandler(axCZKEM1_OnVerify);
//This Log Appears in Event Viewer
eventLog1.WriteEntry("Define events (OnFingers and OnVerify) !");
//This Line Fires Event in Service1.cs for testing event handler
Finger(EventArgs.Empty);
}
}
else
{
eventLog1.WriteEntry("Unable to connect the device");
}
}
public void stopService()
{
if (bIsConnected) {axCZKEM1.Disconnect(); bIsConnected = false;}
}
//This method doesn't run :(
private void axCZKEM1_OnFinger()
{
Finger(EventArgs.Empty);
}
//This method doesn't run too :(
private void axCZKEM1_OnVerify(int iUserID)
{
VerifyEventArgs args = new VerifyEventArgs();
args.UserID = iUserID;
Verify(args);
}
public class VerifyEventArgs : EventArgs
{
public int UserID { get; set; }
}
protected virtual void Finger(EventArgs e)
{
EventHandler handler = OnFinger;
if (handler != null)
handler(this, e);
}
protected virtual void Verify(VerifyEventArgs e)
{
EventHandler<VerifyEventArgs> handler = OnVerify;
if (handler != null)
handler(this, e);
}
}
}
My Main Service Class Code :
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Linq;
using System.Threading;
namespace MyNewService
{
public class Service1 : System.ServiceProcess.ServiceBase
{
private System.Diagnostics.EventLog eventLog1;
private System.ComponentModel.Container components = null;
zkemkeeperHandler zkh;
public Service1()
{
InitializeComponent();
if (!System.Diagnostics.EventLog.SourceExists("DoDyLogSource"))
{
System.Diagnostics.EventLog.CreateEventSource("DoDyLogSource", "DoDyLog");
}
eventLog1.Source = "DoDyLogSource";
eventLog1.Log = "DoDyLog";
eventLog1.WriteEntry("Preparing to start service");
try
{
startZKHandler();
}
catch (Exception ex)
{
eventLog1.WriteEntry(ex.InnerException.Message);
}
}
private void startZKHandler()
{
eventLog1.WriteEntry("creating zkemkeeper handler class");
zkh = new zkemkeeperHandler();
zkh.OnFinger += OnFinger;
zkh.OnVerify += OnVerify;
zkh.startService();
}
private void stopZKHandler()
{
eventLog1.WriteEntry("Disconnecting from device (192.168.0.77)...");
zkh.stopService();
}
private void writeLog2DB(string message)
{
try
{
eventLog1.WriteEntry("writing to database");
DB.DBase.LogTable.AddObject(new LogTable
{
ID = ++DB.IDCounter,
deviceLog = message
});
DB.DBase.SaveChanges();
}
catch (Exception ex)
{
eventLog1.WriteEntry(ex.Message + " - " + ex.InnerException.Message);
}
this.EventLog.Log = "Event Stored in DB.";
}
// The main entry point for the process
static void Main()
{
System.ServiceProcess.ServiceBase[] ServicesToRun;
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new MyNewService.Service1()};
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}
private void InitializeComponent()
{
this.eventLog1 = new System.Diagnostics.EventLog();
((System.ComponentModel.ISupportInitialize)(this.eventLog1)).BeginInit();
this.eventLog1.Log = "DoDyLog";
this.eventLog1.Source = "DoDyLogSource";
this.ServiceName = "MyNewService";
((System.ComponentModel.ISupportInitialize)(this.eventLog1)).EndInit();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
protected override void OnStart(string[] args)
{
// TODO: Add code here to start your service.
eventLog1.WriteEntry("my service started");
}
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your service.
eventLog1.WriteEntry("my service stoped");
stopZKHandler();
}
protected override void OnContinue()
{
eventLog1.WriteEntry("my service is continuing in working");
}
private void OnFinger(object sender, EventArgs e)
{
eventLog1.WriteEntry("Finger Event Raised");
}
private void OnVerify(object sender, zkemkeeperHandler.VerifyEventArgs e)
{
eventLog1.WriteEntry("Verify Event Raised");
}
}
}
What is my mistake? please help me!
The Windows Service that I wrote, can raise custom events but cannot raise my dll events!
I know this thread is old, but I had this problem yesterday, and now I have finally found a solution, after many hours wasted.
The problem is that, the COM object must be created from an STA Thread, and then, for the events to be dispatched correctly, the same STA thread (exactly the same) must be pumping COM messages. This can be done calling Application.DoEvents() in a loop or Application.Run().
So here is my working code (it works, even as a non-interactive Windows Service in Vista+, I am using Windows 8.1)
Thread createComAndMessagePumpThread = new Thread(() =>
{
this.Device = new CZKEMClass(); //Here create COM object
Application.Run();
});
createComAndMessagePumpThread.SetApartmentState(ApartmentState.STA);
createComAndMessagePumpThread.Start();
After the device gets created you can register the events from any thread, and they get dispatched by the STA thread, that created the COM object.
In Windows Forms application, this worked without doing this, because the STA main thread run the form calling Application.Run(Form). Application.Run() then dispatch events like COM events and Windows GUI events, so there is no need to to the trick above.
Reviving this question as I've just been dealing with a related one. Apparently, the OP is using some COM STA objects which need an STA thread and a functional message pump loop to operate properly. The Windows Service execution model doesn't have that by default. Visit the linked answer for more details.
You cannot use events in Windows Service. Exists several causes why not but I would like to offer a solution just for zkemkeeper:
ZK released a zkemkeeper.dll as COM object for working with Windows Application. All device events will fired and not raised in your application when you run it as windows service. Try to add a reference System.Windows.Forms to the project and after successfully connect add row:
Application.Run();

Categories