またもや「Excel VBAと関係ねぇじゃねーか!」と言われそうですが、今回はMS-DOSコマンドの標準出力を変数に取得する方法を解説します。これはもう、Excelとは関係ないVB系のネタなんですね。ただ実行環境がExcelってだけで(^^; ま、いーや書いちゃえ。MS-DOSって何のことだかわからない人は、自分で調べてください(^^; なお、ここではWindows XP Home Editionを例に解説します。
MS-DOSのコマンドには今でも便利に使えるものが多いですし、何よりネットワークを管理されている方は必須コマンドです。VBやVBAからMS-DOSコマンドを実行するときには、問題が2つあります。1つめはShell関数で起動できないことです。MS-DOSコマンドはいわゆるDOS窓で起動する仕組みになっていますので、Shell関数では起動できません。2つめの問題は、実行結果もDOS窓に出力されるということです。いわゆる標準出力ですね。この2つの問題をクリアできれば、MS-DOSコマンドを使ってかなりおもしろいことが可能です。
これら2つの問題は、WSH(Windows Scripting Host)で解決します。WSHのWshScriptExecオブジェクトが持つExecメソッドは、command.comやcmd.exeなどのコマンドシェルを実行できます。さらに実行結果の標準出力を取得することも可能です。さっそくやってみましょう。次のコードはC:\のファイル一覧を表示します。
Sub Sample1()
Dim WSH, wExec, sCmd As String, Result As String
Set WSH = CreateObject("WScript.Shell") ''(1)
sCmd = "dir C:\" ''(2)
Set wExec = WSH.Exec("%ComSpec% /c " & sCmd) ''(3)
Do While wExec.Status = 0 ''(4)
DoEvents
Loop
Result = wExec.StdOut.ReadAll ''(5)
MsgBox Result
Set wExec = Nothing
Set WSH = Nothing
End Sub

(1)でWSHへの参照を作ります。(2)が実行するMS-DOSコマンドです。引数まで指定してください。(3)でExecメソッドを実行しています。コマンドシェルは9x系と2000系で異なりますので%ComSpec%で自動判定させています。実行するとWshScriptExecオブジェクトを返しますので、変数に格納します。MS-DOSコマンドは完了まで時間がかかることがありますので(4)のようにループで完了を待ちます。完了したかどうかはWshScriptExecオブジェクトのStatusプロパティで判定します。MS-DOSコマンドの標準出力はStdOutプロパティで取得できますので、すべてを変数Resultに格納しました。最後にオブジェクト変数を解放しておしまいです。
この実行結果は、DOS窓でMS-DOSコマンドを実行したのと同じです。

上記のコードを実行するとわかりますが、一度DOS窓が表示されます。それを承知の上で使ってください。
さて、上記のコードではファイルの一覧を返すdirコマンドを使いましたが、dirコマンドには豊富なオプションが用意されています。すべてのオプションを知りたいときは、DOS窓で「dir /?」と打ってください。次のコードは、C:\にあるフォルダのうち、非表示ではないフォルダ名だけを、降順で取得して配列に格納します。配列への分割はSplit関数を使っています。Split関数に関しては「Split関数で文字列を区切る」をご覧ください。
Sub Sample2()
Dim WSH, wExec, sCmd As String, Result As String, tmp, i As Long
Set WSH = CreateObject("WScript.Shell")
sCmd = "dir C:\ /b /aD-H /o-N"
Set wExec = WSH.Exec("%ComSpec% /c " & sCmd)
Do While wExec.Status = 0
DoEvents
Loop
Result = wExec.StdOut.ReadAll
tmp = Split(Result, vbCrLf)
For i = 0 To UBound(tmp)
Cells(i + 1, 1) = tmp(i)
Next i
Set wExec = Nothing
Set WSH = Nothing
End Sub

これと同じことをFileSystemObjectなどでやるのは、けっこう手間ですよね。
あとは工夫しだいです。最後にいくつかサンプルを紹介しましょう。次のコードは、C:\tmpのフォルダ構造をツリー形式で取得します。C:\tmpにはあらかじめいくつかのサブフォルダを作ってあります。
Sub Sample3()
Dim WSH, wExec, sCmd As String, Result As String, tmp, buf As String, i As Long
Set WSH = CreateObject("WScript.Shell")
sCmd = "tree C:\tmp"
Set wExec = WSH.Exec("%ComSpec% /c " & sCmd)
Do While wExec.Status = 0
DoEvents
Loop
Result = wExec.StdOut.ReadAll
tmp = Split(Result, vbCrLf)
For i = 2 To UBound(tmp) ''3行目以降を変数に格納します
buf = buf & tmp(i) & vbCrLf
Next i
MsgBox buf
Set wExec = Nothing
Set WSH = Nothing
End Sub

次のコードは、DNSサーバーでwww.yahoo.co.jpのIPアドレスを調べます。
Sub Sample4()
Dim WSH, wExec, sCmd As String, Result As String, tmp, buf As String, i As Long
Set WSH = CreateObject("WScript.Shell")
sCmd = "nslookup www.yahoo.co.jp"
Set wExec = WSH.Exec("%ComSpec% /c " & sCmd)
Do While wExec.Status = 0
DoEvents
Loop
Result = wExec.StdOut.ReadAll
tmp = Split(Result, vbCrLf)
For i = 0 To UBound(tmp)
If Left(tmp(i), 5) = "Name:" Then
buf = tmp(i) & vbCrLf & tmp(i + 1)
End If
Next i
MsgBox buf
Set wExec = Nothing
Set WSH = Nothing
End Sub
