2016年5月17日火曜日

EventCheck.bat

@if(0)==(0) echo off
@rem http://computer-technology.hateblo.jp/entry/20131025/p1
setlocal
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
@rem setlocal DISABLEDELAYEDEXPANSION

@rem 説明:
@rem Windowsの開始日時と終了日時の一覧を出力します。
@rem
@rem 出力例:
@rem   2016/01/28 09:32:21 Thu - 2016/01/28 20:46:37 Thu
@rem   2016/01/29 09:40:02 Fri - 2016/01/29 18:40:56 Fri
@rem   2016/02/01 09:53:05 Mon - 2016/02/01 19:52:03 Mon
@rem   2016/02/02 09:30:32 Tue -
@rem
@rem 引数
@rem   日数
@rem     過去何日前からの記録をするかの日数を指定します。
@rem     日数は正の整数です。
@rem     既定値は40です。
@rem     不正値チェックはしていません。不正値の場合、異常終了します。
@rem
@rem 戻り値
@rem   0
@rem     常に0です。
@rem
@rem 情報源
@rem   Windowsの開始日時
@rem     Windowsのシステム ログのイベントID=6005(イベント ログ サービスの開始)。
@rem
@rem   Windowsの終了日時
@rem     Windowsのシステム ログのイベントID=6006(イベント ログ サービスの終了)。
@rem
@rem Windowsのシステム ログ内を検索するときの期間の条件
@rem   期間の開始日
@rem   「40日前」は当バッチ コマンドの第1引数で変更できます。
@rem
@rem   期間の終了日
@rem   当バッチ コマンド実行日。
@rem
@rem 当バッチ コマンドの名称
@rem   変更できます。
@rem
@rem 実行方法
@rem   引数を指定しない場合
@rem     EventCheck.bat
@rem
@rem   引数を指定する場合
@rem     EventCheck.bat 10

@rem Usage:
@rem EventCheck.bat


@rem ####################
@rem Batch.
@rem ####################

@rem ....................
@rem Batch main.
@rem ....................
set rv=0
if "%~1"=="" (                                              call :L_call_BAT_NoArgs
) else (                                                    call :L_call_BAT_OtherArgs %*
)

@rem ....................
@rem Exit.
@rem ....................
@rem echo.
@rem pause
echo 終了するには何かキーを押してください . . .
pause>nul
exit /b !rv!
goto :eof


@rem ....................
@rem No args.
@rem ....................
:L_call_BAT_NoArgs
@rem echo BAT %0 %* ....................
call :L_call_JS "JS_EventCheck"
set /a rv=!errorlevel!+0
goto :eof


@rem ....................
@rem Other args.
@rem ....................
:L_call_BAT_OtherArgs
@rem echo BAT %0 %* ....................
call :L_call_JS "JS_EventCheck" %*
set /a rv=!errorlevel!+0
goto :eof


@rem ....................
@rem Echo ErrorLevel.
@rem ....................
:L_echoErrorLevel
@rem echo BAT L_echoErrorLevel ....................
@rem echo BAT %0 R errorlevel=!errorlevel!
@rem echo.
goto :eof


@rem ....................
@rem Call JScript.
@rem ....................
:L_call_JS
@rem echo BAT %0 %* ....................
set "jsargs=%*"
if "!jsargs!"=="" (
  cscript.exe //nologo //e:JScript "%~f0"
) else (
  cscript.exe //nologo //e:JScript "%~f0" !jsargs!
)
call :L_echoErrorLevel
goto :eof


@end


// ####################
// JScript.
// ####################


// ....................
// No args.
// ....................
function NoArgs() {
//  WScript.Echo("JS NoArgs ....................");
  // WScript.Echo("JS Argc=" + WScript.Arguments.length + ".");
  WScript.Echo("There are no arguments.");
  return 1;
}


http://qiita.com/osakanafish/items/c64fe8a34e7221e811d0
/**
 * 日付をフォーマットする
 * @param  {Date}   date     日付
 * @param  {String} [format] フォーマット
 * @return {String}          フォーマット済み日付
 */
var formatDate = function (date, format) {
  var WEEK_DAY_EN = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
  if (!format) format = 'YYYY-MM-DD hh:mm:ss.SSS www';
  format = format.replace(/YYYY/g, date.getFullYear());
  format = format.replace(/MM/g, ('0' + (date.getMonth() + 1)).slice(-2));
  format = format.replace(/DD/g, ('0' + date.getDate()).slice(-2));
  format = format.replace(/hh/g, ('0' + date.getHours()).slice(-2));
  format = format.replace(/mm/g, ('0' + date.getMinutes()).slice(-2));
  format = format.replace(/ss/g, ('0' + date.getSeconds()).slice(-2));
  if (format.match(/S/g)) {
    var milliSeconds = ('00' + date.getMilliseconds()).slice(-3);
    var length = format.match(/S/g).length;
    for (var i = 0; i < length; ++i) format = format.replace(/S/, milliSeconds.substring(i, i + 1));
  }
  format = format.replace(/www/g, (WEEK_DAY_EN[date.getDay()]));
  return format;
};


// http://www.activexperts.com/admin/scripts/wmi/jscript/0406/
function WmiDate_parseWmiDateTimeString(strDtmDate) {
  if (strDtmDate == null) {
    return "null date";
  }
  var strDateTime;
  if (strDtmDate.substr(4, 1) == 0) {
    strDateTime = strDtmDate.substr(5, 1) + "/";
  }  else  {
    strDateTime = strDtmDate.substr(4, 2) + "/";
  }
  if (strDtmDate.substr(6, 1) == 0) {
     strDateTime = strDateTime + strDtmDate.substr(7, 1) + "/";
  }  else  {
    strDateTime = strDateTime + strDtmDate.substr(6, 2) + "/";
  }
  strDateTime = strDateTime +
      strDtmDate.substr(0, 4) + " " +
      strDtmDate.substr(8, 2) + ":" +
      strDtmDate.substr(10, 2) + ":" +
      strDtmDate.substr(12, 2);
  return(strDateTime);
};


// http://qiita.com/search?q=JScript%E3%81%A7WMI&sort=rel
// http://qiita.com/tnakagawa/items/89917ca9fbde1c2f47a9
function WmiDate(date) {
  var datetime = null;
  if (date && date instanceof Date) {
    // 「SWbemDateTime」オブジェクト生成
    datetime = new ActiveXObject("WbemScripting.SWbemDateTime");
    datetime.Year = date.getUTCFullYear();                      // 年
    datetime.Month = date.getUTCMonth() + 1;                    // 月
    datetime.Day = date.getUTCDate();                           // 日
    datetime.Hours = date.getUTCHours();                        // 時
    datetime.Minutes = date.getUTCMinutes();                    // 分
    datetime.Seconds = date.getUTCSeconds();                    // 秒
    datetime.Microseconds = date.getUTCMilliseconds() * 1000;   // ミリ秒
  }
  return datetime;
};


function Date_formatLocal(date) {
  var ret = null;
  var DLM_YMD = "/";
  var DLM_HMS = ":";
  if (date && date instanceof Date) {
    ret = date.getFullYear() + DLM_YMD                          // 年
        + ("0" + (date.getMonth() + 1)).slice(-2) + DLM_YMD     // 月
        + ("0" + date.getDate()).slice(-2) + " "                // 日
        + ("0" + date.getHours()).slice(-2) + DLM_HMS           // 時
        + ("0" + date.getMinutes()).slice(-2) + DLM_HMS         // 分
        + ("0" + date.getSeconds()).slice(-2)                   // 秒
//      + "." + ("00" + date.getMilliseconds()).slice(-3)       // ミリ秒
//      + "000"                                                 // ナノ秒
//      + date.getTimezoneOffset()                              // 時差
        ;
  }
  return ret;
};


// http://qiita.com/tnakagawa/items/ae579f19d74dd86e40c6
function wmiProps(wqlQuery) {
  // 結果
  var result = [];
  try {
    // 「SWbemLocator」オブジェクト取得
    var locator = new ActiveXObject("WbemScripting.SWbemLocator");
    // 「SWbemServices」オブジェクト取得(ローカルコンピュータ、名前空間「root\CIMV2」)
    var services = locator.ConnectServer(null, "root\\CIMV2");
    // クエリ実行、「SWbemObjectSet」オブジェクト取得
    var set = services.ExecQuery(wqlQuery);
    // 「SWbemObjectSet」をJScriptで扱えるように「Enumerator」に変換
    var enumSet = new Enumerator(set);
    // 「SWbemObjectSet」の最後までループ
    while (!enumSet.atEnd()) {
      // 要素「SWbemObject」を取得
      var item = enumSet.item();
      // プロパティ「SWbemPropertySet」取得
      var props = item.Properties_;
      // 「SWbemPropertySet」をJScriptで扱えるように「Enumerator」に変換
      var enumProps = new Enumerator(props);
      // アイテム変数
      var item = {};
      // プロパティ分ループ
      item["RecordNumber"] = "";    // Reserve item[0]
      item["Logfile"] = "";         // Reserve item[1]
      while (!enumProps.atEnd()) {
        var val = null;
        // プロパティ取得
        var prop = enumProps.item();
        //WScript.StdOut.WriteLine(prop);
        // nullチェック
        if (prop.Value != null) {
          // 配列判定
          if (prop.IsArray) {
            // 配列化
            val = new VBArray(prop.Value).toArray();
          } else {
            val = prop.Value;
          }
        }
        // アイテム設定
        item[prop.Name] = val;
        // 次のプロパティへ移動
        enumProps.moveNext();
      }
      // アイテム設定
      result.push(item);
      // 次の要素へ移動
      enumSet.moveNext();
    }
  } catch (e) {
      // エラーの場合
      throw e;
  }
  return result;
};


function wmiPropsPrintAscend(props) {
  var DLM_DT_WK = " ";
  var DLM_DT_DT = " - ";
  // 曜日(英語)
  var WEEK_DAY_EN = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
                  // "YYYY/MM/DD hh:mm:dd" + DLM_DT_WK + "www"
                  // "2016/01/02 03:04:05" + DLM_DT_WK + "Sat"
  var DATE_STR_SPC = "                   " + DLM_DT_WK + "   ";
  var dateStrSta = DATE_STR_SPC;
  var dateStrSto = DATE_STR_SPC;
  var dateStrCrr = DATE_STR_SPC;
  var dateTimeDst = new Date().getTimezoneOffset() * 60 * 1000;   // UTCと現地の時差。
  // キー配列
  var keys = null;
  var line1 = [];     // 1要素は1行
  // プロパティ配列数分ループ
  for (var i = props.length - 1; i >= 0; --i) {
    // 1プロパティを1イベントとして要素取得
    var items = props[i];
    // キー存在チェック
    if (keys == null) {
      // 初期化
      keys = [];
      // 要素のキー取得
      for (key in items) {
        keys.push(key);
      }
    }
    var line2 = [];   // 1要素は1イベント
    // 要素数分ループ
    for (var j = 0; j < keys.length; ++j) {
      // 要素取得
      var item = items[keys[j]];
      // 要素存在チェック
      if (item != null) {
        // 要素配列チェック
        if (item instanceof Array) {
          // 配列の場合、改行で連結
          item = item.join("\r\n");
        } else {
          // 文字列化
          item = "" + item;
        }
        // ダブルクォーテーションフラグ偽
        var isQuote = false;
        // 要素にダブルクォーテーションの存在チェック
        if (item.indexOf("\"") >= 0) {
          // ダブルクォーテーションを置き換え
          item = item.replace(/\"/g, "\"\"");
          // ダブルクォーテーションフラグ真
          isQuote = true;
        } else if (item.indexOf(",") >= 0
            || item.indexOf("\r") >= 0
            || item.indexOf("\n") >= 0) {
          // 要素に、「,」「CR」「LF」のいずれかがあるので
          // ダブルクォーテーションフラグ真
          isQuote = true;
        }
        // ダブルクォーテーションフラグ判定
        if (isQuote) {
          // 両端をダブルクォーテーションで囲む
          item = "\"" + item + "\"";
        }
      }
      // 要素設定
      line2.push(item);
    }
    // Windowsの1回分の開始日時と終了日時を1文字列として配列line1へ格納する。
    // Windowsをシャットダウンせずに電源断して再起動した場合、開始日時のイベントが連続することを考慮する。
    // WMIで取得したイベントの日時文字列を現地日時のDate型に変換する。
    var eventDate = new Date(
      Date.parse(WmiDate_parseWmiDateTimeString(line2[3])) - dateTimeDst
    );
    // イベントの現地日時のDate型を文字列に変換する。
    dateStrCrr = Date_formatLocal(eventDate) + DLM_DT_WK + WEEK_DAY_EN[eventDate.getDay()];
    // 1行分のデータを設定。
    if (6005 == line2[2]) {     // 開始日時
      if (dateStrSta != DATE_STR_SPC) {
        line1.push(dateStrSta + DLM_DT_DT + dateStrSto);
      }
      dateStrSta = dateStrCrr;
      dateStrSto = DATE_STR_SPC;
    }
    if (6006 == line2[2]) {     // 終了日時
      line1.push(dateStrSta + DLM_DT_DT + dateStrCrr);
      dateStrSta = DATE_STR_SPC;
      dateStrSto = DATE_STR_SPC;
    }
  }
  // 現在の稼働分は、開始日時ありで終了日時なしとして取得できているはず。
  if ((dateStrSta != DATE_STR_SPC) || (dateStrSto != DATE_STR_SPC)) {
    // 終了日時なしの場合、最終行の終了日時を現在の日時にする
    if ((true) && (dateStrSto == DATE_STR_SPC)) {
      dateStrSto = formatDate(new Date(), "YYYY/MM/DD hh:mm:ss www");
    }
    line1.push(dateStrSta + DLM_DT_DT + dateStrSto);
  }
  for (j = 0; j < line1.length; ++j) {
    WScript.StdOut.WriteLine(line1[j]);
  }
  return;
};


// ....................
// EventCheck.
// ....................
function EventCheck(args) {
  var DAYS = 40;      // 抽出日数(過去n日)
  if ((args != null) && (args.length >= 1)) {
    DAYS = args;
  }
  var dt = new Date();
  dt.setHours(0);
  dt.setMinutes(0);
  dt.setSeconds(0);
  dt.setDate(dt.getDate() - DAYS);
  // WMIでイベントログを抽出するWQL。
  // WMIは日時をUTCで扱う。ただし、日時の書式は独自で、時差の±は逆。
  // WQLはSQLに似ているがORDER BY句がない。
  // Windowsの開始日時と終了日時であれば、降順と言えると思われる。
  var wqlQuery = [
    "SELECT EventCode,TimeGenerated,TimeWritten",
    "  FROM Win32_NTLogEvent",
    "  WHERE (EventCode = 6005 OR EventCode = 6006)",
    "  AND Logfile = 'System'",
    "  AND TimeGenerated >= '" + WmiDate(dt) + "'",
  ].join(" ");
  var props = wmiProps(wqlQuery);
  // 並べ替えせずに末尾から先頭方向へ参照していく方式で
  // Windowsの開始日時と終了日時を昇順で出力。
  wmiPropsPrintAscend(props);
  return 0;
}


// ....................
// Other args.
// ....................
function OtherArgs(jsargs) {
//  WScript.Echo(" OtherArgs ....................");
//  WScript.Echo("JS [" + jsargs.length + "]" + jsargs + ".");
//  for(var idx = 0; idx < jsargs.length; ++idx) {
//    WScript.Echo("JS Args[" + idx + "]=" + jsargs[idx] + ".");
//  }
  WScript.Echo("Other args.");
  return 1;
}


// --------------------
// JScript main.
// --------------------
var rv = 0;
if (WScript.Arguments.length == 0) {
  rv = rv + NoArgs();
} else {
  var args = new Array();
  for (var idx = 0; idx < WScript.Arguments.length; ++idx) {
    args[idx] = WScript.Arguments(idx);
  }
  var ary = new Array();
  ary = args.slice(0, args.length);
  if (0 == 1) {
    rv = rv + 1;
  } else if ((args.length == 1) && (WScript.Arguments(0) == "JS_EventCheck")) {
    rv = rv + EventCheck();
  } else if ((args.length == 2) && (WScript.Arguments(0) == "JS_EventCheck")) {
    rv = rv + EventCheck(args[1]);
  } else {
    rv = rv + OtherArgs(ary);
  }
}
WScript.quit(rv);