パソコンの自動制御に便利なスクリプトツール「PowerShell(パワーシェル)」。
Windowsに標準搭載されており、業務の自動化やバッチ処理に役立つ存在です。
PowerShellが活躍する場面
- 定期的なデータバックアップ
- システムメンテナンスの自動化
- 大量ファイルの一括処理
- 省エネ対策やセキュリティ管理
中でも「スリープ」は、PCの省エネやセキュリティを考えるうえで重要な機能ですが、「コマンドでどうやって制御するの?」「タイマー的な一時停止もスリープって言うの?」と混乱しがちです。
この記事で学べること
- PowerShellにおけるスリープの種類
- スクリプトの一時停止方法
- PCの電源スリープ制御
- 実用的な活用例
- トラブルシューティング
この記事では、PowerShellでのスリープの種類とその制御方法を丁寧に解説。用途別にすぐ使える実例も紹介します。
PowerShellとは(基本知識)

PowerShellの概要
PowerShellの特徴
- Windowsに標準で搭載
- .NETフレームワークベース
- オブジェクト指向のシェル
- 豊富なコマンドレット(コマンド)
PowerShellの起動方法
1. 「Win + R」キーを押す
2. 「powershell」と入力してEnter
3. または「Win + X」→「Windows PowerShell」を選択
管理者権限での起動
1. スタートメニューで「PowerShell」を検索
2. 右クリック→「管理者として実行」
3. UACで「はい」をクリック
PowerShellにおける「スリープ」の種類

「スリープ」と一口に言っても、PowerShellでは2つの異なる意味があります。この違いを理解することが重要です。
(1)スクリプトの一時停止(処理のスリープ)
概要 スクリプトの実行を一時的に止める機能です。プログラムは動いているが、指定した時間だけ処理を待機させます。
使用する場面
- API呼び出しの間隔調整
- ファイル処理の待ち時間
- ユーザーへの表示時間確保
- システム負荷の調整
使用するコマンド
Start-Sleep -Seconds 10 # 10秒待機
Start-Sleep -Milliseconds 500 # 500ミリ秒待機
(2)PC本体のスリープ(電源制御)
概要 パソコン全体をスリープ状態(低電力モード)に移行させる処理です。画面が消え、CPUの動作が停止します。
使用する場面
- 省エネ対策
- セキュリティ確保
- 自動メンテナンス後の電源管理
- 長時間放置時の自動スリープ
使用するコマンド
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
スリープの状態比較
状態 | 電力消費 | 復帰時間 | データ保持 | 用途 |
---|---|---|---|---|
通常動作 | 高 | – | RAM | 作業中 |
スクリプトスリープ | 高 | 即座 | RAM | 処理待機 |
スリープ | 低 | 数秒 | RAM | 一時休止 |
休止状態 | 最低 | 数十秒 | HDD/SSD | 長期休止 |
シャットダウン | なし | 数十秒 | なし | 完全停止 |
まずは「スクリプトを止める」のか「PCを眠らせる」のか、自分の目的を明確にすることが大切です。
スクリプトを一時停止する方法|Start-Sleepの基本

Start-Sleep
はPowerShellにおけるタイマー機能です。処理の流れを制御するために非常によく使われます。
基本的な使い方
秒単位での指定
Start-Sleep -Seconds 5 # 5秒待機
Start-Sleep 5 # 省略形
ミリ秒単位での指定
Start-Sleep -Milliseconds 500 # 500ミリ秒(0.5秒)待機
実用例1:処理の進捗表示
Write-Host "処理を開始します..."
Start-Sleep -Seconds 2
Write-Host "データを読み込み中..."
Start-Sleep -Seconds 3
Write-Host "データを処理中..."
Start-Sleep -Seconds 5
Write-Host "処理が完了しました!"
実用例2:ファイル監視での待機
# ファイルが作成されるまで待機
$filePath = "C:\temp\output.txt"
while (-not (Test-Path $filePath)) {
Write-Host "ファイル待機中..."
Start-Sleep -Seconds 1
}
Write-Host "ファイルが見つかりました!"
実用例3:API呼び出しの間隔調整
# 複数のAPI呼び出しを行う際の間隔調整
$urls = @(
"https://api.example1.com/data",
"https://api.example2.com/data",
"https://api.example3.com/data"
)
foreach ($url in $urls) {
Write-Host "APIを呼び出し中: $url"
# ここでAPI呼び出し処理
Invoke-RestMethod -Uri $url
# 次の呼び出しまで2秒待機(レート制限対策)
Start-Sleep -Seconds 2
}
実用例4:プログレスバー付きの待機
# プログレスバー付きの待機
$totalSeconds = 10
for ($i = 1; $i -le $totalSeconds; $i++) {
$percent = ($i / $totalSeconds) * 100
Write-Progress -Activity "処理待機中" -Status "$i/$totalSeconds 秒" -PercentComplete $percent
Start-Sleep -Seconds 1
}
Write-Progress -Activity "処理待機中" -Completed
Write-Host "待機完了!"
パフォーマンスの考慮事項
短時間での高精度な待機
# 100ミリ秒未満の場合はミリ秒単位を使用
Start-Sleep -Milliseconds 50 # 推奨
Start-Sleep -Seconds 0.05 # 精度が劣る場合がある
長時間の待機
# 1時間待機
Start-Sleep -Seconds 3600
# または読みやすい形で
Start-Sleep -Seconds (60 * 60) # 60秒 × 60分 = 1時間
Start-Sleep
は覚えておいて損のない基本コマンドです。次に、PC自体をスリープにする方法を紹介します。
PCをスリープ状態にする方法|電源制御の実践

Windows PCをPowerShellでスリープ状態に移行させる方法は複数あります。それぞれの特徴と使い分けを詳しく解説します。
方法1:rundll32コマンドを使用
基本構文
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
パラメータの意味
- 第1パラメータ(0):休止状態を無効(0=スリープ、1=休止状態)
- 第2パラメータ(1):強制実行(0=アプリ確認あり、1=強制実行)
- 第3パラメータ(0):ウェイク許可(0=許可、1=禁止)
事前準備:休止状態の無効化
# 管理者権限で実行
powercfg -hibernate off
完全なスクリプト例
# 管理者権限チェック
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Error "このスクリプトは管理者権限で実行してください"
exit 1
}
Write-Host "5秒後にPCをスリープ状態にします..."
Start-Sleep -Seconds 5
# PCをスリープ状態に移行
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
方法2:PowerShell Add-Typeを使用
より制御しやすい方法
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class PowerManager {
[DllImport("powrprof.dll", SetLastError = true)]
public static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent);
}
"@
# スリープ実行
[PowerManager]::SetSuspendState($false, $true, $false)
方法3:WMI(Windows Management Instrumentation)を使用
# WMIクラスを使用したシャットダウン・スリープ
$wmi = Get-WmiObject -Class Win32_OperatingSystem
# スリープ状態に移行(注意:環境によっては動作しない場合があります)
$wmi.SetPowerState(1)
方法4:psshutdownツールの使用
Sysinternals PSToolsのpsshutdownを使用
# 事前にpsshutdownをダウンロードして配置
# https://docs.microsoft.com/en-us/sysinternals/downloads/psshutdown
# スタンバイ(スリープ)モードに移行
psshutdown -d -t 0
タイマー付きスリープスクリプト
指定時間後に自動スリープ
param(
[int]$Minutes = 30 # デフォルト30分
)
$seconds = $Minutes * 60
Write-Host "あと $Minutes 分後にPCがスリープします"
# カウントダウン表示
for ($i = $seconds; $i -gt 0; $i--) {
$remainingMinutes = [math]::Floor($i / 60)
$remainingSeconds = $i % 60
Write-Host "`rスリープまで: ${remainingMinutes}分${remainingSeconds}秒" -NoNewline
Start-Sleep -Seconds 1
# Escキーでキャンセル機能(オプション)
if ([Console]::KeyAvailable) {
$key = [Console]::ReadKey($true)
if ($key.Key -eq "Escape") {
Write-Host "`nスリープをキャンセルしました"
exit
}
}
}
Write-Host "`nPCをスリープ状態にします..."
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
条件付きスリープスクリプト
特定の条件でのみスリープ実行
# CPU使用率が低い場合のみスリープ
$cpuThreshold = 10 # CPU使用率10%以下
$cpu = Get-Counter "\Processor(_Total)\% Processor Time"
$cpuUsage = [math]::Round($cpu.CounterSamples[0].CookedValue, 2)
if ($cpuUsage -lt $cpuThreshold) {
Write-Host "CPU使用率が低いため、スリープします(現在: ${cpuUsage}%)"
Start-Sleep -Seconds 3
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
} else {
Write-Host "CPU使用率が高いため、スリープを見送ります(現在: ${cpuUsage}%)"
}
安全なスリープスクリプト
確認付きスリープ実行
function Confirm-Sleep {
$response = Read-Host "PCをスリープ状態にしますか? (Y/N)"
switch ($response.ToUpper()) {
"Y" {
Write-Host "スリープを実行します..."
Start-Sleep -Seconds 2
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
}
"N" {
Write-Host "スリープをキャンセルしました"
}
default {
Write-Host "Y または N を入力してください"
Confirm-Sleep # 再帰呼び出し
}
}
}
Confirm-Sleep
スリープ設定の確認と管理

現在の電源設定の確認
電源プランの確認
# 現在アクティブな電源プランを表示
powercfg /query SCHEME_CURRENT SUB_SLEEP
# 利用可能な電源プランの一覧
powercfg /list
# スリープ設定の詳細確認
powercfg /query SCHEME_CURRENT SUB_SLEEP STANDBYIDLE
スリープタイマーの確認
# ディスプレイの電源OFF時間
powercfg /query SCHEME_CURRENT SUB_VIDEO VIDEOIDLE
# システムスリープ時間
powercfg /query SCHEME_CURRENT SUB_SLEEP STANDBYIDLE
スリープ設定の変更
コマンドラインでの設定変更
# AC電源接続時のスリープ時間を30分に設定
powercfg /change standby-timeout-ac 30
# バッテリー駆動時のスリープ時間を15分に設定
powercfg /change standby-timeout-dc 15
# ディスプレイの電源OFF時間を10分に設定
powercfg /change monitor-timeout-ac 10
ウェイクタイマーの管理
ウェイクタイマーの確認
# スリープ解除可能なデバイスの確認
powercfg /devicequery wake_armed
# 最後にスリープを解除した理由
powercfg /lastwake
# ウェイクタイマーの一覧
powercfg /waketimers
ウェイクタイマーの無効化
# ウェイクタイマーを無効化
powercfg /change standby-timeout-ac 0
スリープ関連でよくあるトラブルと対処法
トラブル1:rundll32で何も起きない
原因と対処法
# 1. 休止状態が有効になっている
powercfg -hibernate off
# 2. 管理者権限で実行されていない
# → PowerShellを管理者として起動
# 3. 高速スタートアップが干渉している
powercfg /hibernate off
確認用スクリプト
# システムの状態確認
Write-Host "現在の電源設定:"
powercfg /query SCHEME_CURRENT SUB_SLEEP | Select-String "Hibernate\|Standby"
Write-Host "`n管理者権限確認:"
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
Write-Host "管理者権限: $isAdmin"
トラブル2:スリープが勝手に解除される
原因の特定
# 最後にスリープを解除した理由を確認
powercfg /lastwake
# ウェイク可能なデバイスを確認
powercfg /devicequery wake_armed
# アクティブなウェイクタイマーを確認
powercfg /waketimers
対処方法
# マウスやキーボードのウェイク機能を無効化
# デバイスマネージャーで個別設定が必要
# ネットワークアダプターのウェイク機能確認
Get-NetAdapter | Where-Object {$_.Status -eq "Up"} | Get-NetAdapterPowerManagement
# Windows Updateによる自動再起動を無効化
$updateSettings = New-Object -ComObject Microsoft.Update.AutoUpdate
$updateSettings.Settings.NotificationLevel = 1 # 通知のみ
トラブル3:Start-Sleepが効かないように見える
原因と対処法
# 1. 処理が早すぎて気づかない
Write-Host "処理開始: $(Get-Date)"
Start-Sleep -Seconds 5
Write-Host "処理終了: $(Get-Date)"
# 2. 非同期処理と混同している
# → Start-Sleepは同期処理(指定時間必ず待機)
# 3. ミリ秒とマイクロ秒の混同
Start-Sleep -Milliseconds 1000 # 1秒
# Start-Sleep -Microseconds は存在しない
トラブル4:スリープ後にアプリケーションが異常終了
予防策
# スリープ前にアプリケーションを安全に終了
$processesToStop = @("notepad", "calc", "mspaint")
foreach ($processName in $processesToStop) {
$processes = Get-Process -Name $processName -ErrorAction SilentlyContinue
if ($processes) {
Write-Host "$processName を終了中..."
$processes | Stop-Process -Force
Start-Sleep -Seconds 1
}
}
Write-Host "アプリケーション終了完了。スリープを実行します..."
Start-Sleep -Seconds 2
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
トラブル5:ノートPCでスリープが機能しない
確認と対処
# 電源管理ドライバーの状態確認
Get-WmiObject Win32_SystemDriver | Where-Object {$_.Name -like "*power*"}
# BIOS/UEFI設定の確認が必要な場合
Write-Host "以下のBIOS設定を確認してください:"
Write-Host "- ACPI設定"
Write-Host "- Power Management設定"
Write-Host "- USB Power Delivery設定"
# ハードウェア互換性の確認
powercfg /devicequery wake_programmable
実用的なスリープ制御スクリプト

スクリプト1:スマートスリープマネージャー
<#
.SYNOPSIS
スマートスリープマネージャー - 条件に応じて自動でスリープを実行
.DESCRIPTION
CPU使用率、実行中のプロセス、時間帯などを考慮してスリープを実行
.PARAMETER Force
強制的にスリープを実行
.PARAMETER CheckInterval
チェック間隔(分)
#>
param(
[switch]$Force,
[int]$CheckInterval = 5
)
function Test-SystemIdle {
# CPU使用率チェック
$cpu = Get-Counter "\Processor(_Total)\% Processor Time" -SampleInterval 1 -MaxSamples 3
$avgCpu = ($cpu.CounterSamples | Measure-Object CookedValue -Average).Average
# メモリ使用率チェック
$memory = Get-WmiObject Win32_OperatingSystem
$memoryUsage = (($memory.TotalVisibleMemorySize - $memory.FreePhysicalMemory) / $memory.TotalVisibleMemorySize) * 100
# ネットワーク活動チェック
$network = Get-Counter "\Network Interface(*)\Bytes Total/sec" -SampleInterval 1 -MaxSamples 1
$networkActivity = ($network.CounterSamples | Where-Object {$_.InstanceName -ne "Loopback Pseudo-Interface 1"} | Measure-Object CookedValue -Sum).Sum
Write-Host "システム状態:"
Write-Host " CPU使用率: $([math]::Round($avgCpu, 1))%"
Write-Host " メモリ使用率: $([math]::Round($memoryUsage, 1))%"
Write-Host " ネットワーク活動: $([math]::Round($networkActivity / 1024, 1)) KB/s"
# アイドル判定の閾値
return ($avgCpu -lt 10 -and $memoryUsage -lt 80 -and $networkActivity -lt 10240)
}
function Test-CriticalProcesses {
$criticalProcesses = @("sqlservr", "w3wp", "devenv", "Teams", "Zoom")
foreach ($processName in $criticalProcesses) {
if (Get-Process -Name $processName -ErrorAction SilentlyContinue) {
Write-Host "重要なプロセスが実行中: $processName"
return $false
}
}
return $true
}
function Invoke-SmartSleep {
if ($Force) {
Write-Host "強制スリープを実行します..."
} else {
# 時間帯チェック(22:00-06:00の間のみ自動スリープ)
$currentHour = (Get-Date).Hour
if ($currentHour -lt 22 -and $currentHour -gt 6) {
Write-Host "現在の時間帯では自動スリープを実行しません(22:00-06:00以外)"
return
}
# システム状態チェック
if (-not (Test-SystemIdle)) {
Write-Host "システムがアイドル状態ではないため、スリープを見送ります"
return
}
# 重要プロセスチェック
if (-not (Test-CriticalProcesses)) {
Write-Host "重要なプロセスが実行中のため、スリープを見送ります"
return
}
Write-Host "条件を満たしたため、スリープを実行します..."
}
# カウントダウン
for ($i = 10; $i -gt 0; $i--) {
Write-Host "`rスリープまで $i 秒..." -NoNewline
Start-Sleep -Seconds 1
}
Write-Host "`nスリープを実行中..."
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
}
# メイン処理
if ($Force) {
Invoke-SmartSleep
} else {
Write-Host "スマートスリープマネージャーを開始します(チェック間隔: $CheckInterval 分)"
while ($true) {
Write-Host "`n$(Get-Date): システム状態をチェック中..."
Invoke-SmartSleep
Write-Host "次のチェックまで $CheckInterval 分待機..."
Start-Sleep -Seconds ($CheckInterval * 60)
}
}
スクリプト2:タスクスケジューラー連携スリープ
<#
.SYNOPSIS
タスクスケジューラーと連携したスリープ制御
.DESCRIPTION
指定時刻にスリープを実行するタスクを登録・管理
#>
function Register-SleepTask {
param(
[string]$TaskName = "AutoSleep",
[string]$Time = "23:00"
)
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-Command `"rundll32.exe powrprof.dll,SetSuspendState 0,1,0`""
$trigger = New-ScheduledTaskTrigger -Daily -At $Time
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
Register-ScheduledTask -TaskName $TaskName -Action $action -Trigger $trigger -Settings $settings -Principal $principal -Description "自動スリープタスク"
Write-Host "スリープタスクを登録しました: $TaskName (実行時刻: $Time)"
}
function Remove-SleepTask {
param([string]$TaskName = "AutoSleep")
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false -ErrorAction SilentlyContinue
Write-Host "スリープタスクを削除しました: $TaskName"
}
function Show-SleepTasks {
Get-ScheduledTask | Where-Object {$_.TaskName -like "*Sleep*"} | Select-Object TaskName, State, @{Name="NextRun";Expression={(Get-ScheduledTaskInfo $_.TaskName).NextRunTime}}
}
# 使用例
# Register-SleepTask -TaskName "EveningSleep" -Time "22:30"
# Show-SleepTasks
# Remove-SleepTask -TaskName "EveningSleep"
スクリプト3:リモートスリープ制御
<#
.SYNOPSIS
リモートPCのスリープ制御
.DESCRIPTION
ネットワーク経由で他のPCをスリープ状態にする
#>
function Invoke-RemoteSleep {
param(
[string[]]$ComputerName,
[PSCredential]$Credential
)
$scriptBlock = {
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
}
foreach ($computer in $ComputerName) {
try {
Write-Host "リモートスリープを実行中: $computer"
if ($Credential) {
Invoke-Command -ComputerName $computer -ScriptBlock $scriptBlock -Credential $Credential
} else {
Invoke-Command -ComputerName $computer -ScriptBlock $scriptBlock
}
Write-Host "完了: $computer"
} catch {
Write-Error "エラー: $computer - $($_.Exception.Message)"
}
}
}
# 使用例
# $cred = Get-Credential
# Invoke-RemoteSleep -ComputerName "PC01", "PC02" -Credential $cred
高度なスリープ制御テクニック
スリープ状態の監視
# スリープ履歴の確認
function Get-SleepHistory {
param([int]$Days = 7)
$startTime = (Get-Date).AddDays(-$Days)
Get-WinEvent -FilterHashtable @{
LogName = 'System'
Id = 42, 1 # スリープ関連のイベントID
StartTime = $startTime
} | Select-Object TimeCreated, Id, LevelDisplayName, Message | Sort-Object TimeCreated -Descending
}
カスタムスリープ条件
# ファイル監視によるスリープ制御
function Start-FileTriggerSleep {
param(
[string]$WatchPath = "C:\temp\sleep.trigger",
[int]$CheckInterval = 30
)
Write-Host "ファイル監視スリープを開始します: $WatchPath"
while ($true) {
if (Test-Path $WatchPath) {
Write-Host "トリガーファイルを検出しました。スリープを実行します..."
Remove-Item $WatchPath -Force
Start-Sleep -Seconds 3
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
break
}
Write-Host "ファイル監視中... ($(Get-Date))"
Start-Sleep -Seconds $CheckInterval
}
}
スリープ前の自動バックアップ
function Invoke-SleepWithBackup {
param(
[string]$BackupSource = "C:\Users\$env:USERNAME\Documents",
[string]$BackupDestination = "D:\Backup",
[switch]$SkipBackup
)
if (-not $SkipBackup) {
Write-Host "スリープ前にバックアップを実行します..."
# バックアップ先ディレクトリの作成
if (-not (Test-Path $BackupDestination)) {
New-Item -ItemType Directory -Path $BackupDestination -Force
}
# 日付付きバックアップフォルダ
$backupFolder = Join-Path $BackupDestination "Backup_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
try {
# ロバコピーを使用した高速バックアップ
$robocopyArgs = @(
$BackupSource,
$backupFolder,
"/MIR", # ミラー同期
"/R:1", # リトライ回数
"/W:1", # 待機時間
"/NP", # プログレス非表示
"/MT:8" # マルチスレッド
)
Write-Host "バックアップ開始: $BackupSource → $backupFolder"
Start-Process -FilePath "robocopy" -ArgumentList $robocopyArgs -Wait -NoNewWindow
Write-Host "バックアップ完了"
} catch {
Write-Warning "バックアップでエラーが発生しました: $($_.Exception.Message)"
$continue = Read-Host "バックアップに失敗しましたが、スリープを続行しますか? (Y/N)"
if ($continue -ne "Y") {
Write-Host "スリープをキャンセルしました"
return
}
}
}
Write-Host "PCをスリープ状態にします..."
Start-Sleep -Seconds 3
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
}
エラーハンドリングとログ機能

包括的なエラーハンドリング
function Invoke-SafeSleep {
param(
[int]$DelaySeconds = 5,
[string]$LogPath = "$env:TEMP\SleepLog.txt"
)
try {
# ログファイルの初期化
if (-not (Test-Path $LogPath)) {
New-Item -ItemType File -Path $LogPath -Force
}
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Add-Content -Path $LogPath -Value "[$timestamp] スリープ処理開始"
# 管理者権限チェック
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
if (-not $isAdmin) {
$errorMsg = "管理者権限が必要です"
Add-Content -Path $LogPath -Value "[$timestamp] エラー: $errorMsg"
throw $errorMsg
}
# システム状態チェック
$runningProcesses = Get-Process | Where-Object {$_.ProcessName -in @("Teams", "Zoom", "Skype")}
if ($runningProcesses) {
$processNames = $runningProcesses.ProcessName -join ", "
Add-Content -Path $LogPath -Value "[$timestamp] 警告: 通信アプリが実行中 ($processNames)"
$continue = Read-Host "通信アプリが実行中です。続行しますか? (Y/N)"
if ($continue -ne "Y") {
Add-Content -Path $LogPath -Value "[$timestamp] ユーザーによりキャンセル"
return
}
}
# 未保存ファイルの確認
$unsavedFiles = Get-Process | Where-Object {$_.MainWindowTitle -like "*- 名前未設定*" -or $_.MainWindowTitle -like "**"}
if ($unsavedFiles) {
Add-Content -Path $LogPath -Value "[$timestamp] 警告: 未保存ファイルの可能性"
Write-Warning "未保存のファイルがある可能性があります。保存してください。"
Start-Sleep -Seconds 10
}
# カウントダウン
Write-Host "スリープ実行まで:"
for ($i = $DelaySeconds; $i -gt 0; $i--) {
Write-Host "`r $i 秒..." -NoNewline
Start-Sleep -Seconds 1
}
Add-Content -Path $LogPath -Value "[$timestamp] スリープ実行"
Write-Host "`nスリープを実行しています..."
# スリープ実行
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
} catch {
$errorTimestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$errorMessage = $_.Exception.Message
Add-Content -Path $LogPath -Value "[$errorTimestamp] エラー: $errorMessage"
Write-Error "スリープの実行に失敗しました: $errorMessage"
# エラー時の代替処理
$altAction = Read-Host "代替処理を選択してください: [1]再試行 [2]シャットダウン [3]キャンセル"
switch ($altAction) {
"1" {
Write-Host "再試行します..."
Invoke-SafeSleep -DelaySeconds $DelaySeconds -LogPath $LogPath
}
"2" {
Write-Host "シャットダウンを実行します..."
Stop-Computer -Force
}
"3" {
Write-Host "処理をキャンセルしました"
}
default {
Write-Host "無効な選択です。処理をキャンセルします"
}
}
}
}
ログ分析ツール
function Analyze-SleepLog {
param(
[string]$LogPath = "$env:TEMP\SleepLog.txt",
[int]$Days = 30
)
if (-not (Test-Path $LogPath)) {
Write-Warning "ログファイルが見つかりません: $LogPath"
return
}
$logContent = Get-Content $LogPath
$startDate = (Get-Date).AddDays(-$Days)
# ログエントリの解析
$sleepEntries = @()
$errorEntries = @()
foreach ($line in $logContent) {
if ($line -match '^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] (.+)) {
$timestamp = [DateTime]::Parse($matches[1])
$message = $matches[2]
if ($timestamp -ge $startDate) {
if ($message -like "*スリープ実行*") {
$sleepEntries += [PSCustomObject]@{
Timestamp = $timestamp
Message = $message
}
} elseif ($message -like "*エラー*") {
$errorEntries += [PSCustomObject]@{
Timestamp = $timestamp
Message = $message
}
}
}
}
}
# 統計情報の表示
Write-Host "=== スリープログ分析結果 (過去 $Days 日) ==="
Write-Host "スリープ実行回数: $($sleepEntries.Count)"
Write-Host "エラー発生回数: $($errorEntries.Count)"
if ($sleepEntries.Count -gt 0) {
$avgSleepTime = $sleepEntries | Group-Object {$_.Timestamp.Hour} | Sort-Object Count -Descending | Select-Object -First 1
Write-Host "最も多いスリープ時間帯: $($avgSleepTime.Name)時台 ($($avgSleepTime.Count)回)"
}
if ($errorEntries.Count -gt 0) {
Write-Host "`n=== 最近のエラー ==="
$errorEntries | Select-Object -Last 5 | ForEach-Object {
Write-Host "[$($_.Timestamp)] $($_.Message)"
}
}
}
GUI付きスリープ制御ツール
Windows Forms を使用したGUIツール
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
function Show-SleepControlGUI {
# フォームの作成
$form = New-Object System.Windows.Forms.Form
$form.Text = "PowerShell スリープ制御ツール"
$form.Size = New-Object System.Drawing.Size(400, 300)
$form.StartPosition = "CenterScreen"
$form.FormBorderStyle = "FixedDialog"
$form.MaximizeBox = $false
# タイマー設定
$timerLabel = New-Object System.Windows.Forms.Label
$timerLabel.Text = "スリープまでの時間 (分):"
$timerLabel.Location = New-Object System.Drawing.Point(20, 20)
$timerLabel.Size = New-Object System.Drawing.Size(150, 20)
$form.Controls.Add($timerLabel)
$timerTextBox = New-Object System.Windows.Forms.TextBox
$timerTextBox.Text = "5"
$timerTextBox.Location = New-Object System.Drawing.Point(180, 18)
$timerTextBox.Size = New-Object System.Drawing.Size(60, 20)
$form.Controls.Add($timerTextBox)
# チェックボックス
$forceCheckBox = New-Object System.Windows.Forms.CheckBox
$forceCheckBox.Text = "強制スリープ(アプリ確認なし)"
$forceCheckBox.Location = New-Object System.Drawing.Point(20, 50)
$forceCheckBox.Size = New-Object System.Drawing.Size(200, 20)
$form.Controls.Add($forceCheckBox)
$backupCheckBox = New-Object System.Windows.Forms.CheckBox
$backupCheckBox.Text = "スリープ前にバックアップ実行"
$backupCheckBox.Location = New-Object System.Drawing.Point(20, 75)
$backupCheckBox.Size = New-Object System.Drawing.Size(200, 20)
$form.Controls.Add($backupCheckBox)
# ステータスラベル
$statusLabel = New-Object System.Windows.Forms.Label
$statusLabel.Text = "準備完了"
$statusLabel.Location = New-Object System.Drawing.Point(20, 110)
$statusLabel.Size = New-Object System.Drawing.Size(350, 40)
$statusLabel.BorderStyle = "Fixed3D"
$form.Controls.Add($statusLabel)
# プログレスバー
$progressBar = New-Object System.Windows.Forms.ProgressBar
$progressBar.Location = New-Object System.Drawing.Point(20, 160)
$progressBar.Size = New-Object System.Drawing.Size(350, 20)
$progressBar.Visible = $false
$form.Controls.Add($progressBar)
# ボタン
$startButton = New-Object System.Windows.Forms.Button
$startButton.Text = "スリープ開始"
$startButton.Location = New-Object System.Drawing.Point(20, 200)
$startButton.Size = New-Object System.Drawing.Size(100, 30)
$form.Controls.Add($startButton)
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Text = "キャンセル"
$cancelButton.Location = New-Object System.Drawing.Point(140, 200)
$cancelButton.Size = New-Object System.Drawing.Size(100, 30)
$cancelButton.Enabled = $false
$form.Controls.Add($cancelButton)
$immediateButton = New-Object System.Windows.Forms.Button
$immediateButton.Text = "即座にスリープ"
$immediateButton.Location = New-Object System.Drawing.Point(260, 200)
$immediateButton.Size = New-Object System.Drawing.Size(110, 30)
$form.Controls.Add($immediateButton)
# タイマー
$timer = New-Object System.Windows.Forms.Timer
$script:remainingSeconds = 0
$script:isCanceled = $false
# イベントハンドラー
$startButton.Add_Click({
try {
$minutes = [int]$timerTextBox.Text
$script:remainingSeconds = $minutes * 60
$script:isCanceled = $false
$progressBar.Maximum = $script:remainingSeconds
$progressBar.Value = 0
$progressBar.Visible = $true
$startButton.Enabled = $false
$cancelButton.Enabled = $true
$immediateButton.Enabled = $false
$statusLabel.Text = "カウントダウン開始: $minutes 分後にスリープします"
$timer.Start()
} catch {
[System.Windows.Forms.MessageBox]::Show("無効な時間が入力されました", "エラー", "OK", "Error")
}
})
$cancelButton.Add_Click({
$script:isCanceled = $true
$timer.Stop()
$progressBar.Visible = $false
$startButton.Enabled = $true
$cancelButton.Enabled = $false
$immediateButton.Enabled = $true
$statusLabel.Text = "キャンセルされました"
})
$immediateButton.Add_Click({
$result = [System.Windows.Forms.MessageBox]::Show("すぐにスリープしますか?", "確認", "YesNo", "Question")
if ($result -eq "Yes") {
$form.Hide()
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
}
})
$timer.Add_Tick({
if ($script:isCanceled) {
return
}
$script:remainingSeconds--
$progressBar.Value = $progressBar.Maximum - $script:remainingSeconds
$minutes = [math]::Floor($script:remainingSeconds / 60)
$seconds = $script:remainingSeconds % 60
$statusLabel.Text = "残り時間: ${minutes}分${seconds}秒"
if ($script:remainingSeconds -le 0) {
$timer.Stop()
$statusLabel.Text = "スリープを実行中..."
$form.Hide()
# バックアップオプションのチェック
if ($backupCheckBox.Checked) {
# バックアップ処理(簡略版)
$statusLabel.Text = "バックアップ実行中..."
Start-Sleep -Seconds 2
}
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
}
})
$timer.Interval = 1000 # 1秒間隔
# フォーム表示
$form.ShowDialog()
}
# GUIツールの起動
# Show-SleepControlGUI
自動化とスケジューリング
スリープポリシーの実装
class SleepPolicy {
[string]$Name
[hashtable]$Conditions
[scriptblock]$Action
[bool]$Enabled
SleepPolicy([string]$name, [hashtable]$conditions, [scriptblock]$action) {
$this.Name = $name
$this.Conditions = $conditions
$this.Action = $action
$this.Enabled = $true
}
[bool]CheckConditions() {
foreach ($key in $this.Conditions.Keys) {
$value = $this.Conditions[$key]
switch ($key) {
"Time" {
$currentTime = Get-Date -Format "HH:mm"
if ($currentTime -ne $value) { return $false }
}
"DayOfWeek" {
if ((Get-Date).DayOfWeek -notin $value) { return $false }
}
"CpuThreshold" {
$cpu = Get-Counter "\Processor(_Total)\% Processor Time" -SampleInterval 1 -MaxSamples 1
if ($cpu.CounterSamples[0].CookedValue -gt $value) { return $false }
}
"NoActiveUsers" {
$activeSessions = quser 2>$null
if ($activeSessions -and $value) { return $false }
}
}
}
return $true
}
[void]Execute() {
if ($this.Enabled -and $this.CheckConditions()) {
Write-Host "ポリシー '$($this.Name)' の条件が満たされました。実行します..."
& $this.Action
}
}
}
# ポリシーの定義例
$policies = @(
[SleepPolicy]::new("NightSleep", @{
Time = "23:00"
DayOfWeek = @("Monday", "Tuesday", "Wednesday", "Thursday", "Friday")
CpuThreshold = 15
}, {
Write-Host "夜間自動スリープを実行"
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
}),
[SleepPolicy]::new("LunchSleep", @{
Time = "12:00"
NoActiveUsers = $true
CpuThreshold = 10
}, {
Write-Host "昼休み自動スリープを実行"
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
})
)
function Start-SleepPolicyMonitor {
param([SleepPolicy[]]$Policies)
Write-Host "スリープポリシー監視を開始します..."
while ($true) {
foreach ($policy in $Policies) {
$policy.Execute()
}
Start-Sleep -Seconds 60 # 1分間隔でチェック
}
}
# 使用例
# Start-SleepPolicyMonitor -Policies $policies
まとめ|PowerShellでスリープを自在に扱うテクニック
PowerShellでは、**「スクリプトの一時停止」と「PCの電源スリープ」**の両方を柔軟に制御できます。この記事で学んだ内容をまとめると:
基本的なスリープ制御
- Start-Sleep:スクリプトの一時停止
- 秒単位:
Start-Sleep -Seconds 10
- ミリ秒単位:
Start-Sleep -Milliseconds 500
- 秒単位:
- rundll32:PCのスリープ制御
- 基本形:
rundll32.exe powrprof.dll,SetSuspendState 0,1,0
- 管理者権限が必要
- 基本形:
高度な活用方法
- 条件付きスリープ:CPU使用率や時間帯による制御
- スマートスリープ:システム状態を総合判断
- タスクスケジューラー連携:定時自動実行
- GUI制御:使いやすいインターフェース
- ログ機能:実行履歴の管理
トラブルシューティングのポイント
- 管理者権限の確認
- 休止状態の無効化
- ウェイクタイマーの管理
- 実行中アプリの確認
コメント