かつて山市良と呼ばれたおじさんのブログ

セイテクエンジニアのブログ  かつて山市良と呼ばれたおじさんのブログ  vol.213 やっぱりタスクからメール通知したい ― 廃止された通知機能と現実的な代替策|セイテク・シス管道場(Web)

 

 

vol.213 やっぱりタスクからメール通知したい ― 廃止された通知機能と現実的な代替策|セイテク・シス管道場(Web)

2026年06月25日配信
執筆者:山内 和朗

 「セイテク・シス管道場(Web)」では、Windows Serverの要素技術やシステム管理の基本的な部分に焦点を当ててきました。前回からまだ説明していなかったタスクスケジューラとタスクについて掘り下げています。

 

10年以上前にタスクスケジューラ2.0で廃止された3つの機能

 

 現在のWindows ServerおよびWindowsに搭載されているタスクスケジューラは「タスクスケジューラ2.0」と呼ばれるもので、Windows VistaおよびWindows Server 2008で初めて導入されたものです。それ以前、Windows Server 2003 R2やWindows XPの「タスクスケジューラ1.0」(機能名は「タスク」)と区別されます。タスクスケジューラ2.0では、2012年リリースのWindows 8およびWindows Server 2012のときに3つの機能が廃止されました。それは、メッセージの表示と電子メールの送信の2つのアクション、およびATコマンドです。

タスク スケジューラの新機能 > Windows 8(タスク スケジューラ2.0の変更)|Windowsアプリ開発(Microsoft Learn)

 ATコマンドは、schtasks.exeという、より高機能な標準コマンドがもともとあるため、当時、廃止されても問題はなかったと思います。現在のWindowsでも、ATコマンドを実行すると“この AT コマンドは廃止されました。代わりに schtasks.exe を使用してください。”と分かりやすく案内してくれるので悩むことはないでしょう。

 

 メッセージの表示と電子メールの送信の廃止については、代替の方法が必要でした。これらのアクションが廃止されて以降も、タスクには「メッセージの表示(非推奨)」と「電子メールの送信(非推奨)」は存在し続けていますが、この“非推奨”は今となっては“廃止予定だから使わないほうがいい”というものではなく、Windows 8およびWindows Server 2012から利用できなくなっています。そのため、これらのアクションを設定しても、タスクの設定保存時にエラーが表示されます(画面1、画面2)。

 

画面1 「メッセージの表示(非推奨)」と「電子メールの送信(非推奨)」は、非推奨ではなく廃止
画面1 「メッセージの表示(非推奨)」と「電子メールの送信(非推奨)」は、非推奨ではなく廃止

 

画面2 「メッセージの表示(非推奨)」と「電子メールの送信(非推奨)」を設定してもエラーになる
画面2 「メッセージの表示(非推奨)」と「電子メールの送信(非推奨)」を設定してもエラーになる


 メッセージの表示と電子メールの表示アクションは、タスクスケジューラ2.0の新機能として登場した機能でした。これらのアクションは、初期のタスクエンジン(taskeng.exe)*1に実装された機能です。しかし、メッセージの表示については、Windows Vistaにおけるセッション0の分離(サービスは常にセッション0、ユーザーはセッション1以降)の影響を最初からもろに受け*2、「ユーザーがログオンしているかどうかにかかわらず実行する」(タスクはセッション0で実行)オプションでメッセージを表示できないという制限がありました。
*1 現在のsvchost.exe(Scheduleサービス)またはtaskhostw.exeでプログラムが実行されます。
*2 Windows Vistaでは、セッション0分離の互換性対策としてUI0Detectサービス(対話型サービスの検出)が追加されましたが(タスクスケジューラでは利用されたことはありません)、高い権限を持つサービスがUIを出す仕様はセキュリティリスクになるため、Windows 8で既定で無効化され、Windows 10の設計変更の影響で正常に動作しなくなったこともあって、Windows 10(Creators Update)で削除されました(参考: 旧ブログ記事)。

 Windows 7およびWindows Server 2008 R2まで利用できていた電子メールの送信アクションは、宛先、件名、本文、添付ファイルと、SMTPサーバー(:ポート)を指定できるだけの簡単なものでした。当時、既に実際のインターネットメール環境はセキュリティ面が厳格化(TLS、SMTP AUTH、リレー制限など)されており、廃止される以前から実用に耐えない機能でした。

 

 使えないアクションがタスクスケジューラのMMCスナップインに“非推奨”として残っていることに疑問を持たれる人がいるかもしれませんが、これらのアクションが廃止される以前のWindows 7以前やWindows Server 2008 R2以前のコンピューターにこのMMCスナップインをリモート接続すれば、“非推奨”を無視してメッセージの送信や電子メールの送信タスクを設定、保存、そして実行することができました。当時は、これらのOSにアクションを設定してもアップグレード後に使えなくなるので“非推奨”とラベル付けされたわけです。でも、それらのレガシOSはとうの昔にライフサイクルサポートが終了*3しているため、残されていることにもう意味はありません。

*3 Windows 7は2011年2月(3年目のESUは2023年1月)、Windows Server 2008/2008 R2は2011年2月(Azureでの4年目のESUは2024年1月)に終了。

 

メッセージの表示はMsg.exeコマンドで代替可能

 

 メッセージの表示が廃止されたとき、Microsoftが示した代替策はWindows Script Host(WSH)のMsgBox関数(例: MsgBox "メッセージ", 0, "タイトル")の利用でしたが、MsgBox関数もまたセッション0分離の影響を受けます。より適切な代替策は、「Msg.exe」コマンドです。このコマンドは、リモートデスクトップセッションのユーザー(/serverを指定しない場合はローカルコンピューター上のユーザー、*はすべてのログオンユーザー)に対してメッセージを表示するもので、セッション0分離の影響を受けません。タスクの「プログラム/スクリプト」に「Msg(.exe)」、「追加の引数」に「* メッセージ」と入力すれば、そのシステムのすべてのログオンユーザーにメッセージを表示することができます(画面3)。Msgコマンドは既定で60秒後にメッセージを閉じます。表示時間(秒)は/time:パラメーターで調整できます。

 

 Msg * メッセージ
Msg * /time:90 メッセージ

※メッセージに空白を含む場合でもダブルコーテーション("")は任意です。Msgコマンドのパラメーターをメッセージより後ろに指定すると、メッセージの文字列として扱われるので注意してください。

画面3 廃止された「メッセージの表示(非推奨)」の代替は、Msgコマンドで
画面3 廃止された「メッセージの表示(非推奨)」の代替は、Msgコマンドで

 前回の記事(vol.212)では、パフォーマンスモニターのデータコレクターセットからタスクを起動して、実行コマンドの引数($(Arg0))にパフォーマンスカウンターの値を含むテキストメッセージを渡すという、少し珍しいメッセージの表示方法を紹介しました。

 

電子メールの送信の代替はMicrosoft GraphまたはMailKitに変化

 
 電子メールの送信アクションが廃止された当時、代替策としては、Windows PowerShellのSend-MailMessageが示されました。アプリ開発者向けには、.NET Frameworkや.NETのSmtpClientクラスを使用する方法がありました。しかし、以下のドキュメントで記されているように、これらの方法は現在では非推奨です。これらの方法は既に時代遅れとなった古いSMTP環境向けに設計されたもので、例えばOAuth2などのモダン認証を必要とするMicrosoft 365やGmailなど、現代のSMTP環境には対応できません。

Send-MailMessage|PowerShell(Microsoft Learn)
SmtpClientクラス|.NET(Microsoft Learn)

 Microsoftは、Microsoft 365のメール(Exchange Online)で現在、モダン認証に対応したMicrosofft Graph APIを使用したメール送信を推奨しています。SmtpClientクラスを使用していたアプリ開発者向けには、オープンソースの.NETライブラリである「MailKit」を推奨しています。

Microsoft Graph のメール送信プロセスの概要|Microsoft Graph(Microsoft Learn)
jstedfast/MailKit(github.com)

 Microsoft GraphのREST APIを使用したメール送信の例として、Microsoft 365のメールボックスから任意の宛先にメールを送信するPowerShellスクリプト「msgsendbygraphapi.ps1」を用意しました。このスクリプトに次のように引数を指定して実行することで、メール送信が可能です。なお、宛先メールアドレスを省略した場合は、スクリプト内に設定した既定のメールアドレス宛て(この例ではtoaddr@dummy.test)に送信します。なお、CC指定はスクリプトの中に記述することで対応可能です($cc = "メールアドレス1","メールアドレス2")。

.\msgsendbygrahapi.ps1 -msgsub "件名" -msgbody "本文" -msgto "宛先メールアドレス"
または
.\msgsendbygrahapi.ps1 "件名" "本文" "宛先メールアドレス" 

 

[msgsendbygraphapi.ps1]プレーンテキストで表示、ダウンロード)
# ===== パラメーター =====
# Usage:
# .\msgsendbygrahapi.ps1 -msgsubj "TITLE" -msgbody "BODY" -msgto "toaddr@dummy.test"
# .\msgsendbygrahapi.ps1 "TITLE" "BODY" "toaddr@dummy.test"
# .\msgsendbygrahapi.ps1 "TITLE" "BODY"
param (
  [string]$msgsubj = "[Graph API] メッセージのタイトルです",
  [string]$msgbody = "[Graph API] メッセージの本文です。",
  #既定の宛先メールアドレス
  [string]$msgto = "toaddr@dummy.test"
)

# ===== テナントとメールアドレスの設定 =====
$TenantId   = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
$ClientId   = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
$ClientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
$from = "yourmailbox@dummy.test"
$to   = $msgto
#$cc   = "ccaddr1@dummy.test","ccaddr2@dummy.test"
$cc = ""

# ===== トークン取得 =====
$tokenBody = @{
  grant_type  = "client_credentials"
  scope   = "https://graph.microsoft.com/.default"
  client_id   = $clientId
  client_secret = $clientSecret
}

$tokenResponse = Invoke-RestMethod `
  -Method Post `
  -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" `
  -Body $tokenBody

$accessToken = $tokenResponse.access_token

# ===== メール作成 =====
$message = @{
  subject = $msgsubj
  body = @{
    contentType = "Text"
    content   = $msgbody
  }
  toRecipients = @(
    @{
    emailAddress = @{
      address = $to
    }
    }
  )
  from = @{
  emailAddress = @{
    address = $from
  }
  }
}
if($cc) {
  if($cc.Count -gt 1) {
  $ccRecipients = foreach ($c in $cc) {
    @{
      emailAddress = @{
        address = $c
      }
     }
  }
  } else {
  $ccRecipients = @(
    @{
      emailAddress = @{
        address = $cc
      }
    }
  )
  }
  $message.ccRecipients = $ccRecipients
}

$mailBody = @{
  message = $message
  saveToSentItems = $true
} | ConvertTo-Json -Depth 5

# ===== 文字化け対策 =====
$mailBody = [System.Text.Encoding]::UTF8.GetBytes($mailBody )

# ===== 送信 =====
$uri = "https://graph.microsoft.com/v1.0/users/$from/sendMail"

$headers = @{
  Authorization = "Bearer $accessToken"
  "Content-Type" = "application/json"
}

Invoke-RestMethod -Method Post -Uri $uri -Headers $headers -Body $mailBody 

Write-Host "メール送信完了"
 
画面4 Microsoft Graph APIを使用したPowerSHellスクリプトによるタスクからのメール送信
画面4 Microsoft Graph APIを使用したPowerSHellスクリプトによるタスクからのメール送信

 このスクリプトを利用するには、Microsoft Entraにアプリ(サービスプリンシパル)を登録し、クライアントシークレットの作成と、メール送信のためのMicrosoft Graph APIの許可および組織による同意が必要です。その上で、スクリプト内の以下の変数を設定します。

$TenantId = "ディレクトリ(テナント)ID"
$ClientId  = "アプリケーション(クライアント)ID"
$ClientSecret = "クライアントシークレット"$from = "送信元メールアドレス(Microsoft 365メールのメールボックス)"
$msgto = "既定の送信先メールアドレス"

 

 アプリを登録するには、Microsoft Entra管理センターで「Entra ID」の「アプリの登録」でアプリを作成します(画面5)。「ディレクトリ(テナント)ID」と「アプリケーション(クライアント)ID」は登録したアプリの概要ページからコピーできます(画面6)。「証明書とシークレット」で新しいクライアントシークレットを作成すると、作成直後に「クライアントシークレット」をコピーできます(画面7)。さらに、「APIのアクセス許可」で、「Microsoft Graph」、「アプリケーションの許可」を選択し、「Mail.Send」のアクセス許可を追加します(画面8)。APIへのアクセス許可を追加したら、最後に「・・・に管理者の同意を与えます」をクリックして、管理者の同意を付与します(画面9)。
 
参考: Microsoft Entra管理センターでのアプリ(サービスプリンシパル)の準備

画面5(クリックで拡大)
画面5(クリックで拡大) 

vol212_scr06
画面6(クリックで拡大) 
画面7(クリックで拡大) 
画面7(クリックで拡大) 
画面8(クリックで拡大) 
画面8(クリックで拡大) 
画面9(クリックで拡大)
画面9(クリックで拡大)
 

 

 なお、Microsoft 365以外のメールを利用する場合は、ケースバイケースなので省略します。パスワードやアプリパスワードによるSMTP AUTHをサポートしているなら、従来のSmtpClientまたはMailKit、APIが用意されている場合はAPI(Gmail APIなど)を利用することになるでしょう。

参考:
メール メッセージを作成して送信する|Gmail(Google for Developers)

 セイテク・シス管道場(Web) (1) |・・・|(10)(11)(12)(13)(14)(15)(16)(17)(18)(19)(20)|(21)  

blog_yamanxworld_subscribe

blog_yamanxworld_comment

blog_yamanxworld_WP_ws2025

最新記事