2017年3月6日月曜日

プログラム終了後にファイルを削除するHTA

処理に必要な一時ファイルをプログラム起動時などに作成し、終了時に削除したい場合があります。
onbeforeunloadイベントを使えばそのようなことができますが、同様に「プログラム終了時に実行したい処理」が複数ある場合は「window.attachEvent」で各処理を登録するのが安全策ですが、各処理の実行順が重要な場合はattachEventに任せるのも危険です。

hta内で実行順などを考慮するのが面倒なので、htaのプロセスIDをwsfで監視して、プロセスIDの終了を検知したら関連ファイルを削除させるサンプルを作成しました。

以下ソース
<html>
<title>終了後ファイル削除</title>
<body>
<input id=inp style="width:100%">
</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(300,100)
PID=function(){
// プロセス起動中にPIDが更新されることは無いので一度取得したら取得用関数は不要なのでPIDだけ保持する。
var f=function(){
// 子プロセスをcscriptにすると黒い画面が一瞬表示されてしまう。
// 「//B」オプションを付けないとwscriptの設定画面が表示されてしまう。
var childPID = shell.Exec('wscript //B').ProcessID
// 子の親(自身)のPIDを特定する
var res = new Enumerator(GetObject("winmgmts:root\\CIMV2").ExecQuery("SELECT * FROM Win32_Process where ProcessID="+childPID))
return res.atEnd() ? (void 0) : res.item().ParentProcessID
}
// 1度目で取得に成功すればその値を返し、ダメなら2回目の処理を実行する。
return f() || f()
}()
onload=function(){
var path=inp.value=fso.gsf2+'\\'+(new Date()).getTime()
fso.Write(path, '')
wsf.終了後ファイル削除(path)
}
wsf=function(){
var pathDQ=function(path){return 0<path.indexOf(' ') ? ('"'+path+'"') : path }
return {
newWSF:function(fun){
var path=fso.gsf2+'\\'+(new Date()).getTime()+'.wsf'
fso.Write(path, ['<-job>',scriptCode共有用.outerHTML,'<-script>','!'+fun+'()','<-/script>','<-/job>'].join('\r\n').replace(/<-/g,'<'))
return path
},
終了後ファイル削除:function(path){
var m=arguments.callee
if(!m.wsf){
m.wsf = this.newWSF(function(){
arg = WScript.Arguments
PID = arg(0)
path = arg(1)
while(true){
WScript.Sleep(1000)
var res = new Enumerator(GetObject("winmgmts:root\\CIMV2").ExecQuery("SELECT * FROM Win32_Process where ProcessID="+PID))
if(res.atEnd()){break}
}
arr = fso.Read(path).split('\r\n')
for(i=0,L=arr.length;i<L;i++){ fso.AXO.DeleteFile(arr[i]) }
})
fso.Write(m.path = m.wsf+'.list', [m.wsf, m.path].join('\r\n'))
shell.Run('cmd /C '+pathDQ(m.wsf)+' '+PID+' '+pathDQ(m.path), 0)
}
var arr=fso.Read(m.path).split('\r\n')
arr.push(path)
fso.Write(m.path, arr.join('\r\n'))
}
}
}()
</script>
</html>



プロセスを監視するwsfと削除するファイルのPathをリスト化したファイルももちろん削除してくれます。

0 件のコメント:

コメントを投稿