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

WSHに渡された引数の妥当性を自動検証する

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

山田 祥寛
2004/07/31
 
対象OS
Windows NT
Windows 2000
Windows XP
Windows Server 2003
<runtime>要素で宣言された引数情報は、あくまでオンライン・ヘルプを作成するための情報にすぎず、実行時に仕様とは異なる引数を渡してもWSHはエラーを発生しない。
だが<runtime>要素に記述された引数情報と実行時に渡された引数とを動的に照合・検証するスクリプトを作成・利用することで、エラーを検出することができる。
 
解説

 Windows TIPS「WSHスクリプトでヘルプ・メッセージを表示する」でも紹介したように、WSHスクリプト(「.wsf」ファイル)では、<runtime>要素を利用することで、コード内で使用する引数情報を宣言することができる。

 しかしここで注意していただきたいのは、WSHは実行時にこの<runtime>要素を参照して「いない」ということだ。つまり、宣言されたものとは異なる引数を実行時に渡したとしても(また、必須で要求されている引数を渡さなかったとしても)、WSHは特別なエラーを返さない。もちろん多くの場合は、その引数を利用して何らかの処理を行うタイミングで実行時にエラーが返されるはずであるが、コードの内容によっては、エラーすらも返さずに誤った内容で処理を継続してしまう可能性もある。予期せぬ不具合を招かないためにも、最低限、引数の内容を処理前に検証しておくことは欠かせない。

 ただ、このような入力データの妥当性検証は、単調であるだけに煩雑であることが多い。本来のコードのほかに、いちいち検証ロジックを記述しなければならないのは、間違いのもとであるだけでなく、本来のロジックを読みにくくする原因ともなる。また、引数情報を<runtime>要素とスクリプト・コードとで二重管理しなければならないのも面倒である。スクリプト・コードは修正したのに、<runtime>要素は未修正のままだったなどということはよくあることだ。

Windows TIPS「WSHスクリプトでヘルプ・メッセージを表示する」

 そこで本稿では、<runtime>要素で定義された引数情報を実行時に動的に取得し、入力パラメータを検証するためのスクリプトレット・コンポーネントを作成・紹介する。「スクリプトレット(ScriptLets)」とは、スクリプト言語でCOMコンポーンネントを作成するための技術だ。スクリプトレットを利用することで、Visual Basic(VB)やC++言語のように高度なプログラム言語を使わなくても、簡単にコンポーネントを作成することができる。ここで紹介する検証コンポーネントを利用すると、WSHスクリプトでは定型的なコードを埋め込むだけで、入力データの検証処理(およびエラー時にはエラー・メッセージの出力)を行うことができる。


操作方法

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

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

※ファイルvalidation.wsf

<?xml version="1.0" encoding="Shift_JIS" standalone="yes" ?>
<package>
  <component id="validation">
    <?component error="True" debug="True" ?>
    <comment>パラメータ検証コンポーネント</comment>
    <registration progid="Wings.Validator"
      description="パラメータ検証コンポーネント"
      version="1" remotable="True" />
    <public>
      <method name="Validate" dispid="0">
        <parameter name="path" />
      </method>
    </public>
    <object id="objFs"  progid="Scripting.FileSystemObject" />
    <object id="objXml" progid="Msxml2.DOMDocument" />
    <script language="VBScript">
    <![CDATA[
    ' Validateメソッドの実行には、検証の対象となるスクリプトの絶対パス、名前付き引数(WshNamedオブジェクト)、名前なし引数(WshUnnamedオブジェクト)を引き渡す必要がある。Validateメソッドは、渡された情報に基づいて引数の検証を行い、エラー時にはエラー・メッセージを呼び出し元に返す
    Function Validate(path, argsNamed, argsUnNamed)
      objXml.async=False
      objXml.Load(path)
      ' 指定されたスクリプトファイルに含まれる<named>、<unnamed>要素を取得
      Set named=objXml.selectNodes("//named")
      Set unnamed=objXml.selectNodes("//unnamed")
      ' <named>要素(名前付き引数)に含まれる情報を順番に取得、検証処理
      For i=0 To named.Length-1
        Set tmp=named.item(i)
        ' required属性がTrueであり、かつ、実行時に指定された引数の中に対応する名前(name属性)の引数が存在しない場合はエラー
        If tmp.getAttribute("required")="True" Then
          If Not argsNamed.Exists(tmp.getAttribute("name")) Then
            Validate=tmp.getAttribute("name") & "オプションは必須です。"
          End If
        End If
        ' 実行時に指定された引数の中に対応する名前(name属性)の引数が存在し、かつ、type属性がboolean(ブール)型である場合、該当する引数の値が「+」または「-」であることを確認する。それ以外の場合はエラー
        If argsNamed.Exists(tmp.getAttribute("name")) Then
          If tmp.getAttribute("type")="boolean" Then
            If argsNamed.Item(tmp.getAttribute("name"))<>"+" And argsNamed.Item(tmp.getAttribute("name"))<>"-" Then
              Validate=tmp.getAttribute("name") & "はBoolean型です。"
            End If
          End If
        End If
      Next
      ' <unnamed>要素(名前なし引数)に含まれる情報を順番に取得、検証処理
      For i=0 To unnamed.Length-1
        Set tmp=unnamed.item(i)
        ' required属性がTrueで、かつ、実行時に指定された名前なし引数の数が0である場合にはエラー
        If tmp.getAttribute("required")="True" Then
          If argsUnNamed.Length=0 Then
            Validate="名前なし引数は必須です。"
          End If
        End If
        ' many属性がTrueでなく(つまり、名前なし引数を複数指定できない)、かつ、実行時に指定された名前なし引数の数が2以上である場合にはエラー
        If tmp.getAttribute("many")<>"True" Then
          If argsUnNamed.Length>1 Then
            Validate="名前なし引数は単数指定です。"
          End If
        End If
      Next
    End Function
    ]]>
    </script>
  </component>
</package>
  • サンプル・ファイルのダウンロード
    注:サンプルvalidation.wscを実行するには、上のサンプル・ファイルを右クリックしてvalidation.wscというファイル名で保存する)

 スクリプトレットの実行ファイルは拡張子「.wsc」(Windows Scripting Components)とする必要がある。ファイル名自体は何でもよいが、ここでは「validation.wsc」という名前で保存しておこう。

 スクリプトレット・コンポーネントは、使用に先立ってレジストリに登録しておく必要がある(登録には管理者権限が必要となる)。具体的には、エクスプローラで該当ファイルを右クリックし、表示されたコンテキスト・メニューから[登録]を選択する。ただしレジストリへの登録後もファイルは削除してはいけないので(登録時の場所に置いておく必要がある)、あらかじめスクリプト登録用のフォルダなどを作成して、保存しておくとよいだろう。

スクリプトレット・コンポーネントの登録
スクリプトレット・コンポーネントを利用するには、最初にレジストリに登録しておく必要がある。登録を解除するには、コンテキスト・メニューから[登録解除]を実行すればよい。
  .wscファイルを選択し、マウスを右クリックして、ポップアップ・メニューから[登録]を選択する。いったん登録した.wscファイルは、[登録解除]するまで、移動や削除してはいけないので(アクセスできない場合は、スクリプトレットの使用時にエラーとなる)、ファイルの置き場所には注意すること。

 登録が完了すると、次のようなダイアログが表示されるはずである。

スクリプトレット・コンポーネントの登録完了の通知
コンポーネントの登録が正常に完了すると、このようなダイアログが表示される。

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

 次に、上で作成したスクリプトレット・コンポーネントを利用するためのWSHスクリプトを作成しておこう。取りあえず検証処理が正しく動作することを確認するためだけのコードであるので、<script>要素内のスクリプト・コードも必要最小限のものにとどめている。

※ファイル valid.wsf

<?xml version="1.0" encoding="Shift_JIS" standalone="yes" ?>
<package>
<job id="MailTransfer">
<?job error="True" debug="True" ?>
<runtime>
  <description>指定されたあて先にメールを配信する</description>
  <named name="address" helpstring="送信先アドレス"
    type="string" required="True" />
  <named name="replace" helpstring="本文文字列の置換を行うか"
    type="boolean" required="False" />
  <unnamed name="body" helpstring="本文を格納したテキストファイル"
    many="False" required="True" />
  <example>valid.wsf /address:sample@example.com /replace:+ C:\mail.txt
    </example>
</runtime>
<!--引数検証用のコンポーネントWings.Validatorをインスタンス化する-->
<object id="objVld" progid="Wings.Validator" />
<script language="VBScript">
<![CDATA[
' 実行時に指定された名前付き引数、名前なし引数を取得(詳細は、後日公開予定の別稿「WSHで名前付き引数と名前なし引数を扱う」を参照いただきたい)
Set argsNamed=WScript.Arguments.Named
Set argsUnNamed=WScript.Arguments.UnNamed
' Validateメソッドを実行。引数には、第1引数から実行中スクリプトの絶対パス、名前付き引数(WshNamedオブジェクト)、名前なし引数(WshUnnamedオブジェクト)を指定する。Validateメソッドはエラー発生時にエラー・メッセージを、引数に問題がない場合には空文字列を返す
strErr=objVld.Validate(WScript.ScriptFullName,argsNamed,argsUnNamed)
' Validateメソッドの戻り値が空文字列でない場合には、なにかしら引数にエラーがあったものと見なして、エラー・メッセージをダイアログ出力する。また、その後、スクリプトの実行を強制的に終了する
If strErr<>"" Then
  WScript.Echo strErr
  WScript.Quit(1)
End If
' 検証処理後は、本来の処理を記述する(本稿では割愛)
WScript.Echo("正しい場合の処理...")
]]>
</script>
</job>
</package>
  • サンプル・ファイルのダウンロード
    注:サンプルvalid.wsfを実行するには、上のサンプル・ファイルを右クリックしてvalid.wsfというファイル名で保存する)

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

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

 valid.wsfを実行するには、コマンド・プロンプトから以下のようなコマンドを入力する必要がある。

C:\> valid.wsf /address:sample@example.com /replace:+ C:\mail.txt

 これは正しい実行コマンドなので、次のようなダイアログが表示されるはずである。

引数の指定が正しい場合に表示されるダイアログ
与えられた引数の数やタイプなどが正しければ、このようなダイアログが表示される。

 だが、例えば、/addressオプションを省略したり、/replaceオプションに「+」「-」以外の値を指定したりしてみよう。すると、次のようなダイアログが出力されるはずだ。引数の値、また、「.wsf」ファイルで<runtime>要素の設定を変更するなどして、表示の変化を確認してみてほしい。

検証エラー時に表示されるダイアログ
実行時に渡された引数情報を動的に確認し、エラー時にはメッセージをダイアログ表示する。

 なお、本サンプルでは、コード簡素化のために1ファイル複数ジョブには対応していない、<named>…<unnamed>要素のmany/required属性などブール型の値に1、0は指定できないなどの制限もある。だが修正はさほどに難しいことではないので、必要に応じて適宜修正して活用いただきたい。End of Article

関連記事
  Windows TIPS:WSHスクリプトでヘルプ・メッセージを表示する(Windows Server Insider )
     
「Windows TIPS」


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

注目のテーマ

Windows Server Insider 記事ランキング

本日 月間