2004-11-17 [長年日記]

[Q3] アドレス帳

ここ二週間ほど裏でアドレス帳を実装していましたが、trunkにマージしました。[Tool]-[Address Book]でどうぞ。まだ機能的に不十分なところがあると思いますので、こんな機能が欲しいという方はお早めに。

menus.xml, keymap.xml, toolbars.xmlが変更になっています。また、以前のToolAddressBookアクションはToolSelectAddressアクションに変更されていますのでご注意ください。

英語を読む速度

Exceptional C++ Styleが届きました。一緒に注文したHowl's Moving Castleも。両方とも350ページくらいなのですが、前者は10日もあれば読めそうなのに、後者は一ヶ月かかっても読みきれなそうな気配がするのはなぜ。しかし、Harry Potter and the Order of the Phoenixに比べたらはるかに薄いのです*1

Outlookのアドレス帳にアクセス

Outlookのドキュメントを見て最初に思いついたのはこれです。

var app = new ActiveXObject("Outlook.Application");
var ns = app.GetNameSpace("MAPI");
var entries = ns.AddressLists.Item(1).AddressEntries;
for (n = 1; n <= entries.Count; ++n) {
  var entry = entries.Item(n);
  WScript.StdOut.WriteLine(entry.Name);
  WScript.StdOut.WriteLine(entry.Address);
}

しかしこれは本当にアドレス帳としてアクセスしているようで、一つのエントリに複数のアドレスが設定されていると複数のエントリになってしまいますし、細かいプロパティにもアクセスできません。

MAPIFolder経由でアイテムを取るのが正しいようです。

set app = CreateObject("Outlook.Application")
set ns = app.GetNameSpace("MAPI")
set folder = ns.GetDefaultFolder(10)
set items = folder.Items
For n = 1 to items.Count
  set item = items.Item(n)
  itemType = TypeName(item)
  WScript.StdOut.WriteLine(itemType)
  If itemType = "ContactItem" Then
    WScript.StdOut.WriteLine(item.FullName)
    WScript.StdOut.WriteLine(item.Email1Address)
  ElseIf itemType = "DistListItem" Then
    WScript.StdOut.WriteLine(item.DLName)
  End If
  WScript.StdOut.WriteLine()
Next

ちなみにGetDefaultFolderに渡している10はolFolderContactsの値です。なぜいきなりJScriptからVBScriptに変わったのかというと、TypeNameと同じ機能をJScriptから使う方法がわからなかったからです*2

Outlookのアドレス帳にアクセス (2)

OOM経由でアドレス帳からメールアドレスにアクセスすると、毎回「プログラムが、Outlook 内に保存されている電子メール アドレスにアクセスしようとしています。よろしいですか?」というダイアログが出ます。Exchange環境の場合には管理者がこのダイアログを抑制することができるようですが、スタンドアロンの場合にはどうしようもないようです。

Outlook "Object Model Guard" Security Issues for Developersによると、これを回避する方法は、

OOMではなくMAPIを使う
OOMとCDOはブロックされるけれど、MAPIはブロックされない
Trusted COM add-insを使う
Outlookのアドインを作って有効にし、アプリケーションはそのアドインと通信する
サードパーティのライブラリを使う
MAPIをラップするライブラリならブロックされない
ダイアログのOKボタンを押す常駐アプリを使う

だそうです。3番目と4番目は置いておくとしても、わざわざプラグインを作る気もしないし、MAPIを直接使うとOOMよりはるかに面倒だし悩みどころですね。OOM経由でもIDispatch経由のときだけブロックしてvtbl経由のときはブロックしないようにしてくれれば良かったのですけど。

Outlookのアドレス帳にアクセス (3)

MAPIでOutlookのアドレス帳にアクセスするなら、Accessing the Address Book Data Using MAPIが参考になりそうです。良く考えると、今もWABにアクセスするコードはMAPIでやっているのでログイン部分を除くとほとんど使い回しができそうです。

*1  なぜか子供向けファンタジーばかり読んでいる気が…

*2  typeofだとobjectになってしまう

[]