【IDM】MSMQ を使って確実なユーザー登録を行う その4 ~ メッセージの送信

MSMQを使用してユーザー登録を工夫しようシリーズの第4回目です。

前回の登録から..なんと半年...Tech・Ed 2008 では「続き待ってます」と言われておりました...すみませんです。他にも書きかけの記事があったりもして...えーと、えーと、干支が変わる前になんとかしたいかなぁと思う今日この頃です(あ、なんか今日 冴えてるかも!)。

前回までの記事は以下の通りです。

今回は、VBScript(PowerShellじゃないところがニクいじゃぁありませんか)を使用してMSMQでメッセージを送信してみます。

■メッセージを送信してジョブを作成する

第3回の後半で使用したスクリプトを見てみましょう。拡張子はvbsです。

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

Const MQ_RECEIVE_ACCESS = 1 Const MQ_SEND_ACCESS = 2 Const MQ_PEEK_ACCESS = 32 Const MQ_ADMIN_ACCESS = 128 Const MQ_DENY_NONE = 0 Const MQ_DENY_RECEIVE_SHARE = 1 set objQueueInfo = CreateObject("MSMQ.MSMQQueueInfo") set objMsgQueue = CreateObject("MSMQ.MSMQQueue") set objMessage = CreateObject("MSMQ.MSMQMessage") objQueueInfo.PathName = "junichia03\private$\Input" 'objQueueInfo.Formatname = "DIRECT=OS:junichia03\private$\Input" 'objQueueInfo.Formatname = "DIRECT=https://junichia03/msmq/private$\Input" set objDist = objQueueInfo.Open(MQ_SEND_ACCESS ,MQ_DENY_NONE) objMessage.Label = "msg" & date & time objMessage.Body = "メッセージボディ" objMessage.Delivery = 1 objMessage.Send(objDist) objDist.Close

上のスクリプトで重要なのは、2点です。

1点目は、12行目および14/15行目で指定している、キューのパスです。MSMQQueueInfo オブジェクトをいずれかのキューと対応付けるため、PathNameプロパティまたは FormatNamtプロパティを使用してキューのパスを設定しなければなりません。ここで設定したキューは、17行目のOpenメソッドによって初期化され、22行目のSendメソッドでメッセージ送信の宛先として使用されます。

12行目と14/15行目の違いは、パスの設定に PathName を使用しているか、FormatName を使用しているかです。このスクリプトでは、14/15行目がコメントアウトされているので、12行目が使われます。

ローカルコンピューターのプライベートキューをスクリプトから操作する場合には PathNameでもよいのですが、リモートコンピュータのプライベートキューを操作する場合には FormatName を使用します。

まずは PathName から見てみましょう。

PathNameに必要な情報は、「コンピュータ名(NetBios名またはDNS名)」と「キューの名前」です。例えば、Compuer01 に Input という名前のプライベートキューを作成した場合には以下のような指定になります。

  • Computer01\private$\input
  • .\private$\input

private$ は、プライベートキューであることを現しています。MSMQのインストール時に「ディレクトリサービス統合」も同時に組み込んでおり、キューを ActiveDirectory に公開している場合には「パブリックキュー」を作成することが可能です。パブリックキューの場合には、Private$は必要ありません。

また、どうせローカルコンピュータなので、指定を省略して「.\」とすることも可能です。このほうがいろいろなサーバーで使用する場合には汎用的ではあります。

プライベートキューとパブリックキューの違いについて、詳しくはこちらをご覧ください。

さて、次に FormatName です。

リモートコンピュータからプライベートキューにメッセージを発信する場合には、FormatName を使用しなければなりません。おそらく、より汎用的なアプリケーションにするために FormatName を使用することが多くなると思います。MSMQを使用するアプリケーションの場合、メッセージを発信するのはリモートコンピュータとなることが多いでしょうから、FormatName を使うものと覚えてしまってもよいかもしれません。

また FormatNameプロパティを使用すると Direct Format Name という記述形式が使えます。この形式はプライベートキューとパブリックキューのいずれにも使用可能ですが、面白いのはパブリックキューにアクセスする場合に、一旦ディクレクトリサービスから情報を収集することなく「直接」キューと通信が行える形式であるということです。

例えば、インターネット上のコンピュータからキューに対してメッセージを送信することを考えてみると、Active Directory をインターネット上のコンピュータに公開するというのは、ひとまず現実的ではありません。

ただ、ディレクトリサービスにアクセスしないということは、逆にいえば、メッセージをルーティングしたり、メッセージ送信時に認証したり暗号化する際には使用できないということでもありますので注意してください。

FormatName を使用したパスの指定例は以下の通りです。

  • DIRECT=IPX:00000012:00a0234f7500\private$\Input
  • DIRECT=TCP:192.168.1.1\private$\Input
  • DIRECT=OS:Computer01\private$\Input
  • DIRECT=https://Computer01.microsoft.com/msmq/private$\input
  • DIRECT=HTTPS://Computer01.microsoft.com/msmq/private$\input

Direct Format Name を使用すると、プライベートキュー、パブリックキューを問わず、 HTTP やHTTPSを使用してメッセージを送信できるところが便利です。HTTP/HTTPS を使用すると、ファイアウォールの設定でMSMQサービスへの通信が止められていてもメッセージが受け取れるところもよいですね。

ただ、HTTP/HTTPSはメッセージのSendでのみ使用可能であり、PeekやReceive時には使用できないことに注意してください。

参考までに、MSMQで使用されるポート番号についてはこちらをご覧ください。

2点目は17行目です。ここでは、Open メソッドを使用してキューをオープンしていますが、この時にキューのアクセスモードと共有モードを指定します。

Open(アクセスモード, シェアモード)

指定できる値は以下の通りで、これらを用途に応じて組み合わせます。

アクセスモード

  • 1(MQ_RECEIVE_ACCESS):キューからメッセージを読み取った後で削除する
  • 2(MQ_SEND_ACCESS):キューにメッセージを送信する
  • 32(MQ_PEEK_ACCESS):メッセージを参照する(削除しない)
  • 128(MQ_ADMIN_ACCESS):ローカルのキューに対して指定できるモードで、outgoingキュー(メッセージが送信先に出される前に一時的に格納されるローカルのキュー)にスタックされたメッセージを参照したり削除する際に使用する。MQ_PEEK_ACCESS および MQ_RECEIVE_ACCESS ともに指定する。

共有モード

  • 0(MQ_DENY_NONE):すべてのユーザーがキューにアクセス可能
  • 1(MQ_DENY_RECEIVE_SHARE):MQ_RECEIVE_ACCESSで指定可能なオプションで、既にキューがオープンされている場合には他のプロセスからのアクセスを拒否する

このスクリプト例では、メッセージを送信するためにキューをオープンするので、MQ_SEND_ACCESSとMQ_DENY_NONEを指定しています。

19行目~22行目では実際にメッセージを送信していますが、例えばこの部分を以下のように修正すれば、CSVファイルから読み込んだレコードを 1行=1メッセージ としてキューに登録することができます。

Const MQ_RECEIVE_ACCESS  = 1  Const MQ_SEND_ACCESS     = 2  Const MQ_PEEK_ACCESS     = 32  Const MQ_ADMIN_ACCESS    = 128 Const MQ_DENY_NONE           = 0  Const MQ_DENY_RECEIVE_SHARE  = 1 

set objQueueInfo = CreateObject("MSMQ.MSMQQueueInfo") set objMsgQueue = CreateObject("MSMQ.MSMQQueue") set objMessage = CreateObject("MSMQ.MSMQMessage")

objQueueInfo.Formatname = "DIRECT=https://junichia03/msmq/private$\Input"

set objDist = objQueueInfo.Open(MQ_SEND_ACCESS ,MQ_DENY_NONE)

Set objFSO = CreateObject("Scripting.FileSystemObject") Set objInputFile = objFSO.OpenTextfile("userlist.csv", 1, false)

Do Until objInputFile.AtEndOfStream

    Rec = objInputFile.ReadLine Wscript.Echo Rec strUserName = Split(Rec, ",")(0) objMessage.Label = "USERADD " & _ strUserName & " " & _ date & " " & _ time objMessage.Body = Rec objMessage.Delivery = 1 objMessage.Send(objDist)

Loop

objInputFile.Close Set objFSO = Nothing

objDist.Close

上記スクリプトを拡張子 vbs で保存し、以下のようなCSVファイルを用意して useerlist.csv というファイル名で保存してください。

testuser001,Password,\\servername\share\testuser001 testuser002,Password,\\servername\share\testuser002 testuser003,Password,\\servername\share\testuser003 testuser004,Password,\\servername\share\testuser004 testuser005,Password,\\servername\share\testuser005 testuser006,Password,\\servername\share\testuser006 testuser007,Password,\\servername\share\testuser007 testuser008,Password,\\servername\share\testuser008 testuser009,Password,\\servername\share\testuser009 testuser010,Password,\\servername\share\testuser010

コマンドプトンプトでスクリプトを実行すると、CSVファイルから読み込まれたレコードが以下のようにキューに登録されます。

csv2msmq