certutilコマンドでのMD5の取得方法

VBAでMD5を取得する方法にはいくつかありますが、ここではWindows標準のcertutilコマンドを使う方法を紹介します。

certutilコマンドでファイルのMD5を取得するには以下のようなコマンドを実行します。

あとはVBAからこのコマンドを実行すればOKです。

VBAからコマンドプロンプトの実行を行う方法については「VBAでコマンドプロンプトの起動とコマンドの実行を行う」をご参照ください。

事前設定

以下のソースコードではコマンドプロンプトの実行にWshShellクラスを利用しています。

WshShellクラスを利用するために、VBA画面→ツールメニュー→参照設定で「Windows Script Host Object Model」を選択します。これでWshShellクラスを利用できるようになります。

WshShellクラスの変数宣言はIWshRuntimeLibraryライブラリに含まれるため、IWshRuntimeLibrary.WshShellと書いてもいいですし、IWshRuntimeLibraryを書かずにWshShellだけを書いてもいいです。以下のwsh1とwsh2のどちらの書き方もOKです。

ファイルのMD5を取得するソースコード

ここでは5つのファイルのMD5をcertutilコマンドで取得し、それをMD5.txtに出力しています。同じファイルを5回・・・という。。

よくハマる落とし穴コマンド文字列のドライブとディレクトリの指定漏れです。これが無いと動きません。バッチファイルを書く場合、そのバッチファイルの置き場はドライブとディレクトリがカレントディレクトリとなりますが、VBAでコマンドを実行する場合はバッチファイルと異なりカレントディレクトリが未決定の状態です。

そのため、事前にドライブとディレクトリを指定してカレントディレクトリを明示してあげないと、以降のコマンドでファイル名だけを指定したりしていると、どのディレクトリなのか分からず正しく動作しません。

コマンド結果をクリップボードに保存してそれを使うことも出来ますが、上のコードでは複数のコマンドを「 & 」で連結して一度に実行し、コマンド結果をファイルに出力しています。クリップボードを使わないのは理由があります。

例えば以下のようにclip指定をしてクリップボードに保存することも出来ます。

しかし、クリップボードへのコピーの処理は結構遅く、それよりもVBAの処理が速いため、クリップボードの内容が1度更新される間にVBAの処理が終わってしまった、なんてことが普通に起こります。また、クリップボードは他のアプリケーションなどでも共有で利用するため、VBAだけの処理で使っているとは限らないこともあります。このようにクリップボードを使う場合は信頼性が乏しいことからファイル出力での処理としています。

certutilコマンドの結果を「findstr -v “:”」として「:」がない行を対象としているのは、certutilコマンドを実行すると以下のように3行出力するため、不要な上下の行を除外するためです。

実行結果

MD5.txtに以下のように出力されます。同じファイルを5つに対してMD5を求めたため5行とも同じ内容になっています。なおWindows 7や8.1の場合は以下のように16進数値ごとに半角スペースで区切られますが、Windows 10の場合は半角スペースがなく16進数文字列が連続して表示されます。

35 e2 6f 21 8b 16 77 8a c7 bc 07 c2 da 43 8d e8
35 e2 6f 21 8b 16 77 8a c7 bc 07 c2 da 43 8d e8
35 e2 6f 21 8b 16 77 8a c7 bc 07 c2 da 43 8d e8
35 e2 6f 21 8b 16 77 8a c7 bc 07 c2 da 43 8d e8
35 e2 6f 21 8b 16 77 8a c7 bc 07 c2 da 43 8d e8

SHAを求めたい場合

MD5だけでなく他のハッシュ関数のハッシュ値を求めたい場合は、コード内のcertutil コマンドのMD5を「SHA1」や「SHA256」などに書き換えて実行すると、それぞれの結果が出力されます。