[batch] Shell context menu から定型名フォルダを作成するバッチ

```
※記事に関しましてご注意下さい
間違い・勘違いが含まれている可能性もありますので予めご了承ください。
```
以下はバッチ開発の自主トレで作成した際のメモになります。

## お題
エクスプローラーの右クリックメニューから呼び出され、定型名フォルダを作成するバッチを作る
（例：西暦日時フォルダを作成）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705024/0665aaae-29c7-4236-10bd-c3937adab51e.png)

## 条件
- 外部ツール・コマンドは使用せずバッチ内ですべてを行なう
- 極力シンプルなコードにする
- レジストリへの登録・削除機能も同バッチ内に含める
- メニュー登録名はファイル名とする
- ※バッチにフォルダをドラッグ＆ドロップした動作に対応する
- ※バッチは外部からのコマンド呼び出し可能にする

## 作成したバッチ
### インストール・アンインストール
バッチをダブルクリックで実行します。
Shell context menu にまだ同名が無ければメニュー登録し、既に同名のメニューがあった場合はそのメニューを削除します

```
バッチファイル（日時フォルダ作成.cmd）のメッセージ例

・メニューに登録されたメッセージ
"Shell context menu [日時フォルダ作成]" added to registry.
・メニューから削除されたメッセージ
"Shell context menu [日時フォルダ作成]" removed from registry.
```

### 使い方
エクスプローラのフォルダ内で右クリックし、メニューからバッチ名を選択して実行します

例：日時フォルダ作成.cmd をバッチファイル名とした場合
メニューから `日時フォルダ作成` を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705024/0665aaae-29c7-4236-10bd-c3937adab51e.png)

また定型フォルダ名を数種類使用する場合、例えば
・日時フォルダ作成
・ユーザーフォルダ作成
を別のメニューにしたい場合には、バッチファイルを
・日時フォルダ作成.cmd
・ユーザーフォルダ作成.cmd
としてそれぞれ複製し、定型名箇所のみ変更して使用します。
※ 下のカスタマイズ例を参照下さい

### ソースコード
```Batch:日時フォルダ作成.cmd
@echo off
title %~n0
@rem ------------------
@rem author: https://qiita.com/rdj_masato
@rem ------------------

rem ------------------
rem settings
rem ------------------
rem [yes/no] open folder with explorer
set _EXP_OPEN=no

set _REL_PATH=%DATE:/=%

rem ------------------
rem main func
rem ------------------
if "%~1" == "" (
  call :_setup "%~0"
  timeout /t 5
  goto :eof
)
:_main
  if "%~1" == "" goto :eof

  set _BASE_PATH=%~1
  shift
  if not exist "%_BASE_PATH%" goto :_main

  set _ABS_PATH=%_BASE_PATH%\%_REL_PATH%
  if not exist "%_ABS_PATH%" mkdir "%_ABS_PATH%"

  if not "%_EXP_OPEN%"=="yes" goto :_main
  if exist "%_ABS_PATH%" start "" "%_ABS_PATH%"
goto :_main

rem ------------------
rem sub func
rem ------------------
:_setup
  set _REG_KEY=HKCU\Software\Classes\Directory\Background\shell\%~n1

  set _CMD_STR=call :_install "%~1"
  for /f "usebackq delims=" %%i in (`2^>nul reg query "%_REG_KEY%"`) do (
    set _CMD_STR=call :_uninstall "%~1"
  )
  %_CMD_STR%
goto :eof

:_install
  reg add "%_REG_KEY%\command" /t "REG_SZ" /d "\"%~1\" \"%%V\"" /f 1>nul && (
    echo "Shell context menu [%~n1]" added to registry.
  ) || (
    echo [Error] Failed to add "Shell context menu [%~n1]" to registry.
  )
goto :eof

:_uninstall
  reg delete "%_REG_KEY%" /f 1>nul && (
    echo "Shell context menu [%~n1]" removed from registry.
  ) || (
    echo [Error] Failed to remove "Shell context menu [%~n1]" from registry.
  )
goto :eof
```

## カスタマイズ例
基本的に現在のフォルダ以下に `%_REL_PATH%` を作成するため
ソースコード内の `set _REL_PATH=%DATE:/=%` 部分を変更してカスタマイズを行なう

### 基本的な記述
#### {日付}
例：20201011 (英語 OS の場合は要確認)

```
set _REL_PATH=%DATE:/=%
```
#### {ユーザー名}
例: userA

```
set _REL_PATH=%USERNAME%
```
#### {マシン名}
例: computerA

```
set _REL_PATH=%computername%
```
#### {日付} - {ユーザー名}
例：20201011-userA

```
set _REL_PATH=%DATE:/=% - %USERNAME%
```
### 複数階層の例
#### {ユーザー名} / {日付}
例：userA/20201011

```
set _REL_PATH=%USERNAME%\%DATE:/=%
```
#### {日付} / {ユーザー名}
例：20201011/userA

```
set _REL_PATH=%DATE:/=%\%USERNAME%
```
#### {日付} / {マシン名} / {ユーザー名}
例：20201011/computerA/userA

```
set _REL_PATH=%DATE:/=%\%computername%\%USERNAME%
```
### 若干アレンジする例
#### {日付}
例：20201011 (英語 OS の場合は要確認)

```
set _REL_PATH=%DATE:/=%
```
#### {日付6桁}
例：201011 (英語 OS の場合は要確認)

```
set _DATE=%DATE:/=%
set _REL_PATH=%_DATE:~-6%
```
#### {日付4桁}
例：1011 (英語 OS の場合は要確認)

```
set _DATE=%DATE:/=%
set _REL_PATH=%_DATE:~-4%
```


## TODO メモ
- メイン部分（フォルダ作成箇所）を分離した方がよかったかもしれない
- メインウィンドウで複数フォルダを選択した場合、別のレジストリキー登録が必要になる