ヤマハのルータ NVR500をファイルサーバに その7 自動ロック回避

前回は、 遂にPASS BOX 2.5 を NVR500 に接続し、ファイルサーバとして稼動させることに成功しました。

ヤマハのルータ NVR500をファイルサーバに その6 動いた!

今回は、PASS BOX 2.5 の自動ロックを回避する方法について書きます。

HDD USB HDDケース

Seagate(シーゲート) BarraCuda ST2000LM015 バルク品 (2.5インチハードディスク(HDD)/2TB/SATA)

価格:10,374円
(2018/5/29 13:23時点)
感想(1件)

《送料無料》シンプルPASS BOX 2.5 セキュリティ機能搭載 USB3.0接続 SATA2.5インチHDD/SSDケース CENTURY/センチュリー/ハードディスクケース[CSPB25U3]

価格:2,480円
(2018/5/29 13:20時点)
感想(1件)

 

PASS BOX 2.5の自動ロック機能「オートセーフ機能」

PASS BOX 2.5 には、一定期間アクセスがないとロックされるような自動ロック機構が無いと言うWEBサイト等の説明でしたが、実際に製品を購入し添付資料に目を通すと、このような紙切れが入っていました。

下段のほうに「オートセーフ機能について」と題して、説明があり、10分間アクセスが無いと自動的にロックされるのです。説明には、「ロックされる」とは書いていません、「オートセーフ」と書かれていますが、結局はロックのことです。

この機能は、ファイルサーバとして使う場合は、逆に迷惑な機能です。ロック解除する手段は、物理的に PASS BOX 2.5 のキーボードからパスワードを入力するしかないわけで、ロックされる度にパスワードを入力する羽目になります。これでは、誰か一人ファイルサーバの横に張り付けなければなりません。

NVR500 に cron は無いのか

10分間アクセスがないとロックされるので、10以内に何かしらのアクセスがあればいいわけです。それを人間にやらせるのは、 無理な話なので、ここは賢い NVR500 に頼らなければなりません。UNIX や Linux ならすぐに cron でなんとかしようと頭に浮かびます。ところが NVR500 には cron はありません。似たような機能は無いか、コマンドリファレンスを調べてみると、それらしきものを「31.1 スケジュールの設定」のところで見つけました。 “schedule” と言うのコマンドです。詳しくは、コマンドリファレンスを見てもらうとして、簡単に説明するとこんな感じです。

schedule at id [date] time * command

at: “schedule at” で一つのコマンドと考えてください。省略不可。
id: スケジュール番号
date:月/日   省略時は */* とみなす
time:hh:mm[:ss] 時(0..23 または *) 分(0..59 または *) 秒(0..59)秒は省略可

これは使えそうです。mm のところを cron みたいにカンマ区切りで羅列できれば尚可ですね。だめでも、この “schedule at” を複数書いてやればなんとかなりますね。

ファイルサーバにアクセスするコマンドは無いのか

cron 相当の ”schedule at” は見つけたので、次は、ファイルサーバにアクセスするコマンドを探します。それらしきコマンドとして、見つけたのは、

external-memory batch filename batchfile [logfile]

と言うものでした。書かれている章/項のタイトルは「34.14 バッチファイルと実行結果ファイルの設定」と言うところです。”external-memory batch” で1つのコマンドと考えてください。引数は、2つで、”batchfile” と “[logfile]” です。”[logfile]” は、”[]” で囲われているので、省略可能です。

では、”batchfile” はどのようなバッチファイルなんでしょうか。マニュアルには正直言って何も書かれていません。DOS のバッチファイルなのか、NVR500 専用の文法のスクリプトなのか、何も説明がありません。前者の DOS ってことはまずないでしょうから、後者の方だとここは判断します。ただし、文法が特殊かもしれませんが、やりたいことにはループだの条件分岐は不要なので、ただ単に NVR500 のコマンドを実行して、その結果のログをファイルサーバに書き込んでくれればいいだけです。よって、敷居は低いと勝手に思い込んで話を進めます。

NVR500 用バッチファイルを作る

簡単そうな NVR500 のコマンドを探します。構築中に何度も使ったコマンドとして、”ping” がありました。これを使うことにします。時間をかけて他のコマンドを探す理由もありませんし。

バッチの中身はいたって簡単です。ファイル名は、”ping.bat” です。これを、ご自分のPC上でまずは作成してください。内容は、カスタマイズしてください。

# 拠点Aルータ疎通
ping -c 2 192.168.0.1

# 拠点Bルータ疎通
ping -c 2 192.168.2.1

2拠点とも共通のバッチとして使えるように、両拠点のルータにそれぞれ “ping” を打つようにしました。

これを、ファイルサーバの “¥local” の下にコピーします。これでバッチは完成です。

NVR500 用バッチファイルを登録

続いて、作成したバッチを登録します。”external-memory batch filename” を見つけた項のタイトルは「34.14 バッチファイルと実行結果ファイルの設定」でした。バッチを実行するとはどこにも書いてありません。この “external-memory batch filename” は登録(設定)するだけで実行はしてくれません。実行は後述しますが、また別のコマンドです。

登録するには、ssh 等で NVR500 に入って CLI で作業をするか、WEBの管理画面の [トップ] > [詳細設定と情報] > [コマンドの実行] で次のコマンドを入力します。

external-memory batch filename usb1:/local/ping.bat ping.log

ssh で登録した場合は、”save” コマンドもお忘れなく。

ちゃんと登録できたか確認するには、 管理画面の[トップ] > [詳細設定と情報] > [本製品の全設定(config)のレポート作成] で確認できます。

本当に登録できたか、疑い深い方は、一度 NVR500 の電源を OFF/ON してから[トップ] > [詳細設定と情報] > [本製品の全設定(config)のレポート作成] を確認してください。save を忘れると、OFF/ON で消えているはずです。

バッチファイルのパスは、”usb1:/local/ping.bat” となります。先頭で、外部メモリの位置 “usb1” を指定し、DOS/Windows のフォルダ区切りである “¥” は使わず、UNIX/Linux のディレクリ区切り “/” を使って記述します。

最後の “ping.log” は必ず指定してください。ここのバッチファイルの実行結果を格納します。ここはフルパスで書かなくて良いようです。作成される場所は、バッチファイルと同じフォルダです。つまり、”usb1:/local” の下に作成されます。

私が「必ず指定してください」と言ったのには理由があります。ファイルサーバへのアクセスと言う観点では、バッチファイル自体がファイルサーバに入っているので、実行する度にバッチファイルをリードすると思われるでしょうが、たぶんそれは間違いです。NVR500 には、外部メモリ用にキャッシュメモリを割り当てられるので、このバッチファイルは、運が良ければキャッシュに載って、HDD までアクセスがいかないことが想定されます。夜間などは、間違いなくキャッシュに載ります。

一方、ログファイルの方は、NVR500 のデフォルトのキャッシュ動作では、ライトスルーで動作し、書き込みが発生する度に HDD にアクセスします。よって、PASS BOX 2.5 の自動ロックタイマーの10分のカウントダウンが、ログファイルの書き込みでリセットされることになります。

バッチファイルの動作試験

バッチの登録までは終わりました。これだけではバッチは動かないことは、前述しました。実際に動作させて、ログファイルが出来るか確認します。先ほど同様にコマンドを実行します。

execute batch

これだけです。実行結果は画面には出てきません。ファイルサーバ上にログファイル “¥local¥ping.log” が作成されていれば成功です。

バッチのスケジューリング

出来上がったバッチを定期的に実行するようにスケジューリングします。「31.1 スケジュールの設定」のところで見つけました。 “schedule” を使うんでしたね。

schedule at id [date] time * command

at: “schedule at” で一つのコマンドと考えてください。省略不可。
id: スケジュール番号
date:月/日   省略時は */* とみなす
time:hh:mm[:ss] 時(0..23 または *) 分(0..59 または *) 秒(0..59)秒は省略可

id
NVR500 の中でユニークである必要があります。既に別のスケジューリングが登録されているかもしれません。 管理画面の[トップ] > [詳細設定と情報] > [本製品の全設定(config)のレポート作成]  を辿って、出てきた画面の中の、”# Schedule configuration” を探してください。そこに既存のスケジュールがあれば出てきます。そして使われている “id” も出てくるはずです。使われている番号の最大+1を今回使います。

date
毎月/毎日実行するので、ここは “*/*” を指定します。

time
毎時、10分未満の間隔で起動させます。秒は省略します。
cron ライクに記述するなら “*:0,6,12,18,24,30,36,42,48,54″ になります。8 とか、9 の倍数でも良いですが、最後が一定間隔にならないので、6 の倍数にしています。一定間隔にならないことを特に気にしないのであれば、”*:0,9,18,27,36,45,54″ でも大丈夫です。このカンマ羅列が通用するのかはマニュアルに書かれていません。試してダメなら、スケジュールを”id” を変えて複数登録するまでですが、とにかく試してみましょう。

time の後ろの “*” は何の意味か不明ですが、必須のようです。

”command” には、”ping.bat” を指定したくなりますが、それは不正解です。ここには、”execute batch” を指定します。

まとめると、登録するスケジュールコマンドは、次のようになります。

schedule at 2 */* *:0,6,12,18,24,30,36,42,48,54 * execute batch

登録は、ssh 等で NVR500 に入って CLI で作業をするか、WEBの管理画面の [トップ] > [詳細設定と情報] > [コマンドの実行] で次のコマンドを入力します。これも、既に説明したとおりです。save もお忘れなく。また、登録したら、必ず登録出来たか確認もしてください。

最終動作確認

すべての準備が整いました。あとは、最終的な動作確認です。動作確認は、先に出てきたようにファイルサーバ上のログファイルを見てみます。エクスプローラーで黙って見ていても、ログファイルは更新されないので、適当な時間間隔でマウスの右クリックでメニューを出して、「最新の情報に更新」を実行してください。そして、ログファイルの更新日時が、スケジュールとおりに変わっていたら成功です。

どうでしょうか。みなさんの環境ではうまく行きましたか?  私のところでは、分のカンマ羅列もちゃんと動いてくれました。

これで無事ファイルサーバとして本格運用に入れます。

次回は、2拠点間でファイルサーバの同期をさせる方法について書きます。お楽しみに。

 

HDD USB HDDケース

Seagate(シーゲート) BarraCuda ST2000LM015 バルク品 (2.5インチハードディスク(HDD)/2TB/SATA)

価格:10,374円
(2018/5/29 13:23時点)
感想(1件)

《送料無料》シンプルPASS BOX 2.5 セキュリティ機能搭載 USB3.0接続 SATA2.5インチHDD/SSDケース CENTURY/センチュリー/ハードディスクケース[CSPB25U3]

価格:2,480円
(2018/5/29 13:20時点)
感想(1件)

 


NTTフレッツ光

 

【送料無料】YAMAHA ブロードバンドVoIPルーター NVR500

価格:39,353円
(2018/5/29 13:40時点)
感想(5件)

バッチの中で他のプロセスが起動中か確認する

他のプロセスが起動中か確認が必要な場面

このプロセス/アプリが終わってからじゃないと処理ができないとか、このプロセス/アプリが起動中にバッチを実行すると何かを破壊してしまうとかありますよね。そんなときに、プロセス/アプリが起動中か確認する方法を紹介します。



対象となるプロセスを手動で見てみる

起動中かどうか確認したいコマンドやアプリを起動します。その状態でタスクマネージャを起動します。タスクマネージャは、Windows システムツールの中にあります。ここでは、例題としてメモ帳が起動しているかどうか確認してみましょう。

この例では2つのメモ帳が起動されていることが分かります。

でも、バッチの中で “メモ帳” は通用しません。この ”メモ帳” は通称であり、本名と言うのがあります。その本名を調べるには、メモ帳の行の上で、マウスの左ボタンをクリックし、プロパティを開きます。

プロパティ画面が出てきます。

この中の赤で囲った部分が本名です。ずいぶん通称と違います。

バッチの中で、プロセスが起動中か確認するには、この本名を元に探す方法を採ります。


200×200 高速大容量レンタルサーバ10G
mixhost

プロセスリストを取得してみる

現在起動しているプロセスのリストを取得するには、tasklist と言うコマンドを使います。

C:\>tasklist

イメージ名                     PID セッション名     セッション# メモリ使用量
========================= ======== ================ =========== ============
System Idle Process              0 Services                   0          8 K
System                           4 Services                   0     18,268 K
Registry                       120 Services                   0     19,408 K
smss.exe                       504 Services                   0      1,052 K
csrss.exe                      804 Services                   0      5,024 K
wininit.exe                    876 Services                   0      5,676 K

コマンドプロンプトを起動して、実行すると百行以上出てくると思います。上の例では先頭の数行のみ表示しています。でもこんなにたくさん出てきたら、メモ帳を探すのも苦労します。

メモ帳のプロセスを抜き出す

メモ帳のプロセスのみ抜き出すには、/FI オプションを使い、フィルターを掛けます。フィルターには色々と指定方法がありますが、プロセスのイメージ名を指定する方法でフィルターをかけます。イメージ名は、メモ帳であれば前段で取得した “notepad.exe” のことです。では実行してみましょう

C:\>tasklist /FI "IMAGENAME eq notepad.exe"

イメージ名                     PID セッション名     セッション# メモリ使用量
========================= ======== ================ =========== ============
notepad.exe                  12732 Console                    1     22,360 K
notepad.exe                  10920 Console                    1     20,276 K

狙ったとおり “notepad.exe” が2行出てきました。これで、プロセスを確認するテクニックは揃いました。あとはバッチとしてどう組み込むかです。

バッチの中でプロセスが起動中か判定する

バッチの中では対象のプロセスが起動されていたら、バッチを終了するとか、バッチを一時停止するとか色々と場面によって変わってくりかと思います。この例では、起動中であれば、メッセージを出して一時停止する処理にしています。

set PROCIMAGE=notepad.exe
set APLNAME=メモ帳
tasklist /FI "IMAGENAME eq %PROCIMAGE%" | find "%PROCIMAGE%" > NUL
if %errorlevel% == 0 (
    tasklist /FI "IMAGENAME eq %FILEWATCH%"
    echo.
    echo ■■■■■ %APLNAME% が起動されています ■■■■■
    echo 必要であれば %APLNAME% 停止してください
    echo 何かキーを押してください
    pause > nul
)

汎用的に使えるように、1行目と2行目でプロセスイメージ名(本名)とアプリケーション名(通称)を変数にセットしています。

3行目で、プロセスリストにフィルターをかけてプロセスイメージ名のみ抜き出しています。それをパイプで find に渡しています。

4行目では、3行目の最後のコマンド “find” の終了ステータスを判定しています。この例では、プロセスリストの中に “notepad.exe” があると “errorlevel” が 0 になります。

5~10 行目までは、それぞれの用途に合わせて書き換えてお使いください。

 

バッチの中で管理者権限を確認する

管理者権限が必要な場面

色々とシステムを構築していると、えー、このコマンド管理者権限必要なんだと言ったことに出くわします。私の場合は、リモートデスクトップの有効/無効を切り替えたくてバッチを作ったのですが、レジストリを触る “reg” コマンドが管理者権限が必要でした。他にもたくさんあるかと思います。



管理者権限があるか確認する方法

管理者権限があるかどうかは、管理者権限が必要なコマンドを実行して、そのエラーレベルを確認すると言う回りくどいやりかたで実現できます。↓↓↓ これがサンプルコードです。

openfiles > nul 2>&1
if not %errorlevel% equ 0 (
    echo このバッチは管理者権限で実行してください
    echo 終了します。何かキーを押してください。
    pause > nul
    exit 1
)


200×200 高速大容量レンタルサーバ10G
mixhost

1行目で管理者権限が必要な “openfiles” と言うコマンドを実行しています。実行結果は、nul デバイスに標準出力/標準エラー共にリダイレクトしているので、一切画面には出てきません。終了ステータスが、errorlevel 変数にセットされます。正常に終了した場合は、0。異常終了した場合は “0以外” がセットされます。ここが管理者権限の有無の肝です。

2行目は、openfiles の終了ステータスが 0 以外か確認しています。0 以外であれば 3行目 ~ 6行目が処理されます。

このコードをバッチファイルの先頭に入れておくと、管理者権限の有無が最初に確認され、管理者権限が無ければ echo でメッセージを出して、キー入力待ちにし、キー入力があれば終了ステータス “1” で終了します。

いかがでしょうか、簡単ではありますが、バッチの中で管理者権限を確認する方法でした。

 

 

 

 

バッチで今月末/前月末/翌月末などを取得する

どこでも使う日付取得を汎用バッチ化する

日付を取得して、その前月とか翌月とかが欲しいときありあすよね。会社で会計処理するようなときには、前月末締めで前月末って具体的に何月何日? なんてことです。



どこでも欲しくなるような機能ですよね。それなら、汎用バッチ化して、それを呼べばすっきりするし、共通化もできます。

汎用バッチと言っているのは、Windows や DOS にそのような「汎用バッチ」と言うものがあるのではないのですが、バッチから汎用バッチを呼んで、各変数に日付をセットしてもらおうというものです。この考え方は、日付以外の他の機能にもあてはまります。例えば曜日を月~日で欲しいなんて場合も汎用化しておけば、それを呼べばいいだけになります。

百聞は一見に如かず、まずは見てみましょう。

サンプルコード  dategettest.bat

@echo off


call dateget.bat

echo       年   月 0付月  日  0付日 末日
echo 前月 %Lyyyy%   %Lmm%    %LZmm%  %Ldd%     %LZdd%   %LddL%
echo 当月 %yyyy%   %mm%    %Zmm%  %dd%     %Zdd%   %ddL%
echo 翌月 %Nyyyy%   %Nmm%    %NZmm%  %Ndd%     %NZdd%   %NddL%

pause

4行目にかいてある “dateget.bat” と言うのが今回説明する汎用バッチです。このサンプルコードは、その汎用バッチを使う側のものです。汎用バッチを使う側は、”call dateget.bat” と1行書くだけで、次の値が得られます。

  • 現在の年、月、月が1桁の場合に0を先頭に付けたもの、日、日が1桁の場合に0を先頭に付けたもの、末日
  • 翌月の年、月、月が1桁の場合に0を先頭に付けたもの、日、日が1桁の場合に0を先頭に付けたもの、末日
  • 前月の年、月、月が1桁の場合に0を先頭に付けたもの、日、日が1桁の場合に0を先頭に付けたもの、末日

全部で 18個の値を取得できます。実際に実行してみましょう。

実行結果(実行日:2016/2/4)

      年   月 0付月  日  0付日 末日
前月 2016   1    01  4     04   31
当月 2016   2    02  4     04   29
翌月 2016   3    03  4     04   31

うるう年の処理も入っています。実行日が2016年2月4日で、その年はうるう年なので、2月は29日まであります。それで、当月の末日は29となっています。

実行結果(実行日:2018/1/21)

      年   月 0付月  日  0付日 末日
前月 2017   12    12  21     21   31
当月 2018   1    01  21     21   31
翌月 2018   2    02  21     21   28

年跨りの処理も入っています。実行日が2018年1月21日だと、その前月は、2018年12月になります。

実行結果(実行日:2018/5/31)

      年   月 0付月  日  0付日 末日
前月 2018   4    04  30     30   30
当月 2018   5    05  31     31   31
翌月 2018   6    06  30     30   30

前月同日、翌月同日が存在しない場合は、一番近い日:末日が設定されます。実行日が2018年5月31日の場合、前月4月と翌月6月はそれぞれ30日までしかないので、同日も末日も同じ30日が設定されます。


200×200 高速大容量レンタルサーバ10G
mixhost

汎用バッチ  dateget.bat

では、汎用バッチの方をみ見てみましょう。

@echo off
rem 現在の日付けを取得し、各種日付けを求め変数に入れる


rem 求める変数一覧
rem				年		0無月	0付月	0無日	0付日	末日
rem 前月	 Lyyyy		Lmm		LZmm	Ldd		LZdd	LddL
rem 当月	  yyyy		 mm		 Zmm	 dd		 Zdd	 ddL
rem 翌月	 Nyyyy		Nmm		NZmm	Ndd		NZdd	NddL

rem Z を含む変数で数値が1桁の場合、先頭に 0 が付く



rem ************* 現在の日付を取得 ****************************************
rem 日付をYYYY/MM/DD 形式で結果は環境変数 orgdate へ返す。
for /F "tokens=1" %%a in ('date /t') do set orgdate=%%a

rem ■ デバッグ用
rem set orgdate=2018/01/21



rem ***********************************************************************
rem ************* 当月の変数生成 ******************************************
rem ***********************************************************************
rem ***** 現在年月日(yyyy mm dd)を orgdate(YYYY/MM/DD) から求める
rem 年月日の分割
set yyyy=%orgdate:~0,4%
set mm=%orgdate:~5,2%
set dd=%orgdate:~8,2%


rem ***** 月日の数値化(8進数対策)
set /a mm=1%mm%-100
set /a dd=1%dd%-100


rem ***** うるう年判定
set UYYYY=%yyyy%

rem うるう年であれば2月に足す日数
set Udd=0

rem 年が4で割り切れるか
set /a U1=%UYYYY% %% 4

rem 年が100で割り切れるか
set /a U2=%UYYYY% %% 100

rem 年が400で割り切れるか
set /a U3=%UYYYY% %% 400

if %U1%==0 (
	rem 年が4で割り切れると一応うるう年である
	set Udd=1
	
	rem 4で割り切れても、100で割り切れて、400で割り切れないとうるう年ではない
	if %U2%==0 if not %U3%==0 (
		set Udd=0
	)
)


rem ***** 末日を求める
set ddL=
if %mm%==1  (set ddL=31)
if %mm%==2  (set ddL=28)
if %mm%==2  (set /a ddL=%ddL% + %Udd%)
if %mm%==3  (set ddL=31)
if %mm%==4  (set ddL=30)
if %mm%==5  (set ddL=31)
if %mm%==6  (set ddL=30)
if %mm%==7  (set ddL=31)
if %mm%==8  (set ddL=31)
if %mm%==9  (set ddL=30)
if %mm%==10 (set ddL=31)
if %mm%==11 (set ddL=30)
if %mm%==12 (set ddL=31)



rem ***** Z 付き変数の処理  一桁の月、日の先頭に0を付ける
set Zmm=0%mm%
set Zmm=%Zmm:~-2%
set Zdd=0%dd%
set Zdd=%Zdd:~-2%





rem ***********************************************************************
rem ************* 前月の変数生成 ******************************************
rem ***********************************************************************
rem 前月	 Lyyyy		Lmm		LZmm	Ldd		LZdd	LddL

rem ***** 前月の年月(Lyyyy Lmm)を求める
set Lyyyy=%yyyy%
set /a Lmm=%mm%-1

rem 年跨り処理    現在1月 → 前月は12月
if %Lmm% EQU 0 set Lmm=12&&set /a Lyyyy=%yyyy%-1


rem ***** うるう年判定
set UYYYY=%Lyyyy%

rem うるう年であれば2月に足す日数
set Udd=0

rem 年が4で割り切れるか
set /a U1=%UYYYY% %% 4

rem 年が100で割り切れるか
set /a U2=%UYYYY% %% 100

rem 年が400で割り切れるか
set /a U3=%UYYYY% %% 400
	

if %U1%==0 (
	rem 年が4で割り切れると一応うるう年である
	set Udd=1
	
	rem 4で割り切れても、100で割り切れて、400で割り切れないとうるう年ではない
	if %U2%==0 if not %U3%==0 (
		set Udd=0
	)
)


rem ***** 前月の末日(LddL)を求める
if %Lmm%==1  (set LddL=31)
if %Lmm%==2  (set LddL=28)
if %Lmm%==2  (set /a LddL=%LddL% + %Udd%)
if %Lmm%==3  (set LddL=31)
if %Lmm%==4  (set LddL=30)
if %Lmm%==5  (set LddL=31)
if %Lmm%==6  (set LddL=30)
if %Lmm%==7  (set LddL=31)
if %Lmm%==8  (set LddL=31)
if %Lmm%==9  (set LddL=30)
if %Lmm%==10 (set LddL=31)
if %Lmm%==11 (set LddL=30)
if %Lmm%==12 (set LddL=31)



rem ***** 前月の同日(Ldd)を求める
set Ldd=%dd%

rem 前月同日が、末日を超える場合は末日に修正
if %LddL% lss %Ldd% (set Ldd=%LddL%)


rem ***** Z 付き変数の処理  一桁の月、日の先頭に0を付ける
set LZmm=0%Lmm%
set LZmm=%LZmm:~-2%
set LZdd=0%Ldd%
set LZdd=%LZdd:~-2%





rem ***********************************************************************
rem ************* 翌月の変数生成 ******************************************
rem ***********************************************************************
rem 翌月	 Nyyyy		Nmm		NZmm	Ndd		NZdd	NddL

rem ***** 翌月の年月(Nyyyy Nmm)を求める
set Nyyyy=%yyyy%
set /a Nmm=%mm%+1

rem 年跨り処理    現在1月 → 翌月は12月
if %Nmm% EQU 13 set Nmm=1&&set /a Nyyyy=%yyyy%+1


rem ***** うるう年判定
set UYYYY=%Nyyyy%

rem うるう年であれば2月に足す日数
set Udd=0

rem 年が4で割り切れるか
set /a U1=%UYYYY% %% 4

rem 年が100で割り切れるか
set /a U2=%UYYYY% %% 100

rem 年が400で割り切れるか
set /a U3=%UYYYY% %% 400
	

if %U1%==0 (
	rem 年が4で割り切れると一応うるう年である
	set Udd=1
	
	rem 4で割り切れても、100で割り切れて、400で割り切れないとうるう年ではない
	if %U2%==0 if not %U3%==0 (
		set Udd=0
	)
)


rem ***** 翌月の末日(NddL)を求める
if %Nmm%==1  (set NddL=31)
if %Nmm%==2  (set NddL=28)
if %Nmm%==2  (set /a NddL=%NddL% + %Udd%)
if %Nmm%==3  (set NddL=31)
if %Nmm%==4  (set NddL=30)
if %Nmm%==5  (set NddL=31)
if %Nmm%==6  (set NddL=30)
if %Nmm%==7  (set NddL=31)
if %Nmm%==8  (set NddL=31)
if %Nmm%==9  (set NddL=30)
if %Nmm%==10 (set NddL=31)
if %Nmm%==11 (set NddL=30)
if %Nmm%==12 (set NddL=31)



rem ***** 翌月の同日(Ndd)を求める
set Ndd=%dd%

rem 翌月同日が、末日を超える場合は末日に修正
if %NddL% lss %Ndd% (set Ndd=%NddL%)


rem ***** Z 付き変数の処理  一桁の月、日の先頭に0を付ける
set NZmm=0%Nmm%
set NZmm=%NZmm:~-2%
set NZdd=0%Ndd%
set NZdd=%NZdd:~-2%





rem echo ■前月 %Lyyyy% %Lmm% %LZmm% %Ldd% %LZdd% %LddL%
rem echo ■当月 %yyyy% %mm% %Zmm% %dd% %Zdd% %ddL%
rem echo ■翌月 %Nyyyy% %Nmm% %NZmm% %Ndd% %NZdd% %NddL%


 

中身はよく読んでもらえばコメントも書いてあるので、理解していただけるかなと思いますが、汎用バッチなので、そのままコピってまずは使ってください。

使い方は、最初の dategettest.bat にあるように、18種類の変数に各値を入れてくれるので、それを参照するだけです。呼ぶ側で他の変数を使う場合は、この18種類の変数名と被らないようにコーディングしてください。

この汎用バッチの中身について勉強したくなるのは、翌日が欲しいとか、前日が欲しいとか言う場面が出てきたときではないかなと思います。そうときはこのソースをじっくり読んでいただいて改造するといいかもしれません。