Windows のタスク スケジューラで「ログオン時に実行したいが、08:00〜20:00 の間にログオンしたときだけ動かしたい」という要件は、設定だけで解決しようとすると詰まりがちです。この記事では、タスク スケジューラは“起動のきっかけ”に徹し、PowerShell 側で現在時刻を判定して NirCmd で既定のサウンド出力(スピーカー/ヘッドホン)を昼夜で自動切り替えする手順をまとめます。
やりたいこと(要件)を具体化する
まずは「実現したい挙動」を、タスクとして実装できる形に落とし込みます。今回のポイントは、“ログオン時に実行する”だけでなく、“ログオン時刻が特定の時間帯のときだけ実行したい”という条件が入っている点です。
| 状況 | 期待する動作 | 狙い |
|---|---|---|
| 08:00 の時点でログオン済み | 08:00 に実行される | 昼の開始でスピーカーに自動切り替え |
| 09:00 にログオンした | ログオン直後に実行される | 日中の途中参加でも即スピーカーに切り替え |
| 19:30 にログオンした | ログオン直後に実行される | まだ日中なのでスピーカー |
| 20:00 以降にログオンした | (スピーカーへ切り替える処理は)走ってほしくない | 夜はヘッドホンにしたい |
最終的なゴールが「昼はスピーカー、夜はヘッドホン」なら、“スピーカー切り替えタスクを時間帯で抑制する”よりも、そもそも“どちらに切り替えるか”を時間帯で判断するほうがトラブルが少なくなります。ここが設計の分かれ道です。
タスク スケジューラの設定だけでハマる理由
「予定実行を逃したらすぐ実行する」で 8:00 以降のログオンはカバーできる
「毎日 08:00 に実行する」トリガーを作っている場合、PC が 08:00 に起動していないとその回は実行されません。ここを救うのが、次の設定です。
- タスク スケジューラで対象タスクを右クリック → [プロパティ]
- [設定]タブ
- 「スケジュールされた開始が行われなかった場合、できるだけ早くタスクを実行する」にチェック
この設定により、たとえば 09:00 に PC を起動してログオンした場合でも、「08:00 の予定実行を逃した分」としてログオン後すぐに実行されます。“08:00 を過ぎてからの起動・ログオンでもその時点で実行させたい”というニーズに強いです。
ただし、この設定だけでは「20:00 以降にログオンしたときは実行しない」という条件は作れません。08:00 の予定を逃した扱いで、20:30 にログオンしても“できるだけ早く”実行されてしまいます。
ログオン トリガーに「この時間帯だけ実行」を直指定しづらい
タスク スケジューラの GUI には、ログオン トリガーに対して「実行可能な時間帯(08:00〜20:00)をそのまま条件として付与する」ような分かりやすい項目が用意されていません。
もちろん工夫の余地はあります。たとえば「繰り返し間隔」「継続時間」を使い、08:00〜20:00 の間に一定間隔で何度も実行して状態を修正し続ける、といった構成も可能です。しかし今回の要件は、
- ログオン時に 1 回だけ切り替えたい(必要なら 08:00 にも 1 回)
- 実行するかどうかはログオン時刻(=現在時刻)で決めたい
なので、スケジューラ側のトリガーを複雑にするより、「判定ロジックはスクリプトに寄せる」ほうが安定します。
結論:タスク スケジューラは“起動”だけ、時間帯の判定は PowerShell で行う
現実的で壊れにくい構成は次のとおりです。
| 役割 | 担当 | 理由 |
|---|---|---|
| 「いつ」実行するか | タスク スケジューラ(ログオン時/08:00 など) | イベントや時刻に強い |
| 「何を」実行するか | PowerShell スクリプト | 条件分岐(08:00〜20:00 など)を柔軟に書ける |
| サウンド出力の切り替え | NirCmd | コマンドで既定デバイス切替ができる |
この設計だと、スクリプトは「実行されたら必ず現在時刻を見て、昼ならスピーカー、夜ならヘッドホン」という判断を行います。つまり20:00 以降にログオンしても、スピーカーに切り替える処理が走らない(正確には“夜判定になるのでヘッドホン側に寄る”)ため、要件を満たせます。
NirCmd の準備と「デバイス名」の確認が成功率を左右する
NirCmd のコマンドは、指定するデバイス名が一致していないと期待どおりに動きません。ここは最初に固めておくと、後がスムーズです。
NirCmd を配置する
- NirCmd(nircmd.exe)を任意のフォルダに置きます(例:
C:\Tools\nircmd\nircmd.exe) - パスが短く、管理しやすい場所に固定するのがおすすめです
既定のサウンドデバイス名を把握する
方法はいくつかあります。確実なのは Windows 側の名称を拾うことです。
- 設定 → システム → サウンド で出力デバイス名を確認
- 従来のサウンド画面(例:
mmsys.cpl)で再生デバイス一覧から名称を確認
デバイス名は環境によって異なります。たとえば次のような差が出ます。
| よくある表示名の例 | 意味 | 注意点 |
|---|---|---|
| Speakers (Realtek(R) Audio) | 内蔵・有線スピーカー | 括弧や記号まで一致が必要な場合あり |
| Headphones (Bluetooth Headset) | Bluetooth ヘッドホン | 接続していないと切替に失敗することがある |
| ヘッドホン (USB Audio) | USB DAC など | 日本語名でも OK。スクリプトはダブルクォート推奨 |
Bluetooth の場合、ログオン直後はまだデバイスが初期化中で切替に失敗することがあります。後述のスクリプトで数秒待ってから実行できるようにしておくと安定します。
PowerShell スクリプト例(時間帯でスピーカー/ヘッドホンを自動切替)
以下は「08:00〜20:00 はスピーカー」「それ以外はヘッドホン」に切り替えるためのサンプルです。単に Hour だけを見るより、分まで含めて境界(20:00 ちょうど等)を正確に扱えるようにしています。
例として C:\Scripts\Switch-AudioByTime.ps1 に保存してください。
# Switch-AudioByTime.ps1
# 08:00〜20:00:スピーカー / それ以外:ヘッドホン(NirCmdで既定デバイスを切り替え)
# ==== ここを環境に合わせて変更 ====
$NirCmdPath = "C:\Tools\nircmd\nircmd.exe"
$DayDeviceName = "Speakers" # 日中に使いたいデバイス名
$NightDeviceName = "Headphones" # 夜間に使いたいデバイス名
# 時間帯(分まで扱えるよう TimeSpan で定義)
$DayStart = [TimeSpan]::FromHours(8) # 08:00
$DayEnd = [TimeSpan]::FromHours(20) # 20:00(この時刻は夜扱いにする)
# Bluetooth 等の初期化待ち(必要に応じて)
$InitialDelaySeconds = 3
# ================================
# ログ出力(任意)
$LogDir = Join-Path $env:LOCALAPPDATA "AudioSwitch"
$LogFile = Join-Path $LogDir "AudioSwitch.log"
New-Item -ItemType Directory -Force -Path $LogDir | Out-Null
function Write-Log {
param([string]$Message)
$ts = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
Add-Content -Path $LogFile -Value "[$ts] $Message"
}
# NirCmd の存在チェック
if (-not (Test-Path -LiteralPath $NirCmdPath)) {
Write-Log "ERROR: NirCmd が見つかりません: $NirCmdPath"
exit 1
}
# 必要なら少し待つ(ログオン直後のBluetooth対策など)
if ($InitialDelaySeconds -gt 0) {
Start-Sleep -Seconds $InitialDelaySeconds
}
$now = Get-Date
$time = $now.TimeOfDay
# 08:00 以上かつ 20:00 未満を「昼」とする(20:00 ちょうどは夜)
$isDay = ($time -ge $DayStart -and $time -lt $DayEnd)
$target = if ($isDay) { $DayDeviceName } else { $NightDeviceName }
Write-Log "INFO: now=$($now.ToString('HH:mm:ss')) isDay=$isDay target=$target"
# 役割(Console/Multimedia/Communications)をまとめて変える(対応していない環境ではフォールバック)
$roles = @(0, 1, 2)
$success = $false
foreach ($r in $roles) {
& $NirCmdPath setdefaultsounddevice "$target" $r | Out-Null
if ($LASTEXITCODE -eq 0) {
$success = $true
}
}
if (-not $success) {
# role 指定が不要/非対応のケースに備えて role なしで再試行
& $NirCmdPath setdefaultsounddevice "$target" | Out-Null
if ($LASTEXITCODE -eq 0) {
$success = $true
}
}
if ($success) {
Write-Log "INFO: switched to $target"
exit 0
} else {
Write-Log "ERROR: failed to switch. target=$target exitcode=$LASTEXITCODE"
exit 2
}
このスクリプトのポイント
- タスクが何時に起動しても正しい側に寄せる(昼ならスピーカー、夜ならヘッドホン)
- 20:00 ちょうどは夜扱いにして、境界のブレをなくす
- Bluetooth 対策として、必要なら 数秒待ってから切り替えできる
- ログを
%LOCALAPPDATA%\AudioSwitch\AudioSwitch.logに残し、原因追跡しやすい
タスク スケジューラの作り方(ログオン時+08:00 を両立)
ここからはタスク スケジューラの設定です。ポイントは「トリガーは複数持たせて OK」「実行するたびにスクリプトが最終状態を正しくする」構成にすることです。
タスクは「基本タスクの作成」ではなく「タスクの作成」を使う
細かい設定(同時実行の制御、逃した予定実行の扱いなど)が必要になるため、タスク スケジューラで「タスクの作成」から作成します。
全般タブ(最初に迷いやすい項目)
| 項目 | 推奨 | 理由 |
|---|---|---|
| 名前 | AudioSwitch_ByTime など分かりやすく | 後から見て用途が一瞬で分かる |
| セキュリティ オプション | 「ユーザーがログオンしている場合のみ実行する」 | サウンドの既定デバイスはユーザー セッション依存になりやすい |
| 最上位の特権で実行する | 環境により ON 推奨 | 環境差があるため。動かなければ ON を試す |
音声デバイス切替は「誰の既定?」が重要です。共有 PC や複数アカウント環境では、タスクを実行するユーザーを明確にしておくと事故が減ります。
トリガータブ(ログオン時+08:00 の両方を入れる)
ここが今回のキモです。トリガーは 1 つに絞らなくて構いません。
- トリガー 1:「ログオン時」
- トリガー 2:「毎日 08:00」
- (任意)トリガー 3:「毎日 20:00」
「毎日 20:00」も入れる理由は、ログオンしたまま 20:00 を跨いだときに夜用(ヘッドホン)へ確実に切り替えるためです。要件が「ログオン時にだけ合っていれば良い」なら省略できますが、昼夜切替を完成させたい場合は入れておくと体験が安定します。
トリガー追加の具体例です。
| トリガー | 設定例 | 補足 |
|---|---|---|
| ログオン時 | 特定のユーザー(自分のアカウント) | 他ユーザーで勝手に切り替わるのを防ぐ |
| 毎日 08:00 | 開始時刻 08:00 / 毎日 | PC が起動していれば 08:00 に実行される |
| 毎日 20:00(任意) | 開始時刻 20:00 / 毎日 | 夜への切替を自動化(ログオン継続時にも効く) |
さらに安定させたい場合は、ログオン トリガーに「遅延」(例:10 秒)を入れて、デバイス初期化の時間を確保するのも有効です。スクリプト側の Start-Sleep と役割が被るので、どちらか一方で十分です。
操作タブ(PowerShell の呼び出し方)
「プログラムの開始」で PowerShell を呼び出し、作成したスクリプトを実行します。
| 項目 | 設定例 |
|---|---|
| プログラム/スクリプト | powershell.exe |
| 引数の追加 | -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\Switch-AudioByTime.ps1" |
| 開始 (オプション) | C:\Scripts |
-ExecutionPolicy Bypass は手軽ですが、組織ポリシーや運用方針によっては許可されない場合があります。その場合は、署名付きスクリプトにする、許可された実行ポリシーに合わせるなどの調整が必要です。
設定タブ(今回必須級のチェック)
「08:00 を逃したらログオン直後に実行」を成立させる設定と、二重起動によるレースを潰す設定を入れます。
| 設定 | 推奨 | 目的 |
|---|---|---|
| スケジュールされた開始が行われなかった場合、できるだけ早くタスクを実行する | ON | 08:00 に起動していなくても、起動後に追いかけ実行 |
| タスクが既に実行中の場合の規則 | 「新しいインスタンスを開始しない」 | ログオン+08:00 などが同時に走っても衝突しにくい |
| タスクを停止するまでの時間(任意) | 1 分など短め | 万一ハングしても残り続けない |
この構成だと、ログオン時に実行されても 08:00 に実行されても、スクリプトが最終的に“今あるべき状態”に寄せるため、タスク側の条件分岐が不要になります。
「20:00 以降にログオンしたら実行しない」をどう満たすか
厳密に「タスク自体を実行しない」にこだわると、タスク スケジューラ単体では分岐が難しくなります。一方で、目的が「夜はスピーカーに切り替えたくない」なら、次の考え方が実用的です。
- タスクは実行されてもよい(起動トリガーとして働けばよい)
- 実際にスピーカーへ切り替えるかどうかはスクリプトが判定する
- 20:00 以降は夜判定になるので、結果としてスピーカーへは切り替わらない
つまり、ユーザー体験としては「20:00 以降にログオンしてもスピーカーにならない」=要件を満たします。タスクの“実行有無”に固執しないほうが、設定がシンプルで壊れにくくなります。
動作確認のコツ(公開前にここまでチェック)
- タスク スケジューラの対象タスクで「実行」を押して、ログファイル(
%LOCALAPPDATA%\AudioSwitch\AudioSwitch.log)に記録されるか確認する - デバイス名をわざと間違えて実行し、ログに ERROR が出ることを確認(エラーが見える状態にしておく)
- 08:00〜20:00 の境界が気になる場合は、一時的に
$DayStartと$DayEndを短い範囲に変え、切替が起きるかテストする - 「履歴」を有効化し、タスクがいつ起動したか(ログオンなのか 08:00 なのか)を追えるようにする
よくある失敗と対処(チェックリスト)
| 症状 | 原因の候補 | 対処 |
|---|---|---|
| 何も変わらない | NirCmd のパスが違う | $NirCmdPath を実在パスに修正。まず手動で nircmd.exe を実行できるか確認 |
| 特定デバイスに切り替わらない | デバイス名が一致していない | Windows のサウンド設定に出ている名称をそのまま貼る(記号・括弧・全角半角に注意) |
| Bluetooth ヘッドホンだけ失敗しやすい | ログオン直後にまだ接続・初期化が完了していない | $InitialDelaySeconds を 5〜10 秒に増やす/トリガー側の遅延を入れる |
| 08:00 に PC が起動していないと切り替わらない | 「逃した予定はすぐ実行」が OFF | [設定]タブの「スケジュールされた開始が行われなかった場合…」を ON |
| ログオンと 08:00 が近いと二重に走る | トリガーが複数あるため | [設定]で「新しいインスタンスを開始しない」。スクリプトは同じ結果に収束するので基本は問題なし |
| タスクは動くが音が切り替わらない(権限っぽい) | 実行ユーザー/特権の設定が合っていない | 「ユーザーがログオンしている場合のみ実行する」を推奨。必要に応じて「最上位の特権で実行する」も試す |
応用:より“自動感”を高めるトリガー設計
「ログオン時+08:00」だけだと、ログオンしたまま日中→夜に移行しても自動で夜設定になりません。より狙いどおりの体験に寄せるなら、次のようにトリガーを増やすのが効果的です。
- 毎日 08:00(昼開始)
- 毎日 20:00(夜開始)
- ログオン時(途中参加の補正)
この 3 点セットにしておけば、
- 朝ログオンしっぱなしでも 08:00 にスピーカーへ
- 夜まで作業しても 20:00 にヘッドホンへ
- 昼間に PC を起動したらログオン時に即スピーカーへ
- 夜に PC を起動したらログオン時にヘッドホンへ
という形で、昼夜切替が自然に回るようになります。
まとめ(最短で安定させる設計)
- タスク スケジューラ単体で「ログオン時+08:00〜20:00 の間だけ実行」を素直に作るのは難しい
- 「スケジュールされた開始が行われなかった場合、できるだけ早くタスクを実行する」を使うと、08:00 以降の起動・ログオンでも追いかけ実行できる
- 時間帯の判定は PowerShell に寄せ、NirCmd で出力デバイスを切り替えると、構成がシンプルで壊れにくい
- 昼夜切替を完成させるなら「08:00 と 20:00 の定時トリガー+ログオン」を組み合わせると体験が安定する

コメント