VBAでUTF8を直接吐くようなプロセスの標準出力をうまく使う方法(cmd /c を有効利用しましょう)

という意味のわからないタイトルですが、まあ、いろいろと困るのはこういうのです。

VBAとWScript.ShellオブジェクトとMSXMLSubversionを知らない人にはなんのこっちゃって感じですが:

Set shellObj = CreateObject("WScript.Shell")
Set msxml = CreateObject("MSXMLのProgId忘れた")
With shellObj.Run("svn history --limit 1 --xml svn://example.org")
   msxml.LoadXml .StdOut.ReadAll
   ~~ 適当な処理
End With

この処理は一見問題がないように見えますが、非ASCII文字(日本語とか日本語とか)が混入したときに問題が出てきます。(svn --xmlUTF-8XMLを吐きます)

.StdOutがShift_JIS前提で標準出力ストリームを読み込んでしまうせいで、非ASCIIコードポイントで文字化けがおこり、msxml.LoadXmlでロードする内容としては壊れた内容になってしまいます。

これは困った。

まともに直接.StdOutから読むのは無理そうなので、一度どこかのファイルに吐き出してから、それを直接MSXMLにパースしてもらいましょう。

Set shellObj= CreateObject("WScript.Shell")
Set msxml = CreateObject("忘れた")
shellObj.Exec "cmd /c svn history --limit 1 --xml svn://example.org > どこかのファイル"
msxml.Load どこかのファイル
~~ 適当な処理 + どこかのファイルを削除する処理

これでOK。標準出力にどんなバイナリを流されても平気です。重いけど。

ポイントは cmd/c 〜〜 > リダイレクト先 。ファイルに標準出力をリダイレクトさせるためにcmd /cを使ってます。

ほか、exeとしての実体がないdirの出力を出すときにもcmd /cは使えます。

まあ、もっと正攻法的なものがあるんだろうけど…