Windows TIPS
[Scripting]
  Windows TIPS TOPへ
Windows TIPS全リストへ

スクリプトレット・コンポーネントでプロパティを定義する

解説をスキップして操作方法を読む

山田 祥寛
2004/10/16
 
対象OS
Windows 2000
Windows XP
Windows Server 2003
スクリプトレットでは、コンポーネント内共通で利用するパラメータを「プロパティ」として表現することができる。
プロパティは単なる変数として定義することもできるが、アクセス用の関数を介することで、プロパティ設定時の妥当性チェック、参照時の値加工などを行うことができる。
 
解説

 Windows TIPS「よく利用するジョブをスクリプトレットでコンポーネント化する」では、WSHスクリプトやASP(Active Server Page)スクリプトから共通して利用できるコンポーネントを、VBScriptやJScriptのようなスクリプト言語で定義する方法について紹介した。

 このようなコンポーネントには、もちろん、内部に1つの処理(メソッド)だけを含むような単純なものもある。しかし多くの場合、1個のコンポーネントには機能的に関連する複数のメソッドが含まれるのが普通だ。そして複数の処理は、共通するパラメータを利用する場合が少なくない。

 例えば、これから紹介するカウンタ・コンポーネントのケースを考えてみよう。カウンタ・コンポーネントに含まれるIncrementメソッド(カウンタ値をインクリメント)、ShowCountメソッド(カウンタ値を参照)では共通パラメータとして「カウンタ情報を格納するためのデータベース名」を必要とする。もちろん、こうした共通のパラメータは個々のメソッドの引数として渡しても構わないが、利用者側としてはメソッドの呼び出しごとに共通の情報をいちいち指定しなければならないのは面倒だ。そこで、こうした情報はプロパティ(属性)として定義してしまうとよい。プロパティに格納された情報は、コンポーネントがインスタンス化されている間は維持されるので、各メソッドを呼び出す際に指定する必要もなく、呼び出し側ではよりスマートなコードが記述できる。

 スクリプトレットでは、プロパティを2つの方法で実装することができる。

 1つ目は、スクリプト・ブロック内で宣言された変数に、直接、値を格納する方法だ。こちらは変数を宣言するだけなので、実装自体はシンプルであるが、コンポーネント側で何も値の制御ができないというデメリットがある。

 もう1つの方法は、変数に対してあらかじめ決められた関数を介してアクセスする方法だ。こちらの方法では、変数宣言のほかに、変数を参照/設定するためのアクセス関数を用意しなければならず、前者の方法よりも実装は煩雑だ。しかし、変数(プロパティ値)の読み書きを制御できる、設定時に値の妥当性を検証できる、参照時に値の整形が可能であるなど、より柔軟な操作が可能になる。後者の方法を利用することで、コンポーネント内でプロパティ値の制御を完結することができるので、部品としての独立性もより向上する。

 以上、前置きが長くなったが、これらを踏まえて、プロパティを含むコンポーネントの定義を具体的なサンプル例とも併せて紹介しよう。紹介するカウンタ・コンポーネントは、与えられたキーと値の組み合わせで、カウンタ値をAccessデータベースに格納するためのコンポーネントだ。カウンタ・コンポーネントに含まれるメソッド、プロパティは以下のとおりである。

名前 種類 機能
Database プロパティ カウンタ値を記録するデータベース
Increment メソッド 指定された名前のカウンタ値をインクリメント
ShowCount メソッド 指定された名前のカウンタ値を取得
カウンタ・コンポーネントのメソッドとプロパティ
 

操作方法

手順1―テキスト・エディタでスクリプトレットのコードを入力する

 テキスト・エディタ(メモ帳でも何でもよい)を開き、以下のコードを入力してほしい。なお、引用符(')で始まる行、<!--〜-->で囲まれたブロックは、コードの意味を解説するためのコメント部分なので、省略してもよい。

※ファイルcounter.wsc

<?xml version="1.0" encoding="Shift_JIS" ?>
<package>
  <component id="counter">
    <?component error="True" debug="True" ?>
    <registration progid="Wings.Counter" version="1" />
    <public>
      <!--Databaseプロパティの定義。
          プロパティ値参照用メソッドはgetDb、設定用メソッドはsetDb
          <get>要素の省略時、プロパティは書き込み専用、<put>要素の省略時には
          プロパティは読み取り専用であると見なされる-->

      <property name="Database">
        <get internalName="getDb" />
        <put internalName="setDb" />
      </property>
      <!--Incrementメソッドの定義。
          内部関数名はincrement、パラメータはKey、Step-->

      <method name="Increment" internalName="increment">
        <parameter name="Key" />
        <parameter name="Step" />
      </method>
      <!--ShowCountメソッドの定義。内部関数名はshowCount、パラメータはKey-->
      <method name="ShowCount" internalName="showCount">
        <parameter name="Key" />
      </method>
    </public>
    <!--スクリプト内で使用するコンポーネントをインスタンス化-->
    <object id="db" progid="ADODB.Connection" />
    <object id="fs" progid="Scripting.FileSystemObject" />
    <script language="VBScript">
    <![CDATA[
    ' Databaseプロパティの値を格納する変数
    Dim dbName
    ' Databaseプロパティの値を取得するための関数
    Function getDb()
      getDb=dbName
    End Function
    ' Databaseプロパティの値を設定するための関数
    ' ただし、指定されたファイルが存在しない場合は値をセットしない
    Function setDb(dbPath)
      If fs.FileExists(dbPath) Then
        dbName=dbPath
      End If
    End Function
    ' 指定されたカウンタを指定値だけインクリメントするIncrementメソッドを定義。
    ' 引数としてカウンタ名とインクリメントする数値を指定
    Sub increment(Key,Step)
      db.Provider="Microsoft.Jet.OLEDB.4.0" ' 接続プロバイダ
      db.Mode=3 ' 接続モード(読み書き両用)
      db.ConnectionString=dbName ' 接続文字列(データベースへのパス)
      db.Open
      ' 指定されたカウンタ名がすでにcounterテーブルに存在するかを確認
      ' 存在しない場合はレコードを登録、存在する場合は既存レコードを更新
      Set rs=db.Execute("SELECT [key] FROM [counter] WHERE [key]='" & Key & "'")
      If rs.EOF Then
        db.Execute("INSERT INTO [counter]([key],[count]) VALUES('" & Key & "'," & Step & ")")
      Else
        db.Execute("UPDATE [counter] SET [count]=[count]+" & Step & " WHERE [key]='" & Key & "'")
      End If
      db.Close
    End Sub
    ' 指定されたカウンタの値を返すShowCountメソッドを定義。
    ' 引数としてカウンタ名を指定
    Function showCount(Key)
      db.Provider="Microsoft.Jet.OLEDB.4.0" ' 接続プロバイダ
      db.Mode=1 ' 接続モード(読み取り専用)
      db.ConnectionString=dbName ' 接続文字列(データベースへのパス)
      db.Open
      ' 指定されたキー(カウンタ)名に対応するカウント値を取得
      Set rs=db.Execute("SELECT [count] FROM [counter] WHERE [key]='" & Key & "'")
      ' カウント値(取得できなかった場合はエラーメッセージ)を取得
      If rs.EOF Then
        showCount="カウント値を取得できませんでした。"
      Else
        showCount=rs("count")
      End If
      db.Close
    End Function
    ]]>
    </script>
  </component>
</package>

  • サンプル・ファイルのダウンロード
    注:サンプル・ファイルcounter.wscをダウンロードするには、上のリンクを右クリックしてcounter.wscというファイル名で保存する。保存場所をC:\WshCounter以外にするときは、後のサンプル・ファイルも変更すること)

 スクリプトレットの実行ファイルは拡張子「.wsc」(Windows Scripting Components)とする必要がある。ファイル名自体は何でもよいが、ここでは「counter.wsc」という名前で保存しておこう。ファイルを保存するフォルダはどこでもよいが、後で紹介するサンプル・ファイルでは、C:\WshCounterにcounter.wscとcounter.mdbファイルが存在するものとしている。保存する場所を変更する場合は、後のサンプル・ファイルの修正も忘れないようにしていただきたい。

 なお、スクリプトレットを動作させるには、あらかじめコンポーネントをレジストリに登録しておく必要がある。コンポーネントの登録方法については、先のWindows TIPS「よく利用するジョブをスクリプトレットでコンポーネント化する」を参照していただきたい。簡単に述べると、.wscファイルをエクスプローラ上で右クリックして、ポップアップ・メニューから[登録]を選択すればよい。

手順2―カウンタ記録用のデータベースを用意する

 手順1のカウンタ・コンポーネントを動作するには、カウンタ情報を記録するためのAccessデータベース(「.mdb」ファイル)が必要となる。counter.wscと同じフォルダに「counter.mdb」という名前でAccessデータベースを作成して欲しい。

 Accessデータベースには、counterテーブルを以下のフィールド・レイアウトで作成しておくこと。中身のデータは特に必要ない。

フィールド名 データ型 概要
key テキスト型 カウンタのキー(主キー)
count 長整数型 カウント値
counterテーブルのフィールド・レイアウト
Accessデータベースにcounterテーブルを作成し、これらのフィールドを作成する。
  • サンプル・ファイルのダウンロード
    注:サンプル・データベースcounter.mdbをダウンロードするには、上のリンクを右クリックしてcounter.mdbというファイル名で保存する。保存場所をC:\WshCounter以外にするときは、後のサンプル・ファイルも変更すること)

手順3―テキスト・エディタでWSHスクリプトのコードを入力する

 次に、手順1で作成したスクリプトレット・コンポーネントを利用するためのWSHスクリプトを作成しておこう。取りあえずスクリプトレット・コンポーネントで定義された2つのメソッドが正しく動作することを確認するためだけのコードであるので、<script>要素内のスクリプト・コードも必要最小限のものにとどめている。なお、このファイル中では、.mdbファイルへのパスをコード中に直接記述しているので、必要ならば書き換えていただきたい。これを忘れると、実行しても何も結果が表示されない。

※ファイルcounter.wsf

<?xml version="1.0" encoding="Shift_JIS" ?>
<package>
  <job id="count">
  <?job error="true" debug="true" ?>
  <!--スクリプトブロック内で使用するコンポーネントをインスタンス化-->
  <object id="db" progid="ADODB.Connection" />
  <object id="cnt" progid="Wings.Counter" />
  <script language="VBScript">
  <![CDATA[
  ' 「.mdb」ファイルへのパスを定義(適宜、環境に併せて変更すること)
  Const DBPATH="C:\WshCounter\counter.mdb"
  cnt.Database=DBPATH ' カウント値を取得するデータベースへのパス
  ' 現在のスクリプトへのパスをキーに、カウント値をインクリメント
  cnt.Increment WScript.ScriptFullName,1
  ' 現在のスクリプトへのアクセス数(カウント数)を取得
  WScript.Echo("カウンタ値は" &
cnt.showCount(WScript.ScriptFullName) & "です")
  ]]>
  </script>
  </job>
</package>

 WSHの実行ファイルは拡張子「.wsf」(Windows Scripting host File)とする必要がある。ファイル名自体は何でもよいが、ここでは「counter.wsf」という名前で保存しておこう。

手順3―WSHのコードを実行する

 counter.wsfを実行するには、エクスプローラなどからcounter.wsfをダブルクリックするだけでよい。実行ごとにカウント数がインクリメントされていれば成功だ。カウンタ・コンポーネントは実行ファイル名をキーにカウント値を管理しているので、counter.wsfを異なるファイル名に変更して実行すると、カウント値は1で初期化されるはずだ。

counter.wsfの実行結果
WSHスクリプトを実行するたびにカウント値がインクリメントされる。カウント値は指定されたAccessデータベースに保存される。
  表示されたカウンタの値。

スクリプトレットにおけるプロパティの定義

 本稿で注目いただきたいのは、プロパティを定義している個所だ。本稿では、冒頭述べた2つのアプローチのうち、後者の「関数を介する」方法を採用している。そして、設定時にはファイルが実際に存在するかどうかを確かめ、存在しない場合には設定そのものを無効にするようにしているわけだ。もちろん、このような妥当性検証が必要ない場合には、より単純な「変数のみでプロパティを定義する」方法を採ることもできる。そのような場合には、<property>要素や変数アクセス用の関数を略記した上で、プロパティ名と同名の変数を<script>要素内で定義すればよい。

 サンプル中では、<property>要素中の<get>と<put>要素を次のように記述しているが、

※元の構文

<property name="Database">
  <get internalName="getDb" />
  <put internalName="setDb" />
</property>

これを次のような省略した形式で記述することも可能である。

※省略形式1―<get>/<put>要素のinternalName属性を省略

<property name="Database">
  <get />
  <put />
</property>
 
※省略形式2―<property>要素内にまとめて定義

(1) <property name="Database" get put />
(2) <property name="Database" get="getDb" put="setDb" />

 <get>/<put>要素のinternalName属性を省略した場合には、<script>要素で利用する関数の名前は、それぞれ「get_プロパティ名」「put_プロパティ名」としなければならないので、注意すること。例えば上記スクリプト中の該当部分は、次のように記述する。End of Article

Function get_Db()
  (…中略…)
End Function
Function put_Db(dbPath)
  (…中略…)
End Function
 
「Windows TIPS」


Windows Server Insider フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Windows Server Insider 記事ランキング

本日 月間