WSH(JScript)でリパースポイント(ジャンクション、シンボリックリンク)のターゲットパスを得る

前提

OS
Vista以降
C:\test内の構造

<DIR>          dir
           725 dir.lnk
             0 file
           466 file.lnk
<JUNCTION>     junction [c:\test\dir]
<SYMLINKD>     linkd [c:\test\dir]
<SYMLINKD>     linkdr [dir]
<SYMLINK>      linkf [c:\test\file]
<SYMLINK>      linkfr [file]

シンボリックリンクの参照先フルパスを取得

WSH(・∀・)スレッド! Part 4」にあるとおりにプログラムを書いてcscriptで実行してみたところ、以下のようになりました。
test.js

var fso = new ActiveXObject("Scripting.FileSystemObject");
var e = new Enumerator(
  (new ActiveXObject("Shell.Application"))
  .nameSpace("c:\\test")
  .items()
);
for (var f; !e.atEnd(); e.moveNext())
  if (fso[fso.fileExists((f = e.item()).path) ? "getFile" : "getFolder"](f.path).attributes & 1024)
    WScript.echo([f.name, f.extendedProperty("linktarget")].join(" : "));

cscriptでの実行結果

junction :
linkd : C:\test\dir
linkdr : C:\test\dir
linkf : C:\test\file
linkfr : C:\test\file

結果を見るとjunctionのターゲットパスがとれておらず、シンボリックリンク相対パス絶対パスとして取得してしまっています。
この方法はシンボリックリンクの参照先のフルパスが分かればよいという場合に使えます。なお、(ファイル|フォルダ)1つだけを調べるには以下のように書けます。

(new ActiveXObject("Shell.Application")).nameSpace("C:\\test").parseName("linkf").extendedProperty("linktarget") //C:\test\file

CMD.EXEのDIRコマンドを利用したリパースポイントの情報取得

junctionのターゲットパスとシンボリックリンクのターゲット相対パスを取得するために、CMD.EXEのDIRコマンドを利用することにします。
WshShell.execを利用した場合は以下のようになりました。
test3.js

WScript.echo(
  (new ActiveXObject("WScript.Shell"))
  .exec("cmd /c dir C:\\test")
  .stdout.readAll()
  .match(/\n\d{4}\/\d\d\/\d\d +\d\d:\d\d +<(?:JUNCTION|SYMLINKD?)> +junction \[(.+)\]\r/)[1]
)

cscriptでの実行結果

c:\test\dir

test3.jsの欠点はDIRを実行するたびにコマンドプロンプトのウィンドウが開くことです。
ウィンドウを隠すためにWshShell.runを使ったものが以下のtest4.jsになります。
test4.js

(new ActiveXObject("WScript.Shell")).run("cmd /c dir C:\\test > C:\\test\\tmp.txt", 0, true);
WScript.echo(
  (new ActiveXObject("Scripting.FileSystemObject")).openTextFile("C:\\test\\tmp.txt").readAll()
  .match(/\n\d{4}\/\d\d\/\d\d +\d\d:\d\d +<(?:JUNCTION|SYMLINKD?)> +linkdr \[(.+)\]\r/)[1]
);

cscriptでの実行結果

dir

test4.jsを使うといったんファイルに出力することになりますが、ウィンドウは開かなくなります。
この方法を使って簡単に取得するコードを書いたものが以下のtest5.jsになります。
test5.js

var WshShell = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");
var objShell = new ActiveXObject("Shell.Application");

var tmpFilePath = WScript.scriptFullName.replace(/[^\\]+$/, "tmp.txt");

function escapeRegExp(str) {
  return str.replace(/([\\\^\$\*\+\?\.\{\}\(\)\[\]\|])/g, "\\$1");
}

function map(collection, func) {
  for (var e = new Enumerator(collection), a = []; !e.atEnd(); e.moveNext())
    a.push(func(e.item()));
  return a;
}

function getReparsePoints(dir, file) {

  dir = dir.replace(/\\+$/, "");

  WshShell.run('cmd /u /c dir /a- "' + dir + '" > "' + tmpFilePath + '"', 0, true);

  var reg = new RegExp(
    "\\n\\d{4}\\/\\d\\d/\\d\\d +\\d\\d:\\d\\d +<(JUNCTION|SYMLINKD?)> +(" +
    (file ? escapeRegExp(file) : map(objShell.nameSpace(dir).items(), function (o) { return escapeRegExp(o.name);}).join("|")) +
    ") \\[(.+)\\]\\r", "ig");
  var reparsePoints = {};

  fso.openTextFile(tmpFilePath, 1, false, -1).readAll().replace(reg, function (s0, s1, s2, s3) {
    reparsePoints[s2] = { type : s1, path : dir + "\\" + s2, target : s3};
    return s0;
  });

  return reparsePoints;
}

var a = getReparsePoints("C:\\test");
for (var i in a)
  WScript.echo([a[i].path, a[i].type, a[i].target]);

cscriptでの実行結果

C:\test\junction, JUNCTION, c:\test\dir
C:\test\linkd, SYMLINKD, c:\test\dir
C:\test\linkdr, SYMLINKD, dir
C:\test\linkf, SYMLINK, c:\test\file
C:\test\linkfr, SYMLINK, file

この場合、tmp.txtはスクリプトファイルが置かれているフォルダに作られます。

20130811 追記

test5.jsのdirに/a-を追加