简体   繁体   中英

How to capture Logoff event using a windows service in C#?

I am trying to create a service that will log when users logon and logoff. I have no problem with capturing the logon, but for some reason i cannot catch the logoff event. this is the code i have used:

protected override void OnStart(string[] args)
{
    //SystemEvents.SessionSwitch +=    new SessionSwitchEventHandler(SystemEvents_SessionSwitch);
    SystemEvents.SessionEnding += new SessionEndingEventHandler(SystemEvents_SessionEnding);
}
void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
{
    this.EventLog.WriteEntry("We have cought logout event");
    sendData("off");
}

I have tried using SessionEnding, SessionEnded and SessionSwitch but none of them seem to work. I have checked the service, it is up and running and the serive is running under Local System account and the "Allow service to interact with desktop" option is ticked.

Any suggestions?

Service class:

public partial class Service1 : ServiceBase
{
    public Service1()
    {
        InitializeComponent();
    }
    protected override void OnStart(string[] args)
    {
        EventLog.WriteEntry("WinSendSED", "Starting WinSendSED");
        new Thread(RunMessagePump).Start();
    }
    void RunMessagePump()
    {
        EventLog.WriteEntry("WinSendSED.MessagePump", "Starting WinSendSED Message Pump");
        Application.Run(new HiddenForm());
    }
    protected override void OnStop()
    {
        //sendData("off");
        Application.Exit();
    }
}

Hidden Form:

public partial class HiddenForm : Form
{
    public HiddenForm()
    {
        InitializeComponent();
    }
    private string makeNiceMAC(string s)
    {
        for (int i = 0; i < 5; i++)
        {
            s = s.Insert((3 * i) + 2, "-");
        }
        return s;
    }
    private string getUserName()
    {
        Process[] ps = Process.GetProcesses();
        foreach (Process p in ps)
        {
            if (p.ProcessName.Trim() == "explorer")
            {
                ObjectQuery sq = new ObjectQuery
                    ("Select * from Win32_Process Where ProcessID = '" + p.Id + "'");
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(sq);
                foreach (ManagementObject oReturn in searcher.Get())
                {
                    string[] o = new String[2];
                    oReturn.InvokeMethod("GetOwner", (object[])o);
                    return o[0];
                }
            }
        }
        return "";
    }
    private string GetIPAddress()
    {
        IPAddress[] addr = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
        for (int i = 0; i < addr.Length; i++)
        {
            if (addr[i].ToString().Contains("."))
                return addr[i].ToString();
        }
        return "127.0.0.1";
    }
    private string printData()
    {
        WindowsIdentity id = WindowsIdentity.GetCurrent();
        NetworkInterface[] nis = NetworkInterface.GetAllNetworkInterfaces();
        NetworkInterface ni = nis[0];
        foreach (NetworkInterface nii in nis)
        {
            if ((nii.OperationalStatus == OperationalStatus.Up)
                && (!nii.GetPhysicalAddress().ToString().EndsWith("000000E0"))
                && (nii.GetPhysicalAddress().ToString().Length > 5))
            {
                ni = nii;
            }
        }
        string line = "";
        line = line + "'" + makeNiceMAC(ni.GetPhysicalAddress().ToString()) + "', ";
        line = line + "'" + GetIPAddress() + "', ";
        line = line + "'" + getUserName() + "'";
        return line;
    }
    private void sendData(string cmd)
    {
        Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
        IPEndPoint ipAdd = new IPEndPoint(IPAddress.Parse(//"127.0.0.1"), 2345);
            "123.123.123.123"), 2345);
        try
        {
            s.Connect(ipAdd);
            String szData = cmd + printData();
            byte[] byData = System.Text.Encoding.ASCII.GetBytes(szData);
            s.Send(byData);
            s.Close();
        }
        catch (SocketException se)
        {
            s.Close();
        }
    }

    private void HiddenForm_Load(object sender, EventArgs e)
    {
        SystemEvents.SessionEnding += 
            new SessionEndingEventHandler(SystemEvents_SessionEnding);
    }

    void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
    {
        EventLog.WriteEntry("WinSendSED", "We have cought logout event");
        sendData("off");
    }

    private void HiddenForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        SystemEvents.SessionEnding -= 
            new SessionEndingEventHandler(SystemEvents_SessionEnding);
    }

    private System.ComponentModel.IContainer components = null;

    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    private void InitializeComponent()
    {
        this.SuspendLayout();
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(0, 0);
        this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
        this.Name = "HiddenForm";
        this.Text = "HiddenForm";
        this.WindowState = System.Windows.Forms.FormWindowState.Minimized;
        this.Load += new System.EventHandler(this.HiddenForm_Load);
        this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.HiddenForm_FormClosing);
        this.ResumeLayout(false);

    }
}

How about using the Group Policy? You can launch a process on the logoff event, if you use the group policy of the local machine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM