PowerShell をタスクスケジューラで定期実行する方法|ExecutionPolicy の回避と設定手順

  • URLをコピーしました!
目次

はじめに

PowerShell で作成したスクリプトは、手動で実行している限り、その都度の操作が必要になります。決まった時刻や起動時に自動で動かせれば、実行漏れを防ぎ、定型作業を任せられます。これを実現するのが、Windows 標準の「タスクスケジューラ」との連携です。

ただし、タスクスケジューラに PowerShell スクリプト(.ps1 ファイル)を登録しても、そのままでは動かないことがよくあります。多くの場合、原因は Windows のセキュリティ機能である実行ポリシー(ExecutionPolicy)によるブロックです。

本記事では、PowerShell スクリプトをタスクスケジューラで定期実行する手順を、つまずきやすいポイントとあわせて解説します。

この記事でわかること
  • タスクスケジューラで PowerShell を実行する基本の手順と引数の指定方法
  • 多くの人がつまずく実行ポリシー(ExecutionPolicy)を引数で回避する方法
  • ログオン状態と GUI 表示の関係など、無人実行で押さえておく制約
  • スクリプトが動かないときに確認するチェックリスト

結論を先に述べると、タスクスケジューラから PowerShell を呼び出す際に、実行する .ps1 を直接指定するのではなく、powershell.exe(PowerShell 7 の場合は pwsh.exe)をプログラムに指定し、引数で -ExecutionPolicy Bypass -File "スクリプトのパス" を渡すのが基本です。これにより、システム全体のポリシーを変更せずに、そのタスクの実行時だけ制限を回避できます。なお、メッセージボックスのような GUI を表示するスクリプトには、ログオン状態に関する制約があります。この点は後半で扱います。

なぜタスクスケジューラで PowerShell を実行するのか

タスクスケジューラは、指定した条件(トリガー)に応じてプログラムを自動起動する Windows 標準の機能です。PowerShell と組み合わせることで、次の利点があります。

ひとつは、定期実行を任せられることです。「毎日 18 時」「パソコン起動時」といった条件で、人手を介さずに処理を実行できます。もうひとつは、追加ソフトが不要なことです。Windows 標準機能だけで完結するため、フリーソフトを導入しにくい環境でも、業務自動化の手段として利用できます。

Linux や Mac の cron に相当する仕組みを、Windows では標準でタスクスケジューラが担います。複数 OS をまたいだ定期実行の考え方は、関連記事『Python で業務を自動化する方法』でも整理しています。

実行ポリシー(ExecutionPolicy)と引数での回避

タスクスケジューラに .ps1 を登録して実行しても動かない場合、まず疑うべきが実行ポリシーです。

実行ポリシーとは

実行ポリシーは、意図しないスクリプトの実行を防ぐための PowerShell の設定です。Windows クライアントの初期値は Restricted(スクリプトの実行を許可しない)で、この状態では .ps1 を直接実行できません。なお、実行ポリシーはユーザーの操作を制限するセキュリティ境界ではなく、スクリプトの意図しない実行を防ぐための仕組みと位置づけられています。コマンドを直接入力すれば回避できるため、厳密なアクセス制御の手段ではありません。

引数で Bypass を指定する

この制限を回避するために、システム全体の実行ポリシーを恒久的に変更する必要はありません。タスクスケジューラから PowerShell を呼び出す際の引数で、そのタスクの実行時だけ実行ポリシーを Bypass に指定します。

スケジュールタスクは、制限的なマシンポリシーを引き継いだ新しいプロセスで動くことがあります。そのため、マシン全体のポリシーを緩めるのではなく、タスクの引数で直接 -ExecutionPolicy Bypass を渡す方法が、影響範囲を限定できる安全な方法です。

参考: about_Execution_Policies(Microsoft Learn)
“Bypass: Nothing is blocked and there are no warnings or prompts.”
(Bypass: 何もブロックされず、警告も確認もありません。)
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies

具体的な引数の指定は、次の登録手順で詳しく扱います。

タスクスケジューラへの登録手順

作成した PowerShell スクリプトを、タスクスケジューラに登録します。ここで、前述の実行ポリシーの回避を引数で設定します。

基本タスクの作成とトリガー設定

  1. スタートメニューで「タスクスケジューラ」を検索して起動します。
  2. 右側の「操作」メニューから「基本タスクの作成」を選択します。
  3. 任意のタスク名(例: PowerShell 定期実行)を入力し、「次へ」をクリックします。
  4. トリガー(実行タイミング)を選択します。たとえば「毎日」を選び、開始する日付と時刻(例: 18:00:00)を設定します。

プログラムと引数の指定

「操作」で「プログラムの開始」を選択し、次のように入力します。ここが実行ポリシー回避の要になります。

  • プログラム/スクリプト: powershell.exe(PowerShell 7 を使う場合は pwsh.exe
  • 引数の追加: -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\Sample.ps1"

ファイルパスは、スクリプトを保存した実際のフルパスに置き換えます。パスにスペースが含まれる場合は、ダブルクォーテーションで囲みます。

引数の意味は次のとおりです。

引数役割
-NoProfileプロファイルの読み込みを省略し、起動を速く・予測可能にする
-ExecutionPolicy Bypassこのプロセスの実行時だけ、実行ポリシーの制限を回避する
-File "パス"実行する .ps1 ファイルのフルパスを指定する

無人で実行する処理では、これに加えて -NonInteractive(対話的な入力を求めない)や -WindowStyle Hidden(コンソールウィンドウを隠す)を付けると、画面に何も出さずに動かせます。ただし、後述する GUI 表示を伴うスクリプトでは、これらの指定が表示を妨げることがあるため、用途に応じて選びます。

ログオン状態の選択(重要)

タスクのプロパティの「全般」タブには、実行のしかたを決める重要な設定があります。

  • ユーザーがログオンしているときのみ実行する
  • ユーザーがログオンしているかどうかにかかわらず実行する

「ログオンしているかどうかにかかわらず実行する」を選ぶと、サインインしていない状態でも処理が動くため、無人運用に向きます。ただし、この設定ではスクリプトが非対話セッションで動作するため、メッセージボックスなどの GUI は画面に表示されません。GUI を表示したい場合は「ユーザーがログオンしているときのみ実行する」を選ぶ必要があります。管理者権限が必要な処理では、「最上位の特権で実行する」も合わせて有効にします。

参考: Run PowerShell Scripts on a Schedule with Task Scheduler(Windows OS Hub)
“To run the script in the PowerShell Core environment, run pwsh.exe instead of powershell.exe.”
(PowerShell Core 環境でスクリプトを実行するには、powershell.exe ではなく pwsh.exe を実行します。)
https://woshub.com/run-powershell-script-task-scheduler/

登録前の動作確認

登録する前に、同じコマンドを手動で実行し、エラーが出ないかを確認しておくと安全です。コマンドプロンプトや PowerShell で、次のように実行します。

powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\Sample.ps1"

手動で正しく動くことを確認してからタスクに登録すると、原因の切り分けが容易になります。

応用例: 自動サインアウトスクリプト

ここまでの手順を使う応用例として、指定時刻にサインアウトを促すスクリプトを作成します。終業時刻の離席対策などに利用できます。

スクリプトの内容

実行すると確認のメッセージボックスを表示し、「OK」が押されたら 60 秒後にサインアウト(ログオフ)します。「キャンセル」では何もしません。

# 自動サインアウトのサンプル
Add-Type -AssemblyName PresentationFramework

function Show-MessageBox ($message, $title) {
    $button = [System.Windows.MessageBoxButton]::OKCancel
    $image  = [System.Windows.MessageBoxImage]::Warning
    return [System.Windows.MessageBox]::Show($message, $title, $button, $image)
}

$message = "1 分後にサインアウトします。よろしいですか?"
$title   = "サインアウトのお知らせ"
$result  = Show-MessageBox -message $message -title $title

# OK が押されたら 60 秒後にサインアウト
if ($result -eq "OK") {
    Start-Sleep -Seconds 60
    shutdown.exe /l
}

冒頭の Add-Type -AssemblyName PresentationFramework は、GUI のメッセージボックスを使うための宣言です。shutdown.exe /l/l は、ログオフ(サインアウト)を指定するオプションです。ユーザーが「OK」を押した場合のみ、-eq による条件分岐の中の処理が実行されます。

スクリプトの保存

メモ帳などでコードを貼り付け、AutoSignout.ps1 のように拡張子 .ps1 で保存します。メッセージの日本語が文字化けしないよう、文字コードは UTF-8 を選びます。保存先のフルパス(例: C:\Scripts\AutoSignout.ps1)を、タスク登録時の -File に指定します。文字コードでつまずいた場合は、関連記事『Python の SyntaxError: Non-UTF-8 code starting with を解決』の文字コードの考え方も参考になります。

この例の重要な制約

このスクリプトはメッセージボックス(GUI)を表示するため、前述のとおり「ユーザーがログオンしているときのみ実行する」設定で登録する必要があります。「ログオンしているかどうかにかかわらず実行する」を選ぶと、非対話セッションで動作してメッセージボックスが表示されず、ユーザーの確認を得られないまま意図しない挙動になる可能性があります。GUI を伴うスクリプトと無人実行は相性が悪い、という点を理解しておくことが重要です。

スクリプトが動かないときのチェックリスト

タスクスケジューラに登録した PowerShell スクリプトが動かない場合、原因はいくつかのパターンに分かれます。手動では動くのにタスクからは動かない、というケースが典型です。次の順に確認すると、原因を切り分けやすくなります。

実行ポリシーを引数で回避しているか

最初に確認するのが、前述の実行ポリシーです。プログラムに powershell.exe を指定し、引数に -ExecutionPolicy Bypass を含めているかを確認します。.ps1 を直接プログラムに指定していると、実行ポリシーでブロックされることがあります。

パスが絶対パスになっているか

タスクスケジューラは、対話シェルとは異なる環境で動きます。スクリプトのパスや、スクリプト内で読み書きするファイルのパスは、相対パスではなく絶対パスで指定します。必要に応じて、タスクのアクション設定の「開始(ディレクトリ)」に作業フォルダを指定すると、相対パスの基準が安定します。

実行アカウントと権限が適切か

タスクを実行するアカウントには、適切な権限が必要です。「ユーザーがログオンしているかどうかにかかわらず実行する」で動かす場合、実行アカウントに「バッチ ジョブとしてログオン」の権限が必要になることがあります。管理者権限を要する処理では、「最上位の特権で実行する」を有効にします。

アカウントのパスワード変更に注意

「ログオンしているかどうかにかかわらず実行する」設定では、実行アカウントの資格情報が保存されます。アカウントのパスワードを変更・期限切れにすると、保存された資格情報と食い違い、タスクが失敗します。パスワード変更後は、タスクの資格情報を更新します。

ログオン状態と GUI の不一致がないか

メッセージボックスなどの GUI を表示するスクリプトを「ログオンしているかどうかにかかわらず実行する」で登録していないかを確認します。この組み合わせでは GUI が表示されず、処理が進まないように見えます。GUI を伴う場合は「ログオンしているときのみ実行する」を選びます。

ログを出力して原因を確認する

無人実行では画面にエラーが出ないため、ログを残すと原因を追いやすくなります。スクリプトの出力をファイルにリダイレクトしておくと、失敗時の手がかりになります。

powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\Sample.ps1" >> "C:\Scripts\log.txt" 2>&1

また、タスクスケジューラの「履歴」タブや、タスクの「前回の実行結果」に表示される結果コードも、原因の特定に役立ちます。

参考: How to Run PowerShell Script from Task Scheduler(Netwrix)
“Consider how environment variables, paths or permissions might differ in the two situations.”
(2 つの状況で、環境変数・パス・権限がどう異なるかを考慮します。)
https://netwrix.com/en/resources/blog/how-to-automate-powershell-scripts-with-task-scheduler/

まとめ

本記事では、PowerShell スクリプトをタスクスケジューラで定期実行する手順を、つまずきやすいポイントとあわせて解説しました。実行ポリシーの回避と、無人実行で押さえておく制約が要点です。

  • タスクスケジューラは Windows 標準の定期実行の仕組み
  • 実行する .ps1 は直接指定せず powershell.exe の引数で渡す
  • 実行ポリシーは引数の -ExecutionPolicy Bypass で回避する
  • PowerShell 7 を使う場合はプログラムに pwsh.exe を指定
  • 無人実行では非対話セッションのため GUI は表示されない
  • 動かないときはパス・権限・資格情報・ログを確認する
  • 登録前に同じコマンドを手動で実行して動作を確認する

Windows のタスクスケジューラは、Linux や Mac の cron に相当する定期実行の手段です。複数 OS をまたいだ自動化の全体像は、関連記事『Python で業務を自動化する方法』で整理しています。

以上、最後までお読みいただきありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

関西を拠点に活動する、現役インフラエンジニア。経験20年超。

大手通信キャリアにて、中〜大規模インフラ(ネットワーク・サーバ・クラウド・セキュリティ)の設計・構築およびプロジェクトマネジメントに従事。現場で直面した技術課題への対処や、最新の脆弱性情報への実務対応を、一次情報として発信しています。

保有資格
CCIE Lifetime Emeritus(取得から20年以上)/ VCAP-DCA / Azure Solutions Architect Expert

▶ 運営者プロフィール(詳細)

目次