38
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

スクリーンセーバ抑止PowerShell

Last updated at Posted at 2018-07-09

やりたい事

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

制約

  • 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);

以上

38
43
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?