seraphyの日記

日記というよりは過去を振り返るときのための単なる備忘録

Windows Scriptファイル(wsf)を使ってイベントログを保存したりメールを送信したりするサンプル(JScript使用版)

WSFソースコード

<?xml version="1.0" encoding="utf-8" ?>
<package>
  <job id="exportEventLog">
  <?job debug="false" ?>
    <runtime>
      <description>イベントログの指定したログを指定したファイル(*.evt)として保存します。
実行時ユーザは管理者権限がなければなりません。
      </description>
      <named name="logName" helpstring="ログ名" type="string" required="true" />
      <named name="out" helpstring="出力ファイル名" type="string" required="true" />
      <example>
        <![CDATA[
cscript //job:exportEventLog logtools.wsf /logname:Security /out:c:\temp\c.evt
        ]]>
      </example>
    </runtime>
    <script language="JScript">
      <![CDATA[
        // show usages
        var namedArgs = WScript.Arguments.Named;
        if (namedArgs.length == 0 || !namedArgs.exists("out") || !namedArgs.exists("logName")) {
            WScript.Arguments.ShowUsage();
            WScript.Quit(1);
        }
        var logName = namedArgs("logName");
        logName = logName.replace("[\\'|\\\"]", "");
        var objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate,(Backup,Security)}!\\\\.\\root\\cimv2");
        var colLogFiles = objWMIService.ExecQuery(
            "Select * from Win32_NTEventLogFile where LogFileName = '" + logName + "'")
        for (var enm = new Enumerator(colLogFiles); !enm.atEnd(); enm.moveNext()) {
            var objLogFile = enm.item();
            if (objLogFile.BackupEventLog(namedArgs("out")) > 0) {
                WScript.echo("イベントログのファイル保存に失敗しました。");
                WScript.Quit(1);
            }
        }
      ]]>
    </script>
  </job>

  <job id="sendmail">
  <?job debug="false" ?>
    <runtime>
      <description>メールをSMTPサーバを使って送信します。
添付ファイルの指定が可能です。
サーバおよびポートの指定は本スクリプト内のリソース指定(smtp-host/smtp-port)で変更します。
      </description>
      <named name="from" helpstring="送信元メールアドレス(必須)" type="string" required="true" />
      <named name="to" helpstring="送信先メールアドレス" type="string" />
      <named name="cc" helpstring="同報送信先メールアドレス" type="string" />
      <named name="bcc" helpstring="非公開同報送信先メールアドレ" type="string" />
      <named name="subject" helpstring="タイトル(必須)" type="string" />
      <named name="body" helpstring="本文(必須)" type="string" />
      <named name="attachements" helpstring="添付ファイル(フルパス指定、セミコロンで複数指定可)" type="string" />
      <example>
        <![CDATA[
cscript //job:sendmail logtools.wsf /to:xxx@hostname /from:yyy@hostname /subject:test /body:testbody /attachmenets:c:\temp\a.txt;c:\temp\b.txt
        ]]>
      </example>
    </runtime>

    <!-- SMTPサーバ -->
    <resource id="smtp-host">サーバー名</resource>
    <!-- SMTPポート(25) -->
    <resource id="smtp-port">25</resource>

    <script language="JScript">
      <![CDATA[
        // show usages
        if (WScript.Arguments.length == 0) {
            WScript.Arguments.ShowUsage();
            WScript.Quit(1);
        }
        var namedArgs = WScript.Arguments.Named;

        // 引数のチェック
        if (namedArgs("to") == undefined && namedArgs("cc") == undefined && namedArgs("bcc") == undefined) {
          WScript.echo("[ERROR] 引数toまたはcc,bccのいずれか一方は必ず指定しなければなりません。");
          WScript.Quit(1);
        }
        if (namedArgs("from") == undefined || namedArgs("subject") == undefined || namedArgs("body") == undefined) {
          WScript.echo("[ERROR] 引数from,subject,bodyは必ず指定しなければなりません。");
          WScript.Quit(1);
        }

        // CDOによるメール送信内容の設定
        var oMessage = new ActiveXObject("CDO.Message");
        oMessage.From = namedArgs("from");
        if (namedArgs("to") != undefined) {
          oMessage.To = namedArgs("to");
        }
        if (namedArgs("cc") != undefined) {
          oMessage.Cc = namedArgs("cc");
        }
        if (namedArgs("bcc") != undefined) {
          oMessage.Bcc = namedArgs("bcc");
        }
        oMessage.Subject = namedArgs("subject");
        oMessage.TextBody = namedArgs("body");

        // 添付ファイル(フルパス指定、セミコロン区切り)
        if (namedArgs("attachments") != undefined) {
            var atts = namedArgs("attachments").split(";");
            for (var attidx = 0; attidx < atts.length; attidx++) {
                var attfile = atts[attidx];
                oMessage.AddAttachment(attfile);
            }
        }

         // CDOを外部SMTPサーバを用いて送信するように設定
        oMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2;
        oMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = getResource("smtp-host");
        oMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = getResource("smtp-port");
        oMessage.Configuration.Fields.Update();

        // 送信
        oMessage.send();
      ]]>
    </script>
  </job>
</package>

説明

WSFファイルについて
  • wsfはxml形式で複数のスクリプトを1つにまとめて書ける。
  • jobタグで1つのジョブを定義する。

その場合、cscript.exe //job:ジョブ名のように起動する。

  • jobタグごとに引数を定義できる。
    • 引数には名前つき引数と、名前なし引数がある。

名前つき引数は、cscript.exe //job:ジョブ名 /引数名:引数の値 ...のように指定する。
名前引き引数はWScript.Argument.Namedで参照できる。

  • jobタグごとに使用例(example)を記述できる。

名前引き引数とexampleタグは、WScript.ShowUsage()で表示できる。

イベントログの保存について
  • イベントログのアクセスにはWMIを用いる。
  • impersonationLevel=impersonateで特権を有効化する必要がある。
  • ExecQueryが返すコレクションはVBScriptの場合はFor Each構文でループできるが、JScriptを使う場合はEnumeratorオブジェクトとしてラップすることでイテレート可能になる。
メール送信について
  1. CDOSYSのConfiguration.Fieldsにパラメータを指定することで、SMTP認証などを設定できる。
  2. POP before SMTPには対応していない。

参考URL

Collaboration Data Objects(CDO)の手引き

CDOとは何か、どんな種類があるのか?
http://www.microsoft.com/japan/msdn/windows/windows2000/cdo_roadmap.aspx

*1:Windows2000, XP, Windows2003にはCDOSYSが入っている。OfficeやExchangeとは関係ない。