1

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

    }
}
Jeff Atwood
  • 63,320
  • 48
  • 150
  • 153
  • Did you ever try OnSessionSwitch event.See [this link][1]. [1]: http://stackoverflow.com/questions/5353066/how-to-make-a-net-windows-service-detect-logon-logoff-and-switch-user-events – M_Mogharrabi Sep 03 '12 at 05:22

1 Answers1

1

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.

Rihan Meij
  • 1,759
  • 1
  • 14
  • 18
  • thanks for your answer, my problem is i cannot catch the logoff event at all. i.e. my service is not notified when the logoff event happens. –  Feb 23 '10 at 14:36
  • I believe he meant calling a separate executable in the logoff event in group policy, which would indeed work. – Tom Studee Feb 23 '10 at 14:50
  • i see. But is that the right solution if i want to install the service on about 3000 PCs? –  Feb 23 '10 at 15:52