.NET Remotingによるリモートマウスコントロール

数年前、Winapiと組み合わせてRemotingを試し、マウスのリモートコントロールを行うことにしました。 ソリューションは、.NET Remotingを介して対話する2つのアプリケーションで構成される必要があります。 サーバーアプリケーションは、Windowsサービスの形式である必要があります。



サーバーはRAdminサーバーに似ており、ポートでリッスンし、クライアントが接続するのを待ちます。 クライアントが接続すると、サーバーはマウスの位置を変更するかボタンをクリックする必要性に関する情報を受け取ります。



次に、クライアントは指定されたサーバーに接続し、クライアントウィンドウでマウスの位置が変更された場合、サーバーに情報を転送します。



現時点ではWindowsを使用していないため、メモリからすべてを復元します。



Remotingを使用して以来 当時は、ソケットレベルから抽象化し、オブジェクト/インターフェイスレベルでクライアントおよびサーバーと通信することができた新しい興味深いテクノロジーでした。 つまり、ソケットを開いてメッセージを交換する代わりに、サーバーで共有するオブジェクトを宣言し、クライアントでそのメソッドを使用するだけです。 ソケットとSQLを比較し、データベースと直接対話する場合、.NET Remotingは美しく便利なラッパーであるORMに似ています。



お客様



クライアントは簡単に恥をかきます。 起動時にRemotingを初期化し、ボタンをクリックすると、サーバーに接続するか、サーバーから切断します。 ウィンドウとその上にフォームがあります。 その上でのマウスの動きを傍受し、マウスボタンを押したり放したりします。 クライアントは対話するインターフェイスのみを知っており、マウスの変更をその中の機能に転送します。



クライアントリモーティングの構成


<configuration> <system.runtime.remoting> <application> <lifetime leaseTime="20D" sponsorshipTimeout="1H" renewOnCallTime="1D" leaseManagerPollTime="1H" /> <client> <wellknown type="Communication.Communication,Communication" url="tcp://127.0.0.1:8000/Communication.rem" /> </client> <channels> <channel ref="tcp" port="0" clientConnectionLimit="20" > </channel> </channels> </application> </system.runtime.remoting> <appSettings> <add key="RemotingUrl" value="tcp://127.0.0.1:8000/Communication.rem"></add> </appSettings> </configuration>
      
      





顧客コード


記事のどこにもシャープコードがあります。

  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(eX, eY); } 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(); } }
      
      





起動時-設定をロードし、ボタンをクリックすると、リモートオブジェクトが接続されます。 移動してクリックすると、このオブジェクトの対応する関数を呼び出します。



サーバー



サーバーは少し複雑です。 前述のインターフェイスを実装するオブジェクトがあり、.NET Remotingを使用してマウスの変更に関する情報を受け取り、すぐにwinapi SendInputを送信してマウスの位置を変更し、ボタンを押します(いくつかのマウスボタンの場合、キーストロークまたは画面イメージの転送は非常に簡単です)このコードを変更します-引数でサーバーに渡し、戻り値でクライアントに渡します)。



サーバーのリモート構成


 <configuration> <system.runtime.remoting> <application> <lifetime leaseTime="20D" sponsorshipTimeout="1H" renewOnCallTime="1D" leaseManagerPollTime="1H" /> <service> <wellknown mode="Singleton" type="Communication.Communication,Communication" objectUri="Communication.rem"/> </service> </application> </system.runtime.remoting> </configuration>
      
      





サーバーはWindowsサービスとして設計されています(テンプレートを作成するときは、サービスを選択します)。



この場合、メイン関数は次のようになります。

 static void Main() { ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { new Service1() }; ServiceBase.Run(ServicesToRun); }
      
      





サービスは同じアプリケーションですが、個別に起動され、開始/停止するためのいくつかの特権と特別な機能があります。 そのような特別なライフサイクル。 このサービスはユーザーに代わって(カーソルを移動するために)起動する必要があるため、サービスコントロールパネルでユーザーを手動で現在のユーザーに変更します。



この例では、サービスの開始時にサービスを初期化する必要があります。



サーバーコード


  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() { } }
      
      





ここで、Remotingが初期化されるサービスを開始する関数を確認します。 説明、構成のロード、チャネルの登録、オブジェクトの登録について特別なことはありません。 TCPの代わりにHTTPを使用できます。



既製のカーソル制御機能を使用しました。 ここにいるようです

そしてそれらをコミュニケーションに包みました:



 class Communication : MarshalByRefObject, ICommunication { //      –  winapi user32.dll,   –        }
      
      





すべて、サーバーは他に何も必要としません。 このオブジェクトは、.NET Remotingによって管理されます



サービスの追加/削除


このサービス用に特別なインストーラーを作成するオプションがありますが、私の意見では、同様のコンテンツを持つ2つのショートカットを作成する方が簡単です。



インストールするには:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe "G:\current\location\our_service.exe"





削除するには:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe "G:\current\location\our_service.exe" /u








このアプリケーションは、Windows XP SP2を実行しているコンピューターでテストされています。 私の意見では、Windowsの古いバージョン(Vista、7)では、セキュリティのためにいくつかの不具合がありますが、これは解決されています。



ここでは、クライアントとサーバーのフィードバックメカニズムについては説明しません。 はい、2つの接続を作成できます-直接および逆方向、または定期的にサーバーを照会しますが、これはあまりエレガントではありません。 興味のある方は、このトピックに関する次の記事でエレガントなソリューションを紹介します。 そこで、計算がサーバーで実行され、表示がクライアントで実行されるように、3次元空間のポイントを制御します。 次に、クライアント部分をSilverlightに転送し(シルバーの制限により使用できないため、既にRemotingを使用していません)、ブラウザーに表示します。



ソースはここからダウンロードできます



All Articles