2016年10月13日木曜日

PsExecでリモートPCのドライブ空き容量を確認する

PsExecというものを使うとリモートPC上でコマンドを実行することができます。
それを利用してリモートPCに接続されているドライブの空き容量を確認するスクリプトを作成しました。
共有設定しているフォルダが保管されているドライブの空き容量が知りたい時に利用します。




まずはPsExecをダウンロードして、ダウンロードしたファイルの中に含まれている「PsExec.exe」をHTAファイルと同じフォルダに保存します。



HTAファイルを起動すると以下の画面が表示されます。



PC名は自動検出ではなくプログラムファイル内に記載していますので、扱いたいPCの名前に適宜変更してください。



「ドライブリスト取得」ボタンを押すと、PsExecの処理が完了するまで少し待機した後



選択したPCに接続されているドライブのリストが読み込まれます。



「容量確認」ボタンを押すと、PsExecの処理が完了するまで少し待機した後



選択したドライブの容量に関する情報が表示されます。

※上図で「277002076160」となっている箇所はfsutilコマンドの出力内容をそのまま表示していますが、桁数が多すぎて分かりにくいので、右の列に適切な単位で表示するようにしています。


ソースは以下
<html>
<head>
<title>PsExec ドライブ容量の確認</title>
</head>
<body>
<table>
<tr>
<td>PC名</td>
<td>
<select id=selPC>
<option>PC名1
<option>PC名2
<option>PC名3
</select>
</td>
<td><button id=btnPC>ドライブリスト取得</button></td>
</tr>
<tr>
<td>ドライブ</td>
<td><select id=selDr></select></td>
<td><button id=btnDr>容量確認</button></td>
</tr>
</table>
<div id=div></div>
</body>
<script>
resizeTo(460,200)
selPC.onchange=function(){
var ops=selDr.options
while(ops[0]){ops[0]=null}
selDr.onchange()
}
selDr.onchange=function(){ div[iT] = '' }
btnPC.onclick=function(){
this.disabled = true
div[iT] = 'PsExec実行中。少々お待ちください。'
var txt = PsExec(selOps(selPC).text, 'net share').StdOut
var reg = /([A-Z])\$ +([A-Z])\:\\ /, _1, _2
var arr = []
while(txt.match(reg)){
_1 = RegExp.$1
_2 = RegExp.$2
txt = RegExp.rightContext
if(_1 != _2){continue}
arr.push(_1)
}
var ops=selDr.options
while(ops[0]){ops[0]=null}
for0L(arr, function(i,ドライブレター){ ops[i] = new Option(ドライブレター) })
div[iT] = ''
this.disabled = false
}
btnDr.onclick=function(){
var si=selDr.selectedIndex
if(si<0){return alert('先にドライブリストを取得してください')}
this.disabled = true
div[iT] = 'PsExec実行中。少々お待ちください。'
var obj=PsExec(selOps(selPC).text, 'fsutil volume diskfree '+selOps(selDr).text+':'), so=obj.StdOut
if(!so){
div[iT] = obj.StdErr
}else{
div[iH] = '<table border=1><tr><td></td><td></td><td></td></tr></table>'
var tbl=div[FI], tbo=tbl[FI], trModel=tbo[FI].removeNode(true)
var KMGT=function(数値){
return for0L(' KMGT'.split(''), function(i,単位){
if(数値<1000){ return Math.round(数値)+単位+'B' }
数値 /= 1000
})
}
for0L(so.split('\r\n'), function(i,line){
if(!line){return}
var arr=line.split(':'), tr=trModel.cloneNode(true)
tbo.insertBefore(tr)
tr[CN][0][iT] = arr[0]
tr[CN][1][iT] = arr[1]
tr[CN][2][iT] = KMGT(arr[1]-0)
})
}
this.disabled = false
}
PsExec=function(PC名,cmd){
// PsExec.exeはUNCパス上にある場合、shell.runから直接呼び出しても動作しない。
// batファイルを経由して呼び出せば動作するので、呼出し用batファイルを作る。
var pathBAT=gsf2+'/psexec実行用.bat', pathSO=pathBAT+'_StdOut.txt', pathSE=pathBAT+'_StdErr.txt'
Write(pathBAT, [fun(pathPsExec), '\\\\'+PC名, cmd, '>', fun(pathSO), '2>', fun(pathSE)].join(' '))
shell.Run(fun(pathBAT), 0, true)
var R=function(path){return fs.FileExists(path) ? Read(path) : ''}
var obj = {StdOut:R(pathSO), StdErr:R(pathSE)}
// 後始末。多重起動したりした場合は削除処理が重なってエラーになる可能性があるのでtry catchにしておく。
try{ fs.DeleteFile(pathBAT) }catch(e){}
try{ fs.DeleteFile(pathSO ) }catch(e){}
try{ fs.DeleteFile(pathSE ) }catch(e){}
return obj
}
onload=function(){
基準フォルダ = fs.GetParentFolderName(location.href.replace(/^file:/,'').replace(/^\/+([A-Z]:)/,'$1'))
pathPsExec = 基準フォルダ+'/PsExec.exe'
}
AXO = function(name){return new ActiveXObject(name)}
fs = AXO('Scripting.FileSystemObject')
shell = AXO('WScript.Shell')
gsf2 = fs.GetSpecialFolder(2)
Read = function(p){var o=fs.OpenTextFile(p), s=o.AtEndOfStream?'':o.ReadAll(); o.Close(); return s}
Write = function(path,v){with(fs.CreateTextFile(path)){Write(v);Close()}}
RAS = function(p){return Read(p).split('\r\n')}
for0L=function(arr,fun){for(var i=0,L=arr.length,res;i<L;i++){if(res=fun(i,arr[i])){return res}}}
forIn=function(obj,fun){var name,res; for(name in obj){if(res=fun(name, obj[name])){return res}}}
selOps=function(sel){var si=sel.selectedIndex; return si < 0 ? 0 : sel[OP][si]}
fun = function(path){return path.indexOf(' ')<0 ? path : ('"'+path+'"')}
iT='innerText', iH='innerHTML', OP='options', FI='firstChild', CN='childNodes'
</script>
</html>


PsExecはリモートPCと接続する時に時間がかかります。(認証の問題?)
今回のプログラムでは「ドライブリストの取得」と「容量確認」の2つの処理をPsExecに頼っていますが、機能を利用するたびに再接続しているので待ち時間がわりとあります。
PsExecそのものは一旦接続したら切断するまでは対話的にコマンドを実行させる機能を持っているのですが、標準入出力を利用してHTAから実行する場合は1回ごとに再接続するしか今のところ方法がありません。。


※PsExecを利用するには、リモート接続先PCに対して管理者権限が必要です。
PsExecを起動するPCにログインしているユーザーがリモート接続先PCに対して管理者権限を持っていれば「psexec.exe リモートPC名 実行させたいコマンド」で実行できます。
権限がない場合は「psexec.exe リモートPC名 -u ユーザID -p パスワード 実行させたいコマンド」とする必要があります。管理者権限があるユーザIDでもパスワードが無いアカウントはPsExecでは利用できません。

1 件のコメント:

  1. PsExecを使わなくてもdirコマンドでサクっと空き容量を調べられるらしいです。。
    http://www.atmarkit.co.jp/ait/articles/0408/14/news017.html

    返信削除