Windows
PowerShell
ScreenSaver

スクリーンセーバ抑止PowerShell

やりたい事

  • スクリーンセーバうざい

制約

  • Windows10
  • 外部ソフト持ち込まない

できた

  • PowerShell
    • 多分PowerShell2=Win7以降使えると思う
    • 外見はbat
    • 内部はC#
  • マウスぷるぷる

先人の知恵 - Qiita

  • 作ってから記事見つけたけど多分2番の記事なら同等の制約のとき使える
  1. スクリーンセーバの起動を抑制する - mpgバージョン
  2. スクリーンセーバの起動を抑制する - vbsバージョン
  3. スクリーンセーバの起動を抑制する - Arduino Pro Micro(の互換機)を使用
  4. マウスをぷるぷる動かしてスクリーンセーバを抑制するアプリ
  5. やむを得ない事情でスクリーンセーバーが解除できない時に出させないようにするには?
  6. 3分ごとにマウスを動かす

実装

PreventScreenSaver.bat
@powershell -NoProfile -ExecutionPolicy Unrestricted "&([ScriptBlock]::Create((cat -encoding utf8 \"%~f0\" | ? {$_.ReadCount -gt 2}) -join \"`n\"))" %*
@exit /b

Param($minutes = 240)

$cs = @"
using System;
using System.Runtime.InteropServices;

public class Win32SendInput {
 [DllImport("user32.dll")]
 static extern uint SendInput(
  uint nInputs,
  ref INPUT pInputs,
  int cbSize
 );

 [StructLayout(LayoutKind.Sequential)]
 struct INPUT
 {
  public int type;
  public MOUSEINPUT mi;
 }

 [StructLayout(LayoutKind.Sequential)]
 struct MOUSEINPUT
 {
  public int dx;
  public int dy;
  public uint mouseData;
  public uint dwFlags;
  public uint time;
  public IntPtr dwExtraInfo;
 }

 public static void PreventScreenSaver()
 {
  INPUT input = new INPUT();
  input.type = 0; // INPUT_MOUSE;
  input.mi = new MOUSEINPUT();

  input.mi.dwExtraInfo = IntPtr.Zero;
  input.mi.dx = 0;
  input.mi.dy = 0;
  input.mi.time = 0;
  input.mi.mouseData = 0;
  input.mi.dwFlags = 0x0001; // MOVE (RELATIVE)
  int cbSize = Marshal.SizeOf(typeof(INPUT));
  uint r = SendInput(1, ref input, cbSize);
 }
}
"@
Add-Type -Language CSharp -TypeDefinition $cs

for ($i = 0; $i -lt $minutes; $i++) {
  Start-Sleep -Seconds 60
  [Win32SendInput]::PreventScreenSaver() # 
  Write-Host $i
}

解説

  • 頭2行はDOSバッチです。1行目でPowerShell起動、2行目で終了
  • PowerShell起動のパラメータでこのファイル自身を読み込み先頭2行を無視して解釈してます
line1-2
@powershell -NoProfile -ExecutionPolicy Unrestricted "&([ScriptBlock]::Create((cat -encoding utf8 \"%~f0\" | ? {$_.ReadCount -gt 2}) -join \"`n\"))" %*
@exit /b
  • 上記解説の通り3行目以降はPowerShellです
  • デフォルト240分うごかすという設定、パラメータ受け取りで変更できるようにしときます
line4
Param($minutes = 240)
  • PowerShellではC#が埋め込めます
  • ここではヒアドキュメントつかって変数にぶち込んでます
  • 解説できませんがマウス動かすコードです、拾い物を継ぎ接ぎしました
  • 座標0動かしてるので実際は動いてません
line6-52
$cs = @"
using System;
// コード省略
"@
  • この一行でC#をコンパイルしてスクリプトで使えるになっちゃいます
line53
Add-Type -Language CSharp -TypeDefinition $cs
  • 240回のループ中で
  • 1分のスリープと
  • C#で作ったマウスぷるぷると
  • コンソール出力(動作していることを確認用)
line55-59
for ($i = 0; $i -lt $minutes; $i++) {
  Start-Sleep -Seconds 60
  [Win32SendInput]::PreventScreenSaver() # 
  Write-Host $i
}

敢えて対処しない

  • キーワード「リモートデスクトップ アイドルタイマー 2分後に切断」

おまけ

  • とある環境の人には役立つと思うなにか
    • コマンドプロンプトが起動できない環境
    • メモ帳が起動できない環境
    • ブラウザはアドレスバーが表示できない環境
    • ブラウザF12も無効な環境
  • およそプログラム的なことが出来なさそうな環境で、定期的に無操作でないようにしたい場合
ブラウザ→右クリック→要素の検査→コンソール
var s=new ActiveXObject("WScript.Shell");var f=function(){s.sendkeys("^{ESC}");};setInterval("f()",300000);

以上