➊はじめに
在宅勤務などで調べごとをしているときなど、定期的にキーボードやマウス操作をしないと、Teamsアプリが退席中表示となってしまいイマイナイ
ことになってしまうことが多々あります。
➋ Teamsで退席中となるのはどんなとき?
Teamsで退席中となるのは概ね以下の場合です。ただし、この挙動はTeamsのバージョンや組織のポリシーによって異なる可能性があるとのことです。
- 手動でステータスを変更した場合
ユーザーが手動でステータスを「退席中」に変更することもできます。これは、ユーザーが一時的に利用できない状態であることを示すために使用されます。まぁこれは良いですね。
- キーボードやマウスの操作が一定時間ない(アイドル状態)
ユーザーが一定時間、キーボードやマウスを操作しない場合、自動的にステータスが「退席中」に変更されることがあります。これは、ユーザーがデスクにいないことを示すための機能です。
- デスクトップ画面がロックされた場合
特定の環境や組織において、デスクトップ画面がロックされると、Teamsのステータスが「退席中」に変更される場合があります。これは、ユーザーがデバイスから離れていることを示すための自動的な挙動です。
➌ Teamsで退席中防止方法
Teamsで退席中とならないための防止策としては、以下で対処できそうです。
- 1人で会議を開き参加する
-
マウスを動かしたりキーボードを操作して、アクティブな状態を維持する
などなど
➍ お悩み
とは言え、会議ばかりやっていると怪しまれるし、自動でマウスを動かしたりキーボードを操作するアプリはないものか?
皆さん、一度はこういうことを考え、一度は「Mouse Jiggler
」や「Auto Clicker
」など検索したことがあるでしょう...でも、会社貸与のPCだと、アプリのインストールやダウンロードもできないし、お金もかけたくないし...
︙
う~ん
︙
ならば、作ってしまえ!
ということで、イマイルヨの悩みをPowerShell、または、Windows Script Host で吹っ飛ばしたいと思います😉
➎ イマイルヨ (PowerShell)
PowerShellでプログラムを実行可能かどうかの確認をしてから、プログラムを作成しましょう。PowerShellでのプログラムが実行不可能だった場合は、「➏ Windows Script Host(for VBScript)」をお試しください。
(1) プログラムが実行可能か確認
まずは、PowerShellでプログラムを実行できるか、実行ポリシーについて確認しましょう。
👉️PowerShellを通常権限で開いて、「Get-ExecutionPolicy
」を実行してください。
> Get-ExecutionPolicy
Restricted
PowerShell の実行ポリシーは、以下のセキュリティ設定を管理するために使用されます。
実行ポリシー種別 | 説明 |
---|---|
Restricted(制限付き) | すべてのスクリプトが実行不可(デフォルト設定) |
RemoteSigned | ローカルスクリプトは制限なく実行でき、外部からダウンロードしたスクリプトには署名が必要 |
AllSigned | 信頼された発行元から署名されたスクリプトのみが実行可能 |
Unrestricted | すべてのスクリプトが実行可能ですが、外部からダウンロードしたスクリプトには警告が表示 |
「Get-ExecutionPolicy
」の結果が、「Restricted
」である場合は、作ったPowerShellのプログラムが動作しませんので、設定を変更します。
(2) プログラムを実行可能に設定する
PowerShell の実行ポリシーが、「Restricted
」となっていた場合は、以下のコマンドにて実行ポリシーの変更が必要となります。
👉️PowerShellを管理者として実行してアプリを開き、「Set-ExecutionPolicy RemoteSigned
」を実行してください。
こちらの設定変更を行う場合は、管理者権限が必要となります。
> Set-ExecutionPolicy RemoteSigned
(3) プログラムを作成
(1)、(2)でPowerShellの起動準備ができたら、ソースコードを打ち込みましょう(コピペ推奨です)。ファイルは、「イマイルヨ.ps1」として保存してください。
こちらは、10秒毎に「Windowsキー
」を押下したことにし、退席中を防止するイマイルヨのプログラムです。
❖ imairuyo.ps1
Add-Type -AssemblyName System.Windows.Forms
[Console]::Write("Running...")
while ($true) {
[System.Windows.Forms.SendKeys]::SendWait('^{ESC}')
Start-Sleep -Seconds 10
}
※イマイルヨは、PowerShell Ver5.1(Windowsにインストール済みのバージョンです)で動作確認済みです。PowerShellのバージョンは、「Get-Host」コマンドで確認できます。
(4) 起動方法を工夫してみる
「Set-ExecutionPolicy
」を実施できない場合でも…まだ諦めないで🤐
「ps1ファイル
」を起動するような「batファイル
」を作成するとPowerShell実行ポリシーが「Restricted(制限付き)
」でも、一時的に制限を「RemoteSigned
」へ昇格することで、実行できる場合があります。この方法も試してみてください。
❖ imairuyo.bat
powershell -ExecutionPolicy RemoteSigned -File imairuyo.ps1
👉️この場合の起動方法は、「imairuyo.bat
」をダブルクリックで問題ありません。
(5) PowerShell 実行結果
「imairuyo.ps1」ファイルを右クリックして、「PowerShellで実行」を選択してください。
通常「.ps1ファイル」をダブルクリックすると、PowerShellのエディタが開いてしまうことがありますので、必ず右クリからPowerShellを実行してくださいね。
PowerShellスクリプトが起動し、10秒ごとに「Windowsキー
」が押され、Windowsの「スタートメニュー
」がパタパタ動き始めます(ON⇔OFFを繰り返します)。
(6) PowerShell カスタマイズの仕方
(6-1) 繰り返し間隔変更
勘の良い方ならもう分かっていると思いますが、「Start-Sleep -Seconds 」の引数の '10' は10秒間隔という意味です。例えば60秒間隔で「スタートメニュー
」をパタパタさせたい場合は、以下のように値を '60' に修正してください。
Start-Sleep -Seconds 60
(6-2) 押下ボタン変更
「スタートメニュー
」のパタパタはウザくてイヤだよ。「シフトキー
」押下でイイよっていう場合は、以下のようにSendKeysの値を '+' に修正してください。
[System.Windows.Forms.SendKeys]::SendWait('+')
どのキーにするかは、👉こちらの資料を参照してください。
(6-3) イマイルヨ改
上記2つを修正したものがこちらになります。
こちらは、60秒毎に「シフトキー
」を押下したことにし、退席中を防止するイマイルヨのプログラムです。
❖ imairuyo_ShiftPush.ps1
Add-Type -AssemblyName System.Windows.Forms
[Console]::Write("Running...")
while ($true) {
[System.Windows.Forms.SendKeys]::SendWait('+')
Start-Sleep -Seconds 60
}
(6-4) 時刻表示を行うカスタマイズ例
「PowerShellが起動しているからイマイルヨが起動しているんだろうけど、プログラムが正常に動作しているのか分かるようにしてくんない?」っちゅー熱いご要望にもお答えして、以下のようにカスタマイズしてみました。1秒毎に日時が更新されるので、プログラムが正常に動作していることが分かります。
こちらは、1秒毎に「シフトキー」を押下したことにし、退席中を防止するイマイルヨのプログラムです。日時が更新されるので、動作していることが分かりやすいです。
❖ imairuyo_time.ps1
Add-Type -AssemblyName System.Windows.Forms
$prefix = "Running... :"
$textLength = [System.Text.Encoding]::UTF8.GetByteCount($prefix)
[Console]::Clear()
[Console]::ForegroundColor = [ConsoleColor]::Yellow
[Console]::Write($prefix)
while ($true) {
[System.Windows.Forms.SendKeys]::SendWait('+')
$datetime = Get-Date -Format "yyyy/MM/dd HH:mm:ss"
[Console]::ForegroundColor = [ConsoleColor]::White
[Console]::Write($datetime)
Start-Sleep -Seconds 1
[System.Console]::SetCursorPosition($textLength, 0)
}
➏ イマイルヨ(Windows Script Host)
Windows Script Hostでも同様のことができるので、こちらもプログラムを記載しておきます。PowerShellでうまくいかない人は、こちらをお試しください😊
(1) イマイルヨのプログラムを考える
イマイルヨのプログラムを超カンタンに考えてみます。
まず、ウインドウキーを程よく連打し続けるプログラムを考えました。
❖ imairuyo_simple_start.vbs
Set objShell = CreateObject("WScript.Shell")
Do
objShell.SendKeys "^{ESC}"
WScript.Sleep 10000 ' 10 seconds
Loop
次に、WSHは「WScript.exe」で動作するので、このプロセスを終了させるプログラムを考えました。
❖ imairuyo_simple_stop.vbs
' wscript.exe プロセスを終了する
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colProcesses = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'wscript.exe'")
For Each objProcess in colProcesses
objProcess.Terminate
Next
大体これでも問題ありませんが、他のツールなどで「WScript.exe」を利用している場合(競合)を考え、起動したプロセスのみを正しく終了させること、また、本ツールは1個起動すれば十分なので、重複起動させない機能を盛り込みたいと思います。
(2) イマイルヨのプログラム
❖ imairuyo_start.vbs
imairuyo_simple_start.vbs に機能追加したものが以下 imairuyo_start.vbs です。
ロックファイル(imairuyo_lock.lck
)を用いることで重複起動させない機能を追加し、起動した imairuyo_start.vbs のプロセスのみ、imairuyo_stop.vbs で停止させるように「imairuyo_start.vbsのプロセスID」をログファイル(imairuyo_start.log
)に保存するように機能追加したものになります。
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set objShell = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
' ログファイルのパス
Dim logFilePath
logFilePath = fso.GetSpecialFolder(2) & "\imairuyo_start.log"
' ロックファイルのパス
Dim lockFilePath
lockFilePath = fso.GetSpecialFolder(2) & "\imairuyo_lock.lck"
' ロックファイルが存在する場合、すでに実行中とみなして終了
If fso.FileExists(lockFilePath) Then
MsgBox "Another instance is already running.", vbExclamation, "Error"
WScript.Quit
End If
' ロックファイルを作成して、他のインスタンスからの起動を防止
Set lockFile = fso.CreateTextFile(lockFilePath, True)
lockFile.Close
' 自身のプロセスIDを取得
Dim processID
processID = GetCurrentProcessID()
' 起動時にPIDをメッセージボックスに表示
MsgBox "imairuyo_start: PID = " & processID, vbInformation, "Process ID"
' ログファイルにプロセスIDを記録
Dim logFile
Set logFile = fso.CreateTextFile(logFilePath, True)
logFile.WriteLine "imairuyo_start: PID = " & processID
logFile.Close
' メインループ
Do
objShell.SendKeys "^{ESC}"
WScript.Sleep 10000 ' 10秒
Loop
' 現在のプロセスIDを取得する関数
Function GetCurrentProcessID()
Dim colProcesses, objProcess
Set colProcesses = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'wscript.exe'")
For Each objProcess In colProcesses
' 自身のスクリプト名で絞り込む
If InStr(LCase(objProcess.CommandLine), LCase(WScript.ScriptFullName)) > 0 Then
GetCurrentProcessID = objProcess.ProcessId
Exit Function
End If
Next
End Function
❖ imairuyo_stop.vbs
imairuyo_simple_stop.vbs に機能追加したものが以下 imairuyo_stop.vbs です。
ログファイル(imairuyo_start.log
)から「起動した imairuyo_start.vbs のプロセスID情報」を取得し、imairuyo_stop.vbs で対象プロセスIDのみ停止するようにしています。また、最後にロックファイル(imairuyo_lock.lck
)を削除しています。
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set fso = CreateObject("Scripting.FileSystemObject")
Dim logFilePath, lockFilePath, targetProcessID
' ログファイルとロックファイルのパス
logFilePath = fso.GetSpecialFolder(2) & "\imairuyo_start.log"
lockFilePath = fso.GetSpecialFolder(2) & "\imairuyo_lock.lck"
' ログファイルからPIDを取得
If fso.FileExists(logFilePath) Then
Dim logFile, line, tempPID
Set logFile = fso.OpenTextFile(logFilePath, 1)
line = Trim(logFile.ReadLine) ' 余分な空白・改行を削除
logFile.Close
' PIDを抽出
If InStr(line, "PID = ") > 0 Then
tempPID = Trim(Split(line, "PID = ")(1)) ' PID部分を取り出す
If IsNumeric(tempPID) Then
targetProcessID = CLng(tempPID) ' 数値に変換
MsgBox "Extracted PID: " & targetProcessID, vbInformation, "PID Retrieved"
Else
MsgBox "PID is not numeric: " & tempPID, vbCritical, "Error"
WScript.Quit
End If
Else
MsgBox "Log file format invalid.", vbCritical, "Error"
WScript.Quit
End If
Else
MsgBox "Log file not found.", vbCritical, "Error"
WScript.Quit
End If
' WMIを使って該当プロセスを終了
On Error Resume Next
Dim colProcesses, objProcess
Set colProcesses = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE ProcessId = " & targetProcessID)
Dim processFound
processFound = False
For Each objProcess In colProcesses
objProcess.Terminate
processFound = True
MsgBox "Terminated process with PID: " & targetProcessID, vbInformation, "Success"
Next
If Not processFound Then
MsgBox "Process with PID " & targetProcessID & " not found.", vbExclamation, "Not Found"
End If
On Error GoTo 0
' プロセス終了待機
WScript.Sleep 2000 ' 2秒待機して完全終了を確認
' ロックファイルを削除
If fso.FileExists(lockFilePath) Then
fso.DeleteFile(lockFilePath)
MsgBox "Lock file deleted.", vbInformation, "Clean Up"
End If
(2) イマイルヨの開始のさせ方
「imairuyo_start.vbsファイル
」を右クリックしてメニューを出し、「プログラムから開く
」➔「Microsoft Windows Based Script Host
」を選択してください。
これでイマイルヨが、起動できます。ウィンドウなどはできませんが、プログラムは常駐し動作します。
- 本プログラムは、メニューが10秒毎にパタパタとON⇔OFFを繰り返すようになります(10秒ごとにWindowsキーを押下している状態)
(3) イマイルヨの終了のさせ方
「imairuyo_stop.vbsファイル
」を右クリックしてメニューを出し、「プログラムから開く
」➔「Microsoft Windows Based Script Host
」を選択してください。
(4) イマイルヨの手動終了方法
基本的にイマイルヨの終了は、「imairuyo_stop.vbs
」で問題ありません。
何か問題があった場合に備えて、手動終了手順を記載しておきます。
❖ 「プロセスID」の確認方法
コマンドプロンプトから以下のコマンドを実行してください。
> cd %TEMP%
> type imairuyo_start.log
imairuyo_start: 34408
上記実行例の場合、「34408
」が、起動したイマイルヨの「プロセスID」となります。
❖ タスクマネージャーからの終了方法
イマイルヨのプロセスIDを確認後、「タスクバー右クリック
」➔「タスクマネージャー
」を起動し、タスクマネージャーの「詳細
」を押下し、検索バーに「script
」等を入力してください。
先ほど探したプロセスID(imairuyo_start: 34408
)と同じプロセスIDがあるので、これがイマイルヨのプロセスになりますので、これを右クリックし「タスクの終了
」を選択し、プロセスを終了させます。
❖ ロックファイル手動削除方法
コマンドプロンプトからのロックファイルの確認方法、及び、手動削除は方法は、以下の通りです。
> cd %TEMP%
> dir imairuyo_lock.lck
> DEL imairuyo_lock.lck
※「
%TEMP%
」とは、「C:\Users\Username\AppData\Local\Temp
」のことです。
※ PowerShellの場合、該当ディレクトリへの移動は「cd $env:TEMP
」としてください。
タスクマネージャーから「タスクの終了
」を選択した場合は、ロックファイル(imairuyo_lock.lck
)が残るため、「imairuyo_start.vbs
」の新規起動ができなくなってしまいます。そのため、必ずロックファイルの削除をお願いいたします。ロックファイルは手動で削除する他、「imairuyo_stop.vbs
」または「imairuyo_recover.vbs
」を実行しても、ロックファイルの削除が可能です。
(5) トラブルシューティング
何か問題が発生したときは、「imairuyo_recover.vbs
」を実行してください。実行の仕方は、アイコンを右クリックして「PowerShell で実行
」を選択し起動してください。
実行すると以下3つの処理を実行します。
- WScript.exe プロセスをすべて終了(「
imairuyo_recover.vbs
」自身のプロセスは除外) - ロックファイル(
imairuyo_lock.lck
)を削除 - 「
imairuyo_recover.vbs
」自身のプロセスを終了
❖ imairuyo_recover.vbs
' wscript.exe プロセスを終了する
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set fso = CreateObject("Scripting.FileSystemObject")
' ロックファイルのパス
Dim lockFilePath
lockFilePath = fso.GetSpecialFolder(2) & "\imairuyo_lock.lck"
' WScript.exe プロセスをすべて終了(自身のプロセスは除外)
MsgBox "(1) Terminated process start", vbInformation, "Check point"
Set colProcesses = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'wscript.exe'")
For Each objProcess In colProcesses
' 自身のプロセスを除外
If objProcess.ProcessId <> GetCurrentProcessID() Then
objProcess.Terminate
MsgBox "Terminated process with PID: " & objProcess.ProcessId, vbInformation, "Process Terminated"
End If
Next
' プロセス終了待機
WScript.Sleep 2000 ' 2秒待機して完全終了を確認
MsgBox "(1) Terminated process end", vbInformation, "Check point"
' ロックファイルを削除
MsgBox "(2) Lock file deleted process start", vbInformation, "Check point"
If fso.FileExists(lockFilePath) Then
fso.DeleteFile(lockFilePath)
MsgBox "(2) Lock file deleted.", vbInformation, "Lock File Deleted"
Else
MsgBox "(2) Lock file not found.", vbExclamation, "Lock File Missing"
End If
' 最後に自身のプロセスを終了
MsgBox "Recovery completed. Exiting the script.", vbInformation, "Recovery Complete"
' 自身のプロセスを終了
WScript.Quit
' 現在のプロセスIDを取得する関数
Function GetCurrentProcessID()
Dim colProcesses, objProcess
Set colProcesses = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'wscript.exe'")
For Each objProcess In colProcesses
' 自身のスクリプト名で絞り込む
If InStr(LCase(objProcess.CommandLine), LCase(WScript.ScriptFullName)) > 0 Then
GetCurrentProcessID = objProcess.ProcessId
Exit Function
End If
Next
End Function
➐ プログラムのダウンロード
プログラムは、Githubで公開しています。
こちらからダウンロードしてください。
➑ 終わりに
Teamsの退席中表示問題に悩んでいる方は多いと思います。悩んだ結果、PowerShellとWSH(VBS)の勉強もできました。イマイルヨを貴方なりのカスタマイズで、貴方なりのTeamsライフをお過ごしください。他にもこんなやり方ありますよとかあれば、コメント欄で教えてくださいね。
それでは、お疲れさまでした😊