作業用PCのみで出勤確認が出来る仕組みを考えてみる

taskschd_msc

お友達から

従業員が出勤してるか確認する方法何かない?

との相談があったのでちょっと考えてみた。

要件定義

お友達の要望

出勤時間になっても誰も出勤していない場合、それが外から分かるようにして欲しい

平日は13:00、土日は9:30

あと、なるべく業務が増えるのは避けたい

なるほどなるほど。

ではでは日常業務の中で勝手に機能している感じにしてみよう。

システム要件

タスクスケジューラでログインチェックツールを起動し、時間になってもPCにログインされていない場合に複数の宛先へメール送信する

  • ログインチェック機能
  • メール送信機能

こんな感じかな。
業務でパソコン使うので出勤したら意識しなくてもPCにはログインするはず。いや、してくれ。

次はこれを実現するための条件を考えよう。

条件

PCが起動していないとチェック用のスクリプトが実行出来ない。
あと、メール送信はCDOを使いたい。

  • BIOSにOS自動起動の設定がある事
  • SSL/TLS認証のSMTPサーバが使える事
  • 各店舗に行ってBIOSとタスクスケジューラの設定が出来る人

はい、遠くまでは行きたくないです。

ので、設定方法だけ伝えて頑張ってもらいます。
あとはBIOSの機能もあるっぽいしメールはGmailがあるそうなので多分条件クリア。

CDOを使う事については個人的なわがままです。もう検証が終わっているので(笑)
しかし、CDOだとTLS/STARTTLS認証は使えないっぽいので、SSL/TLS認証の我らがGmail先生にメール届けてもらう事にするざます。

という事でスクリプト書いてみよー。

スクリプト作成

前に投稿したVBSでメール送るやつを使います。

VBScriptでメール送信(Gmail)

ちょっと長いけどいちお貼り付けておこう。

CheckGoToWork.vbs

Option Explicit

'*************************************************
'*         ↓↓ メール設定 ↓↓                  *
'*************************************************
Const sTo = "***@yahoo.co.jp,***@gmail.com"		'メール送信先(カンマ区切り)
Const sUser = "***@gmail.com"							'SMTPサーバログインユーザー名
Const sPass = "***"								'SMTPサーバログインパスワード
Const sSubject = "【出勤確認自動メール】***店"		'件名
Const sBody = "出勤確認が取れませんでした。"				'本文
'*************************************************
'*         ↑↑ メール設定 ↑↑                  *
'*************************************************

'=====変数宣言====================================
Dim oWsh,oFso,oPrm,oMsg
Dim sSfn,sDir,sChk,sUrl

'=====オブジェクト設定============================
Set oWsh = CreateObject("WScript.Shell")
Set oFso = CreateObject("Scripting.FileSystemObject")
Set oPrm = WScript.Arguments
Set oMsg = CreateObject("CDO.Message")

'=====変数設定====================================
sSfn = WScript.ScriptFullName
sDir = oFso.getParentFolderName(sSfn) & "\"
sChk = sDir & "chk.txt"
sUrl = "http://schemas.microsoft.com/cdo/configuration/"

'===引数により処理内容分岐========================
'引数が1つでm、d、cのどれかの場合のみ処理実行
If oPrm.Count = 1 Then

	Select Case oPrm(0)
		Case "m"
			Call MakeFile
		Case "d"
			Call DelFile
		Case "c"
			Call Check
		Case Else
			LogEventWarn
	End Select

	Else

	LogEventWarn

End If

'=====引数mの処理=================================
'作業フォルダに判定用ファイルを作成する(引数m)
Sub MakeFile()

	On Error Resume Next

	oFso.CreateTextFile(sChk)	'ファイル作成

	'イベントログに結果書き込み
	Call LogEvent(Err.Number,Err.Description)

	On Error Goto 0

End Sub

'=====引数dの処理====================================
'作業フォルダに判定用ファイルがあれば削除する(引数d)
Sub DelFile()

	On Error Resume Next

	If oFso.FileExists(sChk) Then oFso.DeleteFile(sChk)

	Call LogEvent(Err.Number,Err.Description)

	On Error Goto 0

End Sub

'=====引数cの処理====================================
'作業フォルダに判定用ファイルが無ければメールを送信する(引数c)
Sub Check()

	If Not oFso.FileExists(sChk) Then 

		oMsg.From = sUser
		oMsg.To = sTo
		oMsg.Subject = sSubject
		oMsg.TextBody = sBody
		oMsg.TextBodyPart.Charset = "ISO-2022-JP"

		With oMsg.Configuration.Fields
			.Item(sUrl & "sendusing") = 2
			.Item(sUrl & "smtpserver") = "smtp.gmail.com"
			.Item(sUrl & "smtpserverport") = 465
			.Item(sUrl & "smtpauthenticate") = 1
			.Item(sUrl & "smtpusessl") = true
			.Item(sUrl & "sendusername") = sUser
			.Item(sUrl & "sendpassword") = sPass
			.Update
		End With

	End If

	On Error Resume Next

	oMsg.Send

	Call LogEvent(Err.Number,Err.Description)

	On Error Goto 0

End Sub

'=====イベントログへ処理結果出力==================
Sub LogEventWarn()

		oWsh.LogEvent 2, "引数が正しく指定されなかった為、処理を中止しました。" & VbCrLf & _
			"m、d、cのいずれか1つを指定して下さい。" & VbCrLf & VbCrLf &_
			sSfn

End Sub

Sub LogEvent(iErrNo,sErrMsg)

	If iErrNo <> 0 Then
		oWsh.LogEvent 1, "予期しないエラーが発生しました。" & vbCrLf & vbCrLf & _
			sSfn & " " & oPrm(0) & vbCrLf & _
			"ID:" & iErrNo & vbCrLf & _
			"内容:" & sErrMsg
	Else
		oWsh.LogEvent 0, "正常終了しました。" & vbCrLf & _
			sSfn & " " & oPrm(0) 
	End If

End Sub

'=====終了処理==================
Set oWsh = Nothing
Set oFso = Nothing
Set oPrm = Nothing
Set oMsg = Nothing

WScript.Quit

ダウンロード

はい、完成。
引数によって処理が変わります。

  • 引数「m」 → チェック用ファイル作成
  • 引数「d」 → チェック用ファイル削除
  • 引数「c」 → チェック用ファイルがなければメール送信

コマンドプロンプトでこんな感じで実行します。

C:\>cscript C:\CheckGoToWork\CheckGoToWork.vbs m
ちなみにGmailのSMTPサーバへCDOで普通に接続すると、セキュリティ機能にブロックされるのでGmail側で設定変更が必要でした ⇒ メール送信エラーが出た時の対応

出勤確認の全体の流れとしてはこんなイメージ

  1. PC自動起動時に引数「d」で実行   → チェック用ファイル削除
  2. 従業員ログイン時に引数「m」で実行 → チェック用ファイル作成
  3. 出勤チェック時刻に引数「c」で実行  → チェック用ファイルが無ければメール送信

誰も出勤してこなくて、2番の処理が行われなければメール送信される仕組み。

ほんとはチェック処理に環境変数かレジストリ使おうと思ってたんだけど、なんか権限の関係でうまくいかんかったのでとりあえずファイルの有無で判定。

あと、いちおイベントログに実行ログが吐かれるようにしておいた。

◆正常終了◆

正常終了

◆警告◆

警告

◆エラー◆

エラー

ってか、今気づいたんだけどイベントビュアーって標準のプリントスクリーンだとキャプチャ取れないんだ!!
え、もしかして常識?

まあ、とりあえず置いといて次にタスクの登録です。

タスクスケジューラに登録

そしてタスクスケジューラもプリントスクリーン出来ないし!
マジですか

ではタスクスケジューラにタスクを3つ登録していくよー

  • チェック用ファイル作成
    タスク名:MakeFile
    引数:m
    トリガー:ログイン時に起動
  • チェック用ファイル削除
    タスク名:DelFile
    引数:d
    トリガー:パソコン起動時と毎日6:00に実行
  • チェック用ファイルがなければメール送信
    タスク名:Check
    引数:c
    トリガー:平日の13:00と土日の9:30に実行

Cドライブ直下に「CheckGoToWork」フォルダがあってその中に「CheckGoToWork.vbs」スクリプトがあるのを前提に説明します。

C:\CheckGoToWork\CheckGoToWork.vbs

「MakeFile」タスクの登録

タスクの作成をクリック
タスク スケジューラ-00

《名前》を入力し、【ユーザーまたはグループの変更】をクリック
タスクの作成-00

《使用するオブジェクト名を入力して下さい》に「system」と入力し【OK】をクリック
ユーザー または グループ の選択-00

《最上位の特権で実行する》にチェックを入れ、《構成》から任意の環境を選び、[トリガー]タブをクリック
タスクの作成-01

【新規】をクリック
タスクの作成-02

《タスクの開始》にて「ログオン時」を選択
《停止するまでの時間》にチェックを入れ「5」を入力し【OK】をクリック
新しいトリガー-00

ログオン時のトリガーが出来ました。
次は[操作]タブに行きます。
MekeFile のプロパティ-02

【新規】をクリック
タスクの作成-05

《操作》にてプログラムの開始を選択
《プログラム/スクリプト》に「C:\Windows\System32\cscript.exe」と入力
《引数の追加》に「C:\CheckGoToWork\CheckGoToWork.vbs m」と入力し【OK】をクリック
操作の編集-01

「操作」が作られました。
次は[条件]タブに進みます。
MekeFile のプロパティ-05

《コンピューターをAC電源で使用している場合のみタスクを開始する》のチェックを外す
《タスクを実行するためにスリープを解除する》にチェックを入れる
[設定]タブをクリック
MekeFile のプロパティ -00

《タスクを停止するまでの時間》にチェックを入れ「5」を入力
《タスクが既に実行中の場合に適用される規則》にて「既存のインスタンスの停止」を選択し【OK】をクリック
MekeFile のプロパティ -03

「MakeFile」タスクが登録されました。

タスク スケジューラ-00

同じようにして「DelFile」「Check」タスクを登録していきます。
[トリガー][操作]タブ以外は共通なので省略します。

「DelFile」タスクの登録

【新規】をクリック
タスクの作成-02

《タスクの開始》にて「スタートアップ時」を選択
《停止するまでの時間》にチェックを入れ「5」を入力し【OK】をクリック
新しいトリガー-00

あと、PCのシャットダウンを忘れて帰った時用に毎朝6時にも動くようにしておきます。
【新規】をクリック
DelFile のプロパティ-00

《タスクの開始》にて「スケジュールに従う」を選択
「毎日」を選択し「6:00」を入力
《停止するまでの時間》にチェックを入れ「5」を入力し【OK】をクリック

新しいトリガー-00

「システム起動時」と「毎日6:00」に実行されるようになりました。
次は[操作]タブに行きます。
DelFile のプロパティ -00

【新規】をクリック
タスクの作成-05

《操作》にてプログラムの開始を選択
《プログラム/スクリプト》に「C:\Windows\System32\cscript.exe」と入力
《引数の追加》に「C:\CheckGoToWork\CheckGoToWork.vbs d」と入力し【OK】をクリック
新しい操作-00

「操作」が作られました。
[全般][条件][設定]タブは「MakeFile」タスクと同じです。
MekeFile のプロパティ-05

「Check」タスクの登録

【新規】をクリック
タスクの作成-02

《タスクの開始》にて「スケジュールに従う」を選択
「毎週」「月~金」を選択し「13:00」を入力
《停止するまでの時間》にチェックを入れ「5」を入力し【OK】をクリック
新しいトリガー-00

もっかい【新規】をクリック
タスクの作成-03

《タスクの開始》にて「スケジュールに従う」を選択
「毎週」「土日」「09:30」を選択
《停止するまでの時間》にチェックを入れ「5」を入力し【OK】をクリック
新しいトリガー-02

平日用と土日用のトリガーが出来ました。
次は[操作]タブに行きます。
タスクの作成-00

《操作》にてプログラムの開始を選択
《プログラム/スクリプト》に「C:\Windows\System32\cscript.exe」と入力
《引数の追加》に「C:\CheckGoToWork\CheckGoToWork.vbs c」と入力し【OK】をクリック
新しい操作-00

「操作」が作られました。
[全般][条件][設定]タブは「MakeFile」タスクと同じです。
MekeFile のプロパティ-05

登録したタスクの確認

これでタスクスケジューラに3つとも登録されました。
タスク スケジューラ-00

しかし、同じような設定を何度も行う作業やってると、やっぱGUIってめんどいわー

と思ってコマンドからタスク操作する方法ないか調べたらいくつかあったし!

中でもPowerShellのScheduledTaskはかなり使えそうな感じだけど、なぜかトリガー設定用のNew-ScheduledTaskTriggerがこけるこける。
Windows PowerShell-00

原因調べてたら、コミュニティーで環境依存っぽいってなってたのでとりあえず今回は見送った。

Insider Previewでのpowershell – マイクロソフト コミュニティ

あと、ScheduledTask自体がPowerShell V3.0以前のバージョンは標準搭載じゃないらしいし、各店舗のPCがこのコマンド使える環境か分からんので深追いするのはやめておこう。

PowerShellって今まであんま触った事ないけど中々使い勝手は良さそうに感じるので、これからちょいちょいイジっていきます。

BIOSの自動起動設定

最後にBIOSの設定だけど、これはパソコンによって設定方法変わるよなー

うちのパソコンだと、[Power]-[Wake System From S5]にチェック入れて[Wakeup Hour]のトグルで「9」を選べば『毎日9:00に起動』するように設定出来ました

DSC_0019

大概は「電源」メニューの「WakeUpなんちゃら」とか「PowerOnなんちゃら」で設定出来ると思うので、毎日9時に起動するようにしておきましょう。

終わりに

本当は祝日も対応してないとだけどなー、めんどい(笑)
またなんかカレンダー的なプログラム書く事があったらその時にこっちも対応させよう。

って事で長々と書きましたが、まだ実際に導入はしていないのでこれでうまくいくかは分からんざますのことよ(笑)

いちお導入したらまた追記します。

そして、設定方法のキャプチャ取りながらブログ書くのってメチャ大変だなー
普段から分からん事あったらすぐ検索して知恵をお借りしまくっているので、今さらながら技術系Webサイトの作成者様に感謝です。

このブログもなんかの役に立ったらうれしいですな

追記 2016/06/09
導入したらやっぱり動かんかったー
うちの環境だと普通に動くけど店舗のPCだとなぜかうまくいかなくて《タスクが既に実行中の場合に適用される規則》を「既存のインスタンスの停止」から「新しいインスタンスを並列で実行」に変えたら動くようになった、理由は謎

あと、MakeFileだけトリガーの遅延時間を1分に設定しておいた。