2014年11月27日


Cron の代替え : VBScript でタイマー処理

同一スクリプトで、別々の処理は一応可能のようですが、厳密には非同期では無く一つの処理を実行中は他の処理は待たされるようなので、本来の非同期処理が必要な場合は、外部アプリケーション(スクリプト)を呼び出す形にして下さい。

Windows には、昔から「スケジューラ」というサービスがあり、Cron と同じ事が可能です。しかし、Windows 純正で、URL を呼び出すとなると、それなりに知識も必要ですし、そもそもWindows のスケジューラは、非常に解りにくい不便なしろもので、できればあまり使用したく無いです。

そこで、VBScript のみを使って簡単なスケジューラを作り、そこからさらに VBScript で任意の URL を呼び出します。

10秒毎の非同期別スレッド処理のサンプル
' このセクションは、cscript.exe で処理を強制させるものです
str = WScript.FullName
str = Right( str, 11 )
str = Ucase( str )
if str <> "CSCRIPT.EXE" then
	str = WScript.ScriptFullName
	Set WshShell = CreateObject( "WScript.Shell" )
	Call WshShell.Run( "cmd.exe /c cscript.exe """ & str & """ & pause", 3 )
	WScript.Quit
end if

Dim Disp : Disp = True	' False にすると、秒単位の表示はしなくなります
Set WshShell = WScript.CreateObject("WScript.Shell")

Set SINK = WScript.CreateObject("WbemScripting.SWbemSink","SINK_")
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
objWMIService.ExecNotificationQueryAsync _
 SINK, _
 "SELECT * FROM  __InstanceModificationEvent " & _
 "WHERE TargetInstance ISA 'Win32_LocalTime'"

Wscript.Echo "非同期別スレッドタイマー処理を開始します"
str = WScript.FullName
str = Right( str, 11 )
str = Ucase( str )
if str = "CSCRIPT.EXE" then
	' Cscript.exe で、CTRL+C で終わらせる
	Do
		WScript.Sleep 10000
	Loop
end if

' この処理は、毎秒非同期のスレッドから呼び出されます
Sub SINK_OnObjectReady(objLatestEvent, objAsyncContext)

	' 10秒毎の非同期別スレッド処理
	if objLatestEvent.TargetInstance.Second MOD 10 = 0 then
		' ここが 10秒毎に呼び出されます
		WshShell.Run( "wscript httpget.vbs http://xxxxx.jp/xxxxx.php" )
	end if

	if Disp then
		' 秒単位に呼び出されるこのルーチンで毎回表示
		Wscript.Echo "Time: " & _
			objLatestEvent.TargetInstance.Hour & ":" & _
			objLatestEvent.TargetInstance.Minute & ":" & _
			objLatestEvent.TargetInstance.Second
	end if
End Sub



httpget.vbs
if Wscript.Arguments.Count = 0 then
	Wscript.Echo "httpget url [savepath]"
	Wscript.Quit
end if

' ダウンロード用のオブジェクト
Set objSrvHTTP = Wscript.CreateObject("Msxml2.ServerXMLHTTP")

' 第1引数は URL
strUrl = Wscript.Arguments(0)
if Wscript.Arguments.Count = 1 then
	' 第2引数が無い場合は、URL の最後の部分
	' ( カレントにダウンロード )
	aData = Split(strUrl,"/")
	strFile = aData(Ubound(aData))
else
	' 第2引数がある場合はそれをローカルファイルとする
	strFile = Wscript.Arguments(1)
end if

' ダウンロード要求
on error resume next
Call objSrvHTTP.Open("GET", strUrl, False )
if Err.Number <> 0 then
'	Wscript.Echo Err.Description
	Wscript.Quit
end if
objSrvHTTP.Send
if Err.Number <> 0 then
	' おそらくサーバーの指定が間違っている
'	Wscript.Echo Err.Description
	Wscript.Quit
end if
on error goto 0

if objSrvHTTP.status = 404 then
'	Wscript.Echo "URL が正しくありません(404)"
	Wscript.Quit
end if

' バイナリデータ保存用オブジェクト
Set Stream = Wscript.CreateObject("ADODB.Stream")
Stream.Open
Stream.Type = 1	' バイナリ
' 戻されたバイナリをファイルとしてストリームに書き込み
Stream.Write objSrvHTTP.responseBody
' ファイルとして保存
Stream.SaveToFile strFile, 2
Stream.Close



関連する記事

VBScript : 30秒後のイベント処理
VBScript : 10秒毎に処理を実行する( 時刻指定も可能 )
VBScript : スクリプトを終了しないようにする



【VBScriptの最新記事】
posted by at 2014-11-27 23:09 | VBScript | このブログの読者になる | 更新情報をチェックする