本日のサンプルではコマンドラインのリダイレクトを使ってwsfファイルの終了を検出するようにして、wsfファイルが終了したら後始末用の関数を実行するようにしました。
以下ソース
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<title>lock</title> | |
<body style="text-align:center;overflow:hidden;padding:0px;margin:0px;"> | |
<input id=inp style="width:100%;text-align:center"> | |
<button id=btnL>load</button> | |
<button id=btnI>init</button> | |
<table border=1 style="width:100%;"> | |
<tr><td width=1>A</td><td><input id=inpA style="width:100%"></td></tr> | |
<tr><td width=1>B</td><td><input id=inpB style="width:100%"></td></tr> | |
<tr><td width=1>C</td><td><input id=inpC style="width:100%"></td></tr> | |
</table> | |
<table id=tbl style="position:absolute;top:0px;left:0px;width:100%;height:100%;background-color:#ccc"><td style="text-align:center">初期化中。。少々お待ちください</td></table> | |
</body> | |
<script id=scriptCode共有用> | |
AXO=function(name){return new ActiveXObject(name)} | |
shell = AXO('WScript.Shell') | |
fso=function(){ | |
var fs=AXO('Scripting.FileSystemObject') | |
return { | |
AXO:fs, | |
gsf2:fs.GetSpecialFolder(2), // Z:\TEMP | |
Read:function(path, swCreate, swUnicode){ | |
if(!fs.FileExists(path)){return} | |
with(fs.OpenTextFile(path, 1, swCreate, swUnicode)){ var str=AtEndOfStream ? '' : ReadAll(); Close() } | |
return str | |
}, | |
Write:function(path,str,swUnicode,sw上書きしない){ with(fs.CreateTextFile(path, !sw上書きしない, swUnicode)){ Write(str); Close() } }, | |
Lock:function(path){ | |
var pathL=path+'.lock', ws, wsn=AXO('WScript.Network') | |
try{ | |
ws=fs.CreateTextFile(pathL) | |
ws.Write(wsn.computerName+'\r\n'+wsn.userName) | |
return {Close:function(){ ws.Close(); fs.DeleteFile(pathL) }} | |
} | |
catch(e){ | |
return this.Read(pathL) | |
} | |
} | |
} | |
}() | |
</script> | |
<script> | |
resizeTo(200,200) | |
inp.value = fso.gsf2+'\\lockTest.txt' | |
onbeforeunload=function(){ fso.AXO.FileExists(inp.value) && fso.AXO.DeleteFile(inp.value) } | |
obj = null | |
btnL.onclick=function(){ | |
var path=inp.value, o | |
if(!fso.AXO.FileExists(path)){return alert('ファイルがありません')} | |
try{ eval('o = '+fso.Read(path)) } | |
catch(e){ return alert('ファイルが破損しています') } | |
obj = o | |
inpA.value = o.A | |
inpB.value = o.B | |
inpC.value = o.C | |
} | |
btnI.onclick=function(){ | |
tbl.style.display = 'block' | |
wsf.negoWrite(inp.value, function(path){ fso.Write(path, "{A:'', B:'', C:''}") }, function(){ | |
tbl.style.display = 'none' | |
btnL.onclick() | |
}) | |
} | |
onload=function(){ | |
btnI.onclick() | |
} | |
inpA.onchange=inpB.onchange=inpC.onchange=function(){ | |
var m=arguments.callee, 処理待ち=m.処理待ち, chr=this.id.charAt(3), path=inp.value | |
m.処理待ち = (処理待ち || 0) + 1 | |
wsf.negoWrite(inp.value, (''+function(path){ | |
eval('o = '+fso.Read(path)) | |
o.prop = 'VVV' | |
fso.Write(path, "{A:'"+o.A.replace(/'/g,"\'")+"', B:'"+o.B.replace(/'/g,"\'")+"', C:'"+o.C.replace(/'/g,"\'")+"'}") | |
}).replace(/prop/,chr).replace(/VVV/,this.value.replace(/'/g,"\'")),function(){ | |
// この関数の代わりにbtnL.onclickを渡すとA,B,Cの複数項目を立て続けに編集した場合 | |
// 1項目ずつ編集をファイルに適用して、その時点のファイル内容が画面に反映されて、 | |
// 処理待ちの編集内容が見かけ上キャンセルされたようになってしまう。 | |
// 処理待ちの有無によって動作を切り替える。 | |
if(m.処理待ち==1){ return btnL.onclick() } | |
var o | |
eval('o = '+fso.Read(path)) | |
document.getElementById('inp'+chr).value = o[chr] | |
}) | |
} | |
wsf=function(){ | |
var pathWSF=fso.gsf2+'\\lock.wsf' | |
fso.Write(pathWSF, ['<-job>',scriptCode共有用.outerHTML,'<-script>','!'+function(){ | |
arg = WScript.Arguments | |
path = arg(0) | |
pathF = arg(1) | |
pathL = path+'.lock' | |
wsn = AXO('WScript.Network') | |
eval('f = '+fso.Read(pathF)) | |
while(true){ | |
try{ | |
lock = fso.AXO.CreateTextFile(pathL) | |
lock.Write(wsn.computerName+'\r\n'+wsn.userName) | |
break | |
} | |
catch(e){ WScript.Sleep(1000 * 10 * Math.random()) } // 待ち時間が一定だと永遠にお見合い状態になってしまうので、ばらけさせる。 | |
} | |
f(path) | |
// このスクリプトの動作を分かり易くするための待機時間。実際は不要。 | |
WScript.Sleep(5000) | |
lock.Close() | |
try{ | |
fso.AXO.DeleteFile(pathL) | |
fso.AXO.DeleteFile(pathF) | |
}catch(e){} | |
WScript.Echo('OK') | |
}+'()','<-/script>','<-/job>'].join('\r\n').replace(/<-/g,'<')) | |
var pathDQ=function(path){return 0<path.indexOf(' ') ? ('"'+path+'"') : path } | |
return { | |
negoWrite:function(path, fun, fun終了後){ | |
var pathF=fso.gsf2+'\\fun'+(new Date()).getTime()+'.js', pathO=pathF+'.txt' | |
fso.Write(pathF, fun) | |
shell.run('cmd /C cscript '+pathDQ(pathWSF)+' '+pathDQ(path)+' '+pathDQ(pathF)+' > '+pathDQ(pathO), 0) | |
var objIV=setInterval(function(){ | |
if(!fso.AXO.FileExists(pathO)){return} | |
try{fso.AXO.DeleteFile(pathO)}catch(e){return} | |
fun終了後 && fun終了後() | |
clearInterval(objIV) | |
},1000) | |
} | |
} | |
}() | |
</script> | |
</html> |
このサンプルを2つ起動して、片方は「A」に「1」と入力してonchangeイベントを発生させ、もう片方は「B」に「2」と入力してonchangeイベントを発生させると対象ファイルに対して二つのwsfがロック試行&書き込みを行います。
書き込み完了後、wsfはコマンドラインに対して標準出力で「OK」という文字列を返すと、それがリダイレクトによってテキストファイルに出力されて、それによってhtaがwsfの終了を検出し、後始末用の関数を実行します。
このサンプルが行う「後始末」は書き込み成功後のファイルを読み込んで、書き込み待ち項目数に応じて個別の項目値か全ての項目値をinputエリアに代入します。
0 件のコメント:
コメントを投稿