提高自定义类事件在Windows服务C#自定义、事件、Windows

2023-09-03 04:27:21 作者:男生伤感,忧伤男生

我的确写了一个窗口服务,可以连接到使用DLL中的网络设备。所以一切工作正常,但该事件处理程序不会在夺冠的服务工作!这里是我的code:

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 :

我的自定义类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);
        }
    }
}

我的主要服务类code:

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!

Windows服务是我写的,可以提高自定义事件,但不能提高我的DLL的事件!

The Windows Service that I wrote, can raise custom events but cannot raise my dll events!

推荐答案

我知道这个线程是老了,但我昨天有这个问题,现在我终于找到了一个解决方案,经过几个小时浪费。 问题在于,在 COM对象必须从STA线程创建的,那么,对于事件要正确出动,相同的STA线程(完全一样)必须抽COM消息。这是可以做到调用Application.DoEvents()在一个循环或Application.Run()。

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

因此​​,这里是我的工作code(它的工作原理,甚至作为一个非交互式服务的Windows Vista中+,我使用Windows 8.1)

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();

在该设备被创建,你可以从任何线程注册事件,他们的STA线程,创建COM对象得到调度。

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.

在Windows窗体应用程序,这个工作没有这样做,因为STA主线程运行窗体调用Application.Run(表格)。 Application.Run()然后分派像COM事件和Windows GUI事件的事件,所以没有必要上述伎俩。

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.