Help us understand the problem. What is going on with this article?

スクリーンセーバ抑止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)

$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
if (! $myWindowsPrincipal.IsInRole($adminRole))
{
  $newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";
  $newProcess.Arguments = $myInvocation.MyCommand.Definition;
  $newProcess.Verb = "runas";
  [System.Diagnostics.Process]::Start($newProcess); # 
}

$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++) {
  Write-Host $i
  Start-Sleep -Seconds 60
  [Win32SendInput]::PreventScreenSaver() # 
}

解説

DOSバッチ から PowerShell 実行

  • 頭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

PowerShell 本体

  • 上記解説の通り3行目以降はPowerShellです
  • デフォルト240分うごかすという設定、パラメータ受け取りで変更できるようにしときます
line4
Param($minutes = 240)

管理者として自身を実行

line6-15
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
if (! $myWindowsPrincipal.IsInRole($adminRole))
{
  $newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";
  $newProcess.Arguments = $myInvocation.MyCommand.Definition;
  $newProcess.Verb = "runas";
  [System.Diagnostics.Process]::Start($newProcess); # 
}

CS 埋め込み

  • PowerShellではC#が埋め込めます
  • ここではヒアドキュメントつかって変数にぶち込んでます
  • 解説できませんがマウス動かすコードです、拾い物を継ぎ接ぎしました
  • 座標0動かしてるので実際は動いてません
line17-63
$cs = @"
using System;
// コード省略
"@

CS コンパイル

  • この一行でC#をコンパイルしてスクリプトで使えるになっちゃいます
line64
Add-Type -Language CSharp -TypeDefinition $cs

CS 実行 ループ

  • 240回のループ中で
  • 1分のスリープと
  • C#で作ったマウスぷるぷると
  • コンソール出力(動作していることを確認用)
line66-70
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);

以上

kfjt
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした