
Remote mouse control with .NET Remoting
- Tutorial
A couple of years ago, I decided to try Remoting in combination with winapi and do remote mouse control. The solution should consist of 2 applications interacting through .NET Remoting. The server application must be in the form of a Windows service.
The server is similar to the RAdmin server, listens to the port and waits for the client to connect. When a client connects, the server receives information about the need to change the position of the mouse or click a button.
The client, in turn, connects to the specified server and, if the mouse position changes in the client window, transfers information to the server.
At the moment I do not use Windows, so I will restore everything from memory.
I used Remoting since at that time it was a new interesting technology that allowed us to abstract from the socket level and communicate with the client and server at the object / interface level. That is, instead of opening a socket, exchanging messages, we simply declare the object that we want to share on the server and use its methods on the client. If you compare the sockets with SQL and direct interaction with the database, then .NET Remoting is similar to ORM, a beautiful and convenient wrapper.
The client is simple to disgrace. At startup, initialize Remoting, when you click the button, we connect to the server or disconnect from it. There is a window and a form on it. We intercept mouse movements on it and pressing / releasing the mouse button. The client knows only the interface with which it interacts, transfers changes in our mouse to the functions in it.
Everywhere in the article is a sharpe code.
At startup - load the configuration, then, when you click on the button, we connect the remote object. When moving and clicking, we call the corresponding function of this object.
The server is a little trickier. It has an object that implements the aforementioned interface, using .NET Remoting it receives information about changes in the mouse and immediately sends winapi SendInput to change the position of the mouse and press its button (for several mouse buttons, transfer of keystrokes or screen image change this code - in arguments we pass to the server, and in the return value we pass to the client).
The server is designed as a Windows service (when creating the template, select service).
In this case, the main function looks like this:
Services are the same applications, but they are launched separately, they have some privileges and special functions for starting / stopping. Such a special life cycle. Since this service should be launched on behalf of our user (to move the cursor), we change the user to the current one manually in the services control panel.
In our case, the service must be initialized when the service starts.
Here we see the function to start the service in which Remoting is initialized. There is nothing special to explain, load the config, register the channel, register the object. You can use HTTP instead of TCP.
I took the cursor control functions ready-made. Seems to be here .
And wrapped them in Communication:
Everything, the server does not need anything else, because this object will be managed through .NET Remoting
There is an option to make a special installer for this service, but in my opinion it is easier to create 2 shortcuts with similar contents:
To install:
To remove:
This application has been tested on computers running Windows XP SP2. On older versions of Windows (Vista, 7), in my opinion, there are some glitches due to security, but this can be solved.
The feedback mechanism of the server with the client is not described here. Yes, you can make 2 connections - direct and reverse, or periodically query the server, but this is not very elegant. If you are interested, then I will show you an elegant solution in the next article on this topic. There we will control the point in three-dimensional space so that the calculations are carried out on the server, and the display was carried out on the client. And then we transfer the client part to Silverlight (already without Remoting, since the limitations of the silver do not allow it to be used) and display it in the browser.
Sources can be downloaded here .
The server is similar to the RAdmin server, listens to the port and waits for the client to connect. When a client connects, the server receives information about the need to change the position of the mouse or click a button.
The client, in turn, connects to the specified server and, if the mouse position changes in the client window, transfers information to the server.
At the moment I do not use Windows, so I will restore everything from memory.
I used Remoting since at that time it was a new interesting technology that allowed us to abstract from the socket level and communicate with the client and server at the object / interface level. That is, instead of opening a socket, exchanging messages, we simply declare the object that we want to share on the server and use its methods on the client. If you compare the sockets with SQL and direct interaction with the database, then .NET Remoting is similar to ORM, a beautiful and convenient wrapper.
Client
The client is simple to disgrace. At startup, initialize Remoting, when you click the button, we connect to the server or disconnect from it. There is a window and a form on it. We intercept mouse movements on it and pressing / releasing the mouse button. The client knows only the interface with which it interacts, transfers changes in our mouse to the functions in it.
Client Remoting Configuration
Client code
Everywhere in the article is a sharpe code.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
RemotingConfiguration.Configure("Client.config");
}
ICommunication iCommunication;
bool connected;
private void button1_Click(object sender, EventArgs e)
{
if (!connected)
{
iCommunication = (ICommunication)Activator.GetObject(typeof(ICommunication), textBox4.Text);
connected = true;
iCommunication.Move(100, 100);
button1.Text = "Отключиться";
}
else
{
button1.Text = "Подключиться";
connected = false;
}
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (!connected) return;
iCommunication.Move(e.X, e.Y);
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
if (!connected) return;
iCommunication.Down();
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
if (!connected) return;
iCommunication.Up();
}
}
At startup - load the configuration, then, when you click on the button, we connect the remote object. When moving and clicking, we call the corresponding function of this object.
Server
The server is a little trickier. It has an object that implements the aforementioned interface, using .NET Remoting it receives information about changes in the mouse and immediately sends winapi SendInput to change the position of the mouse and press its button (for several mouse buttons, transfer of keystrokes or screen image change this code - in arguments we pass to the server, and in the return value we pass to the client).
Remoting configuration for server
The server is designed as a Windows service (when creating the template, select service).
In this case, the main function looks like this:
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new Service1() };
ServiceBase.Run(ServicesToRun);
}
Services are the same applications, but they are launched separately, they have some privileges and special functions for starting / stopping. Such a special life cycle. Since this service should be launched on behalf of our user (to move the cursor), we change the user to the current one manually in the services control panel.
In our case, the service must be initialized when the service starts.
Server code
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
Communication communication;
protected override void OnStart(string[] args)
{
System.Runtime.Remoting.RemotingConfiguration.Configure(Application.StartupPath+"\\Server.config");
System.Runtime.Remoting.Channels.ChannelServices.UnregisterChannel(channel);
BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();
System.Collections.IDictionary props =
new System.Collections.Hashtable();
props["port"] = 8625;
channel = new TcpChannel(props, clientProv, serverProv);
System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(channel);
communication = new Communication();
ObjRef or = RemotingServices.Marshal(communication, "Communication.rem");
communication.Move(100, 100);
}
TcpChannel channel;
protected override void OnStop()
{
}
}
Here we see the function to start the service in which Remoting is initialized. There is nothing special to explain, load the config, register the channel, register the object. You can use HTTP instead of TCP.
I took the cursor control functions ready-made. Seems to be here .
And wrapped them in Communication:
class Communication : MarshalByRefObject, ICommunication
{
//здесь много кода для движения мышки – вызова winapi user32.dll, кому интересно – есть в исходниках и по ссылке выше
}
Everything, the server does not need anything else, because this object will be managed through .NET Remoting
Add / Remove Service
There is an option to make a special installer for this service, but in my opinion it is easier to create 2 shortcuts with similar contents:
To install:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe "G:\current\location\our_service.exe"
To remove:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe "G:\current\location\our_service.exe" /u
This application has been tested on computers running Windows XP SP2. On older versions of Windows (Vista, 7), in my opinion, there are some glitches due to security, but this can be solved.
The feedback mechanism of the server with the client is not described here. Yes, you can make 2 connections - direct and reverse, or periodically query the server, but this is not very elegant. If you are interested, then I will show you an elegant solution in the next article on this topic. There we will control the point in three-dimensional space so that the calculations are carried out on the server, and the display was carried out on the client. And then we transfer the client part to Silverlight (already without Remoting, since the limitations of the silver do not allow it to be used) and display it in the browser.
Sources can be downloaded here .