WinCE デバイスのリモート操作~その1(1/2)
■「リモートディスプレイアプリケーション」
どちらかといえば、デバッグ用の機能になりますが、WinCE/WEC には、ネットワーク経由で画面をリモート表示し、操作する機能が標準で付属しています。CERDisp というユーティリティが、そうです。
CERDisp を OS イメージへ追加するには、次のカタログ項目を選択して下さい:
コア OS
CEBASE
コア OS サービス
デバッグツール
★ リモートディスプレイアプリケーション
Platform Builder のカタログ項目ビューには、「リモートディスプレイアプリケーション」の下に、次の二つの項目があります:
CE リモートディスプレイアプリケーション
CE リモートディスプレイユーティリティ
「CE リモートディスプレイアプリケーション」が、CERDisp であり、リモート操作する対象の WinCE/WEC 上で動作します。「CE リモートディスプレイユーティリティ」は、リモート操作を行うホスト(開発用の PC など)で動かすユーティリティで、CERHost という名前です。
CERHost の方は、PC 用にあらかじめビルドされたものが、
%_WINCEROOT%/PUBLIC/COMMON/OAK/BIN/I386/
に入っています。このフォルダに入っている cerhost.exe を PC で起動しておき、その後、リモート操作したい WinCE/WEC 上で、cerdisp.exe を起動して、両者を接続すると、WinCE/WEC の画面を PC に表示できます。
CERDisp の使い方については、Nicolas BESSON という人の Blog の 2007/12/28 のエントリでも説明されています:
Enable Remote Display Application – CERDisp
http://nicolasbesson.blogspot.com/2007/12/enable-remote-display-application.html
また、Mike Hall(Windows Embedded プロダクトグループのテクニカルプロダクトマネージャ)の Blog の 2007/01/04 のエントリでは、”AutoLaunch” というツールと一緒に、CERDisp が紹介されています:
CE 6.0: Booting processes with Command Line Options.
http://blogs.msdn.com/b/mikehall/archive/2007/01/04/ce-6-0-booting-processes-with-command-line-options.aspx
このページで紹介されている AutoLaunch は、レジストリの [HKEY_LOCAL_MACHINE\init] キー下に登録して WinCE/WEC の起動直後に起動されるようになっています(そのための .reg ファイルが、ソースファイルに同梱されています)。AutoLaunch は、起動すると、レジストリの [HKEY_LOCAL_MACHINE\Startup] キー下に登録された内容を見て、登録されたアプリケーションを起動します。
AutoLaunch の便利な点は、[HKEY_LOCAL_MACHINE\Startup] キー下に登録されたアプリケーションを起動する前に、WinCE/WEC に IP アドレスが設定されるまで待つ点です。つまり、WinCE/WEC デバイスのネットワークインタフェース(Ethernet コントローラなど)と TCP/IP スタックの初期化動作が完了し、さらに、DHCP が有効な場合は DHCP サーバから IP アドレスの割り当てを受けて IP アドレスが設定されるまでの間、AutoLaunch は、登録されたアプリケーションを起動しません。従って、WinCE/WEC デバイスの IP アドレスが確定する前にネットワークアプリケーションが自動起動されてしまい、そのアプリケーションがエラーを起こしてしまう、という心配がないのです。
また、[HKEY_LOCAL_MACHINE\init] キーに登録する場合とは違い、登録するアプリケーションのコマンド引数を指定できるのも、AutoLaunch の便利な点です。[HKEY_LOCAL_MACHINE\init] キーの場合、起動されたアプリケーションが SignalStarted() を呼び出す際の引数をコマンドライン引数として渡す仕組みになっているため、コマンド引数を指定することが出来ません。詳細については、上記の Mike Hall の Blog を読んでみて下さい。
■CERDisp と CERHost の動作の仕組み
さて、以下では、CERDisp と CEHost の動作の仕組みについて、簡単に説明します。これら二つのアプリケーションのソースコードは、
%_WINCEROOT%/PUBLIC/COMMON/OAK/DRIVERS/CERDISP/
配下にありますので、興味のある人は、ソースコードも読んでみて下さい。
上で紹介した Nicolas BESSON の Blog では、CERHost がサーバ、CERDisp がクライアントという風に説明されていますが、実際は逆で、CERDisp の方がサーバとして動作します。CERDisp と CERHost は、それぞれ、次のように動作します。
・CERDisp の動作
- 起動すると、スクリーンサイズと OS バージョンなどのデバイス情報を取得し、クライアント(CERHost)との接続用スレッドを始動する。
- クライアントとの接続用スレッドは、TCP ソケットを生成して、ポート987番に対し bind() & listen() を実行した後、ブロードキャスト用のスレッドを始動し、その後、accept() を呼び出して TCP 接続されるのを待つ。
- ブロードキャスト用のスレッドは、UDP ソケットを生成して、同じくポート987に対し、デバイス情報と自身の IP アドレスの対を5秒間隔で繰り返しブロードキャストする。
ブロードキャスト用のスレッドは、クライアントと接続したことを検出したら、自発終了する。
- クライアントとの接続用スレッドは、accept() の呼び出しが完了してクライアントと接続したら、ブロードキャスト用のスレッドの終了を待つ。ブロードキャスト用のスレッドが終了したら、クライアントからのイベント通知を受信するスレッドを始動し、その後、画面内容をクライアントへ転送するループ動作を実行する。
画面内容をクライアントへ転送するループ動作では、レジストリで設定された間隔(デフォルトは、100ミリ秒)で画面内容をキャプチャして、キャプチャした画像データをクライアントに送信する。ここで、送信する画像データは、BitBlt() でキャプチャした画面内容を、行単位でランレングス圧縮したもの。
- クライアントからのイベント通知受信スレッドは、画面内容を送信するのと同じ TCP ソケットに対して、クライアントから送られたイベントを受信して処理するループ動作を実行する。クライアントから送られたイベントは、マウスイベントであれば、mouse_event() を呼び出し、キーボードイベントであれば keybd_event() を呼び出すことにより、システムのイベントキューへ投入する。
・CERHost の動作
- 起動すると、UDP ソケットを生成して、ポート987番に対するブロードキャストメッセージを監視し、検出したサーバ(CERDisp)のリストを構築・管理する。
- 検出した CERDisp のうち、[File] → [Connect...] メニューのダイアログで指定された IP アドレスのものに TCP 接続し、通知されたスクリーンサイズと同じサイズになるよう、自身のウィンドウの(クライアント矩形の)サイズを調節する。
- 以降は、TCP ソケットから画面内容を受信して、自身のウィンドウに表示する動作と、マウスイベントおよびキーボードイベントを TCP ソケットで送信する動作を繰り返す。
このようにして、CERDisp と CERHost が連携し、WinCE/WEC のリモート操作を実現します。WinCE/WEC には、RDP (Remote Desktop Protocol) のサーバ機能は付属していませんが、CERDisp と CERHost を使えば、似たことができるというわけです。
Mike Hall が彼の Blog で書いているように、この機能は、WinCE/WEC のリファレンスボードや開発ボードを使う際、ボードにモニタや液晶パネルを繋がなくても、開発用の PC だけで、WinCE/WEC と開発環境を同時に操作する際に便利でしょう。最近のボードは、液晶パネルが付属しているものが珍しくありませんが、それでも、開発用の PC だけで操作できるというのは、便利な場合が少なくないと思います。
ところで、注意深い人は、
%_WINCEROOT%/PUBLIC/COMMON/OAK/DRIVERS/CERDISP/
の下に、CERDisp と CERHost の他にもソースディレクトリがあることに気づいたのではないかと思います。次回は、それについて書きます。