URAMIRAIKAN

1020のなれの果て (since 2005.6.19)

PowerShellでスクリーンロックとログオフ

 Windows 10で「スクリーンロックしてから一定時間経過したらログオフさせたい」という要望がありまして、ちょっとしたスクリプトでやってみたメモ。

 基本的にはここにある内容を利用して、あとは目的に合わせて使いやすいように味付けした感じです。

 やっているうちに気がついたのですが、電源管理でディスプレイをオフにするようにしているとロック/アンロックの判定がうまくいかないことが多いようです。今回はそれに関してあまりは深追いせず、無効にする感じで。

 とりあえずWindows 10 (1809 - 1909) で動作確認。
 当然ですが、PowerShellはあらかじめ実行可能にしておく。

Param ( [Parameter(HelpMessage="Lock delay seconds")][alias("Lock","l")][Int]$LockSec = 0, [Parameter(HelpMessage="Shutdown delay seconds")][alias("Shutdown","s")][ValidateRange(30,86400)][Int]$LogoffSec = 60, [alias("Force","f")][Switch]$ForceFlag ) $ActionInt = 0 if ($ForceFlag) { $ActionInt = $ActionInt + 4 } $LockMethods = @' [return: MarshalAs(UnmanagedType.Bool)] [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern bool PostMessage(uint hWnd, uint Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", SetLastError = true)] public static extern bool LockWorkStation(); '@ $PwMgr = Add-Type -MemberDefinition $LockMethods -Name "PowerManager" -PassThru -Language CSharp Start-Sleep $LockSec $LockResult = $PwMgr::LockWorkStation() $ErrorActionPreference = "SilentlyContinue" $i = 10 Start-Sleep $i $LockProc = Get-Process LockApp while ($i -lt $LogoffSec) { $Proc = [System.Diagnostics.Process]::GetProcessById($LockProc.Id) $Threads = $Proc.Threads if ($Threads[0].WaitReason -eq "Suspended") { Exit } else { Start-Sleep 1 $i++ } } (Get-WmiObject -Class Win32_OperatingSystem -ComputerName .).Win32Shutdown($ActionInt) Exit

 ログアウト時間が経過する前にスクリーンロックを解除した場合には何もせずにスクリプトを終了します。そのために"LockApp"プロセスの状態をモニターしているのですが、微妙にタイムラグがあったりするので最低でも10秒間待ってからモニターするようにしました。
 他に、使用時に調整が効くようにロックとログアウトまで時間を引数で指定するようにしたくらいでしょうか。