TechNote

事務屋のおぼえがき

バッチで仮想ドライブ(.vhdx)をマウントしてinetcacheフォルダ削除

背景

大量のユーザプロファイルディスク(←これが仮想ディスク(.vhdx))があり、このユーザプロファイルごとにinetcacheフォルダ(IEのキャッシュがたまる場所)をもつような特殊な環境があるとする。今回、仮想ディスクをマウント⇒inetcacheフォルダの中身を削除、という操作をバッチ化する必要が生じたのでメモ。あまりバッチに詳しくない身としては多少の学びがあった。

削除部分

まずは簡単そうなところから。inetcacheフォルダの中身の削除に関する部分
inetcacheフォルダの中にはこのように、複数のフォルダと「container.dat」が存在。

f:id:kojikoji75:20201205151017p:plain
inetcache


今回container.datは残してフォルダのみ削除したいので、とりあえずのバッチ記述は下記でいける。...はず。

set target=e:\AppData\Local\Microsoft\Windows\INetCache\IE\*
set log=d:\test\log.txt

for /d %%1 in (%target%) do rd /s /q "%%1" >>%log%
if %errorlevel%==0 (
echo success >>%log%
) else (
echo failure >>%log%
)

ちなみにフォルダ削除コマンドrd(rmdir)のオプションは下記のとおり。

/s:サブフォルダも削除
/q:確認なし

しかしこれを実行してもinetcache内のフォルダは削除されなかった。


実は for /d in ではこの時点で見えているものしか対象にならないために、隠しフォルダは一覧にリストアップされてくれない。
このため、先にattribで一括で属性変更することが必須となる。

set target=e:\AppData\Local\Microsoft\Windows\INetCache\IE\*
set log=d:\test\log.txt

rem ---追加ここから---
rem 先に隠し属性を解除
cd /d e:
cd e:\AppData\Local\Microsoft\Windows\INetCache\IE\
attrib /d /s -r -s -h
rem ---追加ここまで---

for /d %%1 in (%target%) do rd /s /q "%%1" >>%log%
if %errorlevel%==0 (
echo success >>%log%
) else (
echo failure >>%log%
)

attribコマンドはファイルやフォルダの属性を管理するコマンド。
オプションは下記のとおり。

/d:フォルダも処理
/s:現在のフォルダと全てのサブフォルダの一致するファイルを処理
-r:読み取り専用属性を取り除く
-s:システムファイル属性を取り除く
-h:隠しファイル属性を取り除く

inetcache内のフォルダ群は、単なる「隠しファイル」属性だけではなく「システムファイル」属性でもあったため、上記のようにした。(「読み取り専用」はどうだったか忘れたがとりあえずいれといた)

また、わざわざ「cd」で該当ディレクトリまで移動しているのは、attribコマンドはそのようにしないと正常に動作しなかったため。(※正解かどうかはわからない)
こういうコマンドごとにもつ性質を見極めた(ような気になった)瞬間はうれしいもの。

これで削除部分は完了。

仮想ディスクのマウント部分

次に仮想ディスクのマウントについて。
仮想ディスクのマウントはdiskpartコマンドを使う。

具体的には、diskpartコマンドを記述したバッチと、またそれとは別にdiskpartのスクリプトファイルを用意する必要がある。

バッチ側

set log=d:\test\log.txt
set diskpartfile=d:\test\mountvdisk.txt

diskpart /s %diskpartfile% >>%log%

diskpartスクリプトファイル側(mountdisk.txt)

select vdisk file="D:\ProfileDisk\a.vhdx"
attach vdisk
exit
f:id:kojikoji75:20201205154634p:plain
diskpart実行結果

これで動作確認はOK。組み合わせると下記のような感じ。

@echo off

set diskpartfile=d:\test\mountvdisk.txt
set target=e:\AppData\Local\Microsoft\Windows\INetCache\IE\*
set log=d:\test\log.txt

rem 仮想ディスクをマウント
diskpart /s %diskpartfile% >>%log%


rem 開始ログ出力
echo %date% %time% 処理開始 >>%log%

rem 隠し属性等解除
cd /d e:
cd e:\AppData\Local\Microsoft\Windows\INetCache\IE\
attrib /d /s -r -s -h

rem フォルダのみ削除
for /d %%1 in (%target%) do rd /s /q "%%1" >>%log%
if %errorlevel%==0 (
echo success >>%log%
) else (
echo failure >>%log%
)

rem 終了ログ出力
echo %date% %time% 処理終了 >>%log%


ちなみに「バッチファイルとは別にスクリプトファイルを用意する必要がある」と書いたが、パイプで渡す方法もある。
こんな感じ。

(echo select vdisk file="%target%"
echo attach vdisk
)|diskpart

また、当初バッチファイル名を「diskpart.bat」などとしていたら、バッチを実行するとループ処理みたいになった。これは自分自身が呼び出されるという挙動となるために起こるもの。バッチファイル名にコマンド名をつけるのはNG。ときどきしか使わないのですぐ忘れる。