やりたい事
- スクリーンセーバうざい
制約
- Windows10
- 外部ソフト持ち込まない
できた
- PowerShell
- 多分PowerShell2=Win7以降使えると思う
- 外見はbat
- 内部はC#
- マウスぷるぷる
先人の知恵 - Qiita
- 作ってから記事見つけたけど多分2番の記事なら同等の制約のとき使える
- スクリーンセーバの起動を抑制する - mpgバージョン
- スクリーンセーバの起動を抑制する - vbsバージョン
- スクリーンセーバの起動を抑制する - Arduino Pro Micro(の互換機)を使用
- マウスをぷるぷる動かしてスクリーンセーバを抑制するアプリ
- やむを得ない事情でスクリーンセーバーが解除できない時に出させないようにするには?
- 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);
以上