IronPython で Merlin を動かす

(追記) 真雪さんのところで さらに cool な方法 が紹介されています.That's Pythonic!




Python Workshop the Edge 2007IronPython のセッションで,デスクトップにアニメーションキャラクタを表示するデモに興味を持たれた方が多いようなので,これを試す方法を書いておきます.

MSAgent とは?

MSAgent とは,ユーザーに情報を提示したりユーザーからの質問を受け取ったりするアバターの仕組みです.Windows 2000 で導入された Layered Window という機能 *1 を活用して,デスクトップ上を自由に移動しながら,滑らかなアニメーションを行います.
Office 97 で導入された,かの有名なイルカさん (Office アシスタント) ですが,Office 2000 以降ではこの MSAgent を使うことで画面外に移動することが可能になりました.さらに,MSAgent は COM を通じて Office 以外のアプリケーションにも公開されており,自分のアプリケーションからキャラクタを使用したり,自分で新しいキャラクタを作ったりすることもできます.

MSAgent を入手するには?

ご存じの通り,イルカさんたちの立場は芳しくありません.

例えば,悪評高い「イルカ」は,一つ目の限界を解消しようとしたものであった。しかし,このヘルプ・アシスタントを本当に使っているユーザーはいるだろうか?(図)。


図●従来のOfficeに見られる敗北の象徴

当初から鬱陶しいと酷評され,Office XP では「もはやアシスタントは不要になった」とデフォルトでは表示されなくなり,Office 2007 ではついにインストールすらされなくなってしまいました.
早くからベイジアンネットワークを自然言語検索に応用したり*2,レイヤードウィンドウを有効に活用したりと,野心的な仕組みではあったのですが,いかんせん使い方を誤ったようで,近年では Microsoft の自虐ネタの代名詞になりつつあります*3
そんなわけで Office 2007 をインストールしてももうイルカさんはインストールされません.では最近の環境ではあのデモを実行することができないかというと,実は Windows XPWindows Vista には依然として MSAgent のランタイムライブラリが最初からインストールされています.%SYSTEMROOT%\MSAgent (たとえば C:\Windows\MSAgent) を調べてみてください.
さらに,いくつかのキャラクタも MSDN サイトからダウンロードすることが可能です.アーサー王の物語にちなんだと思われる魔法使い『Merlin』のキャラクターファイルも,そのなかの 1 つです.
第 1 回 VC# で MSAgent 〜 Visual C# .NET による MSDNAA おもしろプログラミング 〜』で紹介されているように,MSAgent の開発者用ページにある、キャラクターデータのダウンロードページ から,Merlin をダウンロードしてインストールして下さい.これで,Merlin を使用する準備は整いました.

IronPython の準備

CodePlex のサイト から IronPython をダウンロードします.今回は,IronPython 2.0 Alpha 2 を使用してみましたが,問題なく Merlin を動作させることができました.
パッケージは ZIP ファイルで圧縮されているので,好きな場所に展開します.シェルによる対話モードで IronPython を起動するには ipy.exe を実行しますが,このとき以下のようにオプションを設定することで,出力を色分けしたり,タブ補完が有効になったりします.気に入った設定でショートカットを作っておくと良いでしょう.

ipy.exe -X:ColorfulConsole -X:AutoIndent -X:TabCompletion

また,IronPython\Tutorial\Tutorial.htm の "Tutorial 3: IronPython and COM interoperability" に,今回紹介する Merlin のデモの実行の仕方が書かれています.基本的にはこのチュートリアルに書かれているとおりに実行すれば良いのですが,Windows SDK に付属するツール (tlbimp.exe) を要求していたりと若干面倒な方法をとっていますので,以下では一部別の方法を紹介します.

.NET から COM オブジェクトを使う準備

.NET の Microsoft 実装である CLR は,COM オブジェクトを .NET の世界から使えるようにも設計されていますが,このとき事前に COM オブジェクトのインターフェイス情報を,.NET の型情報にマッピングしておくという手順をとります.チュートリアルの以下の部分は,その作業,つまり COM のタイプライブラリ (TLB) から,tlbimp.exe というツールを使って,.NET の型情報としてインポートした DLL を作成する作業を説明しています.

Task 1: Creating COM interop assemblies

  1. Open the "SDK Command Prompt" or "Visual Studio 2005 Command Prompt" from the start menu.

  2. The .NET Frameworks SDK comes with the "tlbimp" tool which converts a COM type library into .NET metadata information -- the interop assembly.  The COM object library we want to use from IronPython is msagent, located in %SystemRoot%\msagent\agentsvr.exe.  Use the tlbimp tool to generate the interop assembly for msagent (tlbimp writes to the current directory):

tlbimp %SystemRoot%\msagent\agentsvr.exe

C:\IronPython\Tutorial>tlbimp %SystemRoot%\msagent\agentsvr.exe
Microsoft (R) .NET Framework Type Library to Assembly Converter 2.0.50727.42
Copyright (C) Microsoft Corporation.  All rights reserved.
 

Type library imported to AgentServerObjects.dll

tlbimp.exe は .NETSDK に付属するツールですが,わざわざこのために SDK をインストールしてもらうというのは大げさです.そこで,このツールが行うのと同じ作業をする C# の簡単なコードを書いてみました.今回は,このソースコードIronPython から動的にコンパイルすることで,tlbimp.exe なしにチュートリアルを進めてみたいと思います.
以下のファイルを,IronPython のディレクトリに "tlbimp.cs" という名前でダウンロードしておいて下さい.
http://www.dwahan.net/nyaruru/hatena/tlbimp.cs

Merlin を動かす

さて,準備は整いました.ipy.exe を起動しましょう.
まず,IronPython .NET サポートを有効化します.

import clr

次に,先ほどおいた C# のコードを動的にコンパイルして,tlbimp.exe と同じ作業を行う準備をします.

from Microsoft.CSharp import *
from System.CodeDom.Compiler import *
cscp = CSharpCodeProvider()
opt = CompilerParameters()
opt.GenerateInMemory = True
result = cscp.CompileAssemblyFromFile(opt, "tlbimp.cs")
clr.AddReference(result.CompiledAssembly)

from TlbImpLib import *

これで,TlbImp という C# で書かれたクラスが使用できるようになりました.
さらに,TlbImp クラスを使って動的に COM の型情報をインポートします.agentsvr.exe の場所は,MSAgent のランタイムライブラリのインストール場所に合わせて調整して下さい.一般的には "%SYSTEMROOT%\MSAgent\agentsvr.exe" の位置にあります.

agentAsm = TlbImp.Import( r"C:\Windows\MSAgent\agentsvr.exe", "AgentServerObjects" )
clr.AddReference(agentAsm)

ここまでの作業が,ちょうどチュートリアルの clr.AddReferenceToFile("AgentServerObjects.dll") までに相当します.
あとはチュートリアル通りで OK です.まずは,AgentServerObjects 名前空間以下をインポートします.

from AgentServerObjects import *

Merlin を表示させてみましょう.

a = AgentServerClass()
cid = a.Load("Merlin.acs")[0]
c = a.GetCharacter(cid)
c.Show(0)

吹き出しに "IronPython Tutorial" と表示させてみます.

c.Think("IronPython Tutorial")

エージェントがどんな動作に対応しているかも,簡単に調べることができます.

for n in c.GetAnimationNames(): print n

先ほども紹介した『第 1 回 VC# で MSAgent 〜 Visual C# .NET による MSDNAA おもしろプログラミング 〜』にも色々な使い方が提示されているので,一通り眺めてみると良いでしょう.
画面上を移動させてみます.

c.MoveTo(100, 400, 1)
c.MoveTo(400, 100, 1)

最後に終了する前に,以下のようにキャラクタを閉じておきます.

c.StopAll(0)
c.Hide(0)

以上,IronPython から MSAgent を使用する方法でした.

*1:ウィンドウの一部または全部を透明化したり半透明化したりする機能です

*2:[http://www.atmarkit.co.jp/fwin2k/opinion/yamazaki/yama_2002_09.html:title=君はベイジアン・ネットワークを知っているか?]

*3:[http://itpro.nikkeibp.co.jp/article/NEWS/20070605/273571/:title=【TechEd 2007】「もうビジョンは語らない」,沈黙し始めたMicrosoft] より [http://itpro.nikkeibp.co.jp/js/2006/popup.shtml?i=http%3A//itpro.nikkeibp.co.jp/article/NEWS/20070605/273571/pic04.jpg&c=%u5199%u771F4%u25CFMicrosoft%20Bob%u3068Office%u30A2%u30B7%u30B9%u30BF%u30F3%u30C8%u304C%u652F%u914D%u3059%u308B%u6697%u9ED2%u306E%u672A%u6765%u56F3:title=Microsoft BobとOfficeアシスタントが支配する暗黒の未来図]