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)
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.