スクリプトを使ってWindowsのロック・アンロック時に実行するタスクを登録する

Windows では、タスクスケジューラを使うと、Windowsのロック・アンロックをトリガとしたプログラム（タスク）の自動実行を行うことができます（下記関連記事参照）。

https://qiita.com/byuu/items/6dfe4e6fa477824f5b02

この記事では、このスケジューラへの登録を PowerShell スクリプトで実行する方法について記載します。

## 動作確認した環境

```
PS> (Get-WmiObject Win32_OperatingSystem).Caption
Microsoft Windows 10 Home
PS> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.18362.1171
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.18362.1171
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
```

```
> py --version
Python 3.9.0
```

## 手順

Windowsをロックした際に処理を実行したい場合は以下のスクリプトの `COMMAND` と `ARGUMENT` を実行したい処理に置き換えて、管理者権限がある PowerShell で実行してください。

```
$scheduler = new-object -com("Schedule.Service")
$scheduler.Connect()
$folder = $scheduler.GetFolder("\")
$definition = $scheduler.NewTask(0)
$triggers = $definition.Triggers
$trigger = $triggers.Create(11) # TASK_TRIGGER_SESSION_STATE_CHANGE
$trigger.StateChange = 7 # TASK_SESSION_LOCK 
$action = $definition.Actions.Create(0)
$action.Path = "COMMAND_NAME"
$action.Arguments = "ARGUMENT"
$folder.RegisterTaskDefinition("Lock Logging", $definition, 6, "", "" , 0)
```

補足情報：

* 引数が不要な場合は、`$action.Arguments = "ARGUMENT"` の行は削除してください。
* アンロックの場合は `$trigger.StateChange = 8`（8は `TASK_SESSION_UNLOCK`）にすることで登録できます。

## 参考文献

https://social.technet.microsoft.com/Forums/en-US/2263c5a7-41d4-4c64-96ee-46437aba1a85/schedule-task-with-trigger-quoton-workstation-lockquot?forum=winserverpowershell

https://docs.microsoft.com/en-us/windows/win32/taskschd/taskfolder-registertaskdefinition

https://docs.microsoft.com/windows/win32/taskschd/trigger-type

https://github.com/aikige/homeBinWin/tree/master/setup

## Pythonなどの他の言語で実施する場合

サンプルをよく読むとわかりますが、処理としては `Schedule.Service` のCOMオブジェクトを取得して設定しているだけですので、Windows の COM オブジェクトを操作することができる言語であれば大体どれを使っても良さそうです。

試しに Python で作ってみたところ、動きました。

```
import win32com.client
import os

def register_task(scheduler, state_change, task_name, command, arguments):
    folder = scheduler.GetFolder('\\')

    definition = scheduler.NewTask(0)

    TASK_TRIGGER_SESSION_STATE_CHANGE = 11
    trigger = definition.Triggers.Create(TASK_TRIGGER_SESSION_STATE_CHANGE)
    trigger.StateChange = state_change

    TASK_ACTION_EXEC = 0
    action = definition.Actions.Create(TASK_ACTION_EXEC)
    action.Path = script
    action.Arguments = arguments

    TASK_CREATE_OR_UPDATE = 6
    TASK_LOGON_NONE = 0
    NO_USER = ''
    NO_PASSWORD = ''
    folder.RegisterTaskDefinition(task_name, definition,
            TASK_CREATE_OR_UPDATE, NO_USER, NO_PASSWORD, TASK_LOGON_NONE)

script = 'COMMAND_NAME'
argument = 'ARGUMENT'
scheduler = win32com.client.Dispatch('Schedule.Service')
scheduler.Connect()
TASK_SESSION_LOCK = 7
TASK_SESSION_UNLOCK = 8
register_task(scheduler, TASK_SESSION_LOCK, 'Lock Logging', script, argument)
```

予想通りほとんど同じです。

---

## おまけ: PowerShell スクリプトが実行できない場合の対処方法

以下の記事を参照

https://qiita.com/Targityen/items/3d2e0b5b0b7b04963750