1

I have a Arduino communicating the state of a button through serial port. On the PC I have a Windows Service application that is polling the serial port to get the state of the button. Whenever I receive a message in the serial port about the button state, I write the received message to a file, and also want to log the current mouse position. Following this I would like to raise a left click event at the current mouse position.

For some reason, when I read the current mouse position using GetCursorPos, I always get 0, 0 as the mouse position. I am using user32.dll to do this.

The following is my C# code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Threading;
using System.IO;
using System.IO.Ports;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;

namespace MouseInterface
{
    public class MyMouseClass
    {
        [DllImport("user32.dll")]
        static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

        [Flags]
        public enum MouseEventFlags
        {
            LEFTDOWN = 0x00000002,
            LEFTUP = 0x00000004
        }

        [DllImport("user32.dll")]
        static extern bool SetCursorPos(int x, int y);

        [DllImport("user32.dll")]
        public static extern bool GetCursorPos(ref Point pt);

        public static void LeftDown(int x, int y)
        {
            SetCursorPos(x, y);
            mouse_event((int)(MouseEventFlags.LEFTDOWN), x, y, 0, 0);
        }

        public static void LeftUp(int x, int y)
        {
            SetCursorPos(x, y);
            mouse_event((int)(MouseEventFlags.LEFTUP), x, y, 0, 0);
        }
    }

    public partial class Service1 : ServiceBase
    {
        private HCIDevice hcidev;

        public Service1()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {

            hcidev = new HCIDevice();
            hcidev.init();
        }

        protected override void OnStop()
        {
            hcidev.terminate();
        }

        private void onElapsedTimer(object source, ElapsedEventArgs e)
        {

        }
    }


    public class HCIDevice
    {
        private SerialPort _sPort;
        private Thread _reader;
        private bool _connected;
        private bool _stop;
        private System.Timers.Timer _contimer = new System.Timers.Timer();

        public HCIDevice()
        {
            // create a new serial port
            _sPort = new SerialPort();
            // update settings
            updateSerialPortSettings();

            // set reader and writer threads.
            _reader = new Thread(this._readerthread);

            // reset flags.
            _connected = false;
            _stop = false;

            // start the thread.
            //init();
        }

        public void connect()
        {
            if (this._sPort.IsOpen == false)
            {
                try
                {
                    this._sPort.Open();
                    _connected = true;
                    AddToFile("Device connected!\n");
                }
                catch
                {
                }
            }
        }

        public void disconnect()
        {
            if (this._sPort.IsOpen)
            {
                this._sPort.Close();
            }
            _connected = false;
            AddToFile("Device disconnected!\n");
        }

        public void init()
        {
            try
            {
                this._stop = false;
                // start thread.
                this._reader.Start();
            }
            catch
            {
                //AddToFile("Service could not be started!\n");
            }
        }

        public void terminate()
        {
            // first stop.
            this._stop = true;
            this._reader.Join();
            //AddToFile("Device stopped!");
        }

        public bool isRunning()
        {
            return (this._stop == false);
        }

        public bool isConnected()
        {
            return this._sPort.IsOpen;
        }

        private void updateSerialPortSettings()
        {
            // Allow the user to set the appropriate properties.
            this._sPort.PortName = System.Configuration.ConfigurationManager.AppSettings["devCOM"];
            this._sPort.BaudRate = int.Parse(System.Configuration.ConfigurationManager.AppSettings["devbaudrate"]);
            this._sPort.Parity = Parity.None;
            this._sPort.DataBits = 8;
            this._sPort.StopBits = StopBits.One;
            this._sPort.Handshake = Handshake.None;

            // Set the read/write timeouts
            this._sPort.ReadTimeout = 500;
            this._sPort.WriteTimeout = 500;
        }

        private void _readerthread()
        {
            byte[] _rxdata = new byte[1024];
            //int n;
            double nanosecPerTick = 1.0 / Stopwatch.Frequency;
            Stopwatch stp_watch = new Stopwatch();
            stp_watch.Start();

            AddToFile("Service started!\n");
            while (_stop == false)
            {
                // make sure the device is still connected.
                if (isConnected())
                {

                    // Do nothing if in pause
                   // Not paused read data and parse
                    try
                    {
                        handle_message();
                    }
                    catch (System.TimeoutException) { }
                }
                else
                {
                    // Just got disconnected?
                    if (_connected)
                    {
                        disconnect();
                        // Reset timer.
                        stp_watch.Reset();
                        stp_watch.Start();
                    }
                    else
                    {
                        // try to connect every one second.
                        if (stp_watch.ElapsedMilliseconds >= 1000)
                        {
                            connect();
                            // Reset timer.
                            stp_watch.Reset();
                            if (_connected == false)
                            {
                                stp_watch.Start();
                            }
                        }
                    }
                }
            }
            disconnect();
            AddToFile("Service stopped!\n");
        }

        private void AddToFile(string line)
        {
            using (FileStream fs = File.Open(System.Configuration.ConfigurationManager.AppSettings["logloc"], FileMode.Append, FileAccess.Write, FileShare.None))
            {
                Byte[] info = new UTF8Encoding(true).GetBytes(string.Format("{0} {1}", DateTime.Now.ToString("dd-MMM-yyyy HH:mm:ss"), line));
                // Add some information to the file.
                fs.Write(info, 0, info.Length);
            }
        }

        private void handle_message()
        {
            // read line.
            string msg = _sPort.ReadLine();
            AddToFile(msg);
            Point pt = new Point();
            MyMouseClass.GetCursorPos(ref pt);
            AddToFile(string.Format("{0}, {1}", pt.X, pt.Y));
        }
    }   
}

What am I doing wrong? I googled for a couple of hours to find the solution, but could not find anything about this.

siva82kb
  • 1,910
  • 4
  • 19
  • 28
  • You should look into the restrictions of the service application running on your windows machine. It might be that the service isn't allowed to get the cursors current position. I think that you can run services under either specific user accounts or the overall system. – Cicero Oct 10 '16 at 09:18
  • Your service is running in a separate non interactive window station/desktop, but you are trying to read the mouse position in the window station/desktop of the current user, and you can't. The correct way to handle the desired behaviour is to have code running inside the user session and make the service call it to retrieve the cursor position. – MC ND Oct 10 '16 at 09:24
  • @MCND Where can I find information about how to do what you have mentioned in your comment? – siva82kb Oct 10 '16 at 09:27
  • [Window stations and Desktops](https://msdn.microsoft.com/en-us/library/windows/desktop/ms687098(v=vs.85).aspx) – MC ND Oct 10 '16 at 09:29
  • [Interactive services](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683502(v=vs.85).aspx), specially all the warnings about why it is a bad design. Then move into something like [this](http://stackoverflow.com/q/3128017/2861476). The rest is IPC between the application and the service. – MC ND Oct 10 '16 at 09:36
  • I almost forget [this](https://msdn.microsoft.com/en-us/library/windows/hardware/dn653293(v=vs.85).aspx) – MC ND Oct 10 '16 at 09:39
  • @siva82kb Did you get your answer? – N.K Nov 13 '19 at 06:01

0 Answers0