UWSCで休止状態からの復帰タイマーを設定する

UWSC公式掲示板で、二回ほど、状況に応じて次の復帰時間を決めたい、という欲求を見た。
二回目の方は、UWSC自身を別プロセスUWSCから操作するような決着だったけど、それってくどいよね。


ということで、復帰する関数を作ってみた。(モジュールにするほどではなかったので)



スクリプト

の前に、お断り。
このスクリプト、正しいつもりなんですけど、UWSCのLONGLONGがUNSIGNEDなのかコメントにもあるように、215秒以上で動作しません。
LONGLONGがSIGNEDになればこれで良いので、これはこれとして、現時点の対策を下に追記しました。


Resume.uws

OPTION EXPLICIT

IFB GET_UWSC_NAME = "Resume.uws" THEN
	DIM timer

	timer = SetResumeTimer(VAL(INPUT("何秒後に復帰?", "60")))
	IFB timer THEN
		POFF(P_SUSPEND)
		ClearResumeTimer(timer)
		MSGBOX("成功")
	ELSE
		MSGBOX("SetTimer失敗")
	ENDIF

ENDIF


// 指定時間はだいたいの目安(60秒単位くらいで考えて)
FUNCTION SetResumeTimer(sec, rep=0)
	// 復帰用タイマー設定
	DEF_DLL CreateWaitableTimerW(DWORD, BOOL, wstring): DWORD: kernel32
	DEF_DLL SetWaitableTimer(DWORD, var LONGLONG, LONG, pbyte, pbyte, BOOL): BOOL: kernel32

	RESULT = CreateWaitableTimerW(NULL, FALSE, NULL)
	IFB RESULT THEN
		DIM ltime = -10000000 * sec	//指定時刻までのタイマー時間を100ns単位で設定 正だとUTC時刻
		IFB !SetWaitableTimer(RESULT, ltime, rep, NULL, NULL, TRUE) THEN	// rep はミリ秒。0は単発
			ClearResumeTimer(RESULT)
			RESULT = 0
		ENDIF
	ENDIF
FEND

FUNCTION ClearResumeTimer(timer)
	DEF_DLL CancelWaitableTimer(DWORD): BOOL: kernel32
	DEF_DLL CloseHandle(DWORD): BOOL: kernel32
	RESULT = FALSE
	IF CancelWaitableTimer(timer) THEN RESULT = CloseHandle(timer)
FEND


SetResumeTimer関数で、タイマーのハンドルが戻ります。
タイマー処理が終わったら、ClearResumeTimerしてタイマーを解放してください。
基本はCALLでインクルードして使う想定。
このスクリプト単体で動かすと、指定時間後に復帰する動作確認がとれます。
あんまり精度は良くないです。
60秒未満の場合は休止・復帰コストが高いので、Sleepでもしてください。

LONGLONG対策スクリプト

Resume.uws

OPTION EXPLICIT

IFB GET_UWSC_NAME = "Resume.uws" THEN
	DIM timer

	timer = SetResumeTimer(VAL(INPUT("何秒後に復帰?", "60")))
	IFB timer THEN
		POFF(P_SUSPEND)
		ClearResumeTimer(timer)
		MSGBOX("成功")
	ELSE
		MSGBOX("SetTimer失敗")
	ENDIF

ENDIF


// 指定時間はだいたいの目安(60秒単位くらいで考えて)
FUNCTION SetResumeTimer(sec, rep=0)
	// 復帰用タイマー設定
	DEF_DLL CreateWaitableTimerW(DWORD, BOOL, wstring): DWORD: kernel32
	DEF_DLL SetWaitableTimer(DWORD, DWORD[], LONG, pbyte, pbyte, BOOL): BOOL: kernel32

	RESULT = CreateWaitableTimerW(NULL, FALSE, NULL)
	IFB RESULT THEN
		//指定時刻までのタイマー時間を100ns単位で設定 正だとUTC時刻
		DIM ltime[1]
		ltime[0] = VAL("$" + COPY(FORMAT(-10000000 * sec, 16, -1), 9, 8))
		ltime[1] = VAL("$" + COPY(FORMAT(-10000000 * sec, 16, -1), 1, 8))
		IFB !SetWaitableTimer(RESULT, ltime, rep, NULL, NULL, TRUE) THEN	// rep はミリ秒。0は単発
			ClearResumeTimer(RESULT)
			RESULT = 0
		ENDIF
	ENDIF
FEND

FUNCTION ClearResumeTimer(timer)
	DEF_DLL CancelWaitableTimer(DWORD): BOOL: kernel32
	DEF_DLL CloseHandle(DWORD): BOOL: kernel32
	RESULT = FALSE
	IF CancelWaitableTimer(timer) THEN RESULT = CloseHandle(timer)
FEND

とりあえず、300秒(約5分)で試しましたがOKでした。
これでいけるでしょう。(多分)
(不要でしょうが、UTC時刻での設定(正数での設定)は未対応ですが、対応するなら、FORMATに対してReplaceが必要です。)