
かつて山市良と呼ばれたおじさんのブログ
セイテクエンジニアのブログ かつて山市良と呼ばれたおじさんのブログ vol.131 Defenderの定義の更新も自動化したい|どうする!?残る閉域網の更新管理(6)
2025年08月25日配信
2025年08月25日更新
執筆者:山内 和朗
共有フォルダーを利用した、閉域網(クローズドネットワーク)内のサーバーの更新管理環境を自作し、数か月運用してきましたが、更新プログラムのファイルサーバーへのコピー作業という手間はかかるものの、それ以外は自動化でき、期待通りに動作しています。しかし、そういえばMicrosoft Defenderウイルス対策の定義ファイルが更新されていないことに気付きました。
[getmpamfe.ps1](プレーンテキストで表示)
ログのパス($LogPath)と、「mpam-fe.exe」のダウンロード先のパスは適宜変更してください。
function Write-Log {
param (
[string]$Message,
[string]$LogPath = "$env:TEMP\getmpamfe.log"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$entry = "[$timestamp] $Message"
Add-Content -Path $LogPath -Value $entry
}
$LogPath = "E:\work\WUPackages\logs\getmpamfe.log"
Write-Log -Message "Downloading the latest mpam-fe.exe..." -LogPath $LogPath
$mpamfeCurrent = "E:\Work\WUPackages\Defender\mpam-fe.exe"
$mpamfeTemp = "$env:TEMP\mpam-fe.exe"
Invoke-WebRequest -uri "https://go.microsoft.com/fwlink/?LinkID=121721&arch=x64" -outfile $mpamfeTemp -UseBasicParsing
$newSigVer = [version](Get-ItemProperty $mpamfeTemp).VersionInfo.ProductVersion
if (Test-Path $mpamfeCurrent) {
$currentSigVer = [version](Get-ItemProperty $mpamfeCurrent).VersionInfo.ProductVersion
if ($newSigVer -gt $currentSigVer) {
Remove-Item $mpamfeCurrent -Force
Move-Item -Path $mpamfeTemp -Destination $mpamfeCurrent
Write-Log -Message "Updated to the latest mpam-fe.exe(ver: $newSigVer)." -LogPath $LogPath
} else {
Remove-Item $mpamfeTemp -Force
Write-Log -Message "Current mpam-fe.exe(ver: $currentSigVer) is up-to-date." -LogPath $LogPath
}
} else {
Move-Item -Path $mpamfeTemp -Destination $mpamfeCurrent
Write-Log -Message "Downloaded to the latest mpam-fe.exe(ver: $newSigVer)." -LogPath $LogPath
}
次のPowerShellスクリプト「sigupdate.ps1」は、共有フォルダー上の指定したパスを参照し、「mpam-fe.exe」が存在すれば、そのファイルのプロパティの製品バージョンと、現在インストールされている定義ファイルのバージョンを比較し、「mpam-fe.exe」のほうが新しいバージョンであれば実行して最新の定義をインストールします。バージョンチェックしてからインストールするかどうかを判断しているため、スクリプトを繰り返し実行した場合でも、同じ定義がインストールされることはありません(画面4)。このスクリプトのポイントは、共有フォルダーのUNCパスは信頼できない場所(例: IPアドレス指定はインターネットゾーン)として判断され、直接実行するとWindows Defender SmartScreenなどのセキュリティ機能でブロックされる可能性があるため、一時フォルダーにコピーしてから実行することです。また、インストールが完了し、更新されたことを確認するために、Start-Process -Waitで実行が終わるまで待機しているところもポイントです。
画面4 「mpam-fe.exe」が存在するUNCパスを-PackageDirに、ログ出力先を-LogDirに指定して実行することで、最新の定義をインストールする
更新対象のサーバーのタスクスケジューラに、「powershell.exe <パス>¥sigupdate.ps1」を定期的に実行するようにタスクを登録すれば、共有フォルダー上に最新の「mpam-fe.exe」を自動的にインストールできます(画面5)。なお、タスクは、ビルトインAdministratorなどの管理者の権限で、ログオンしているかどうかに関係なく実行するように構成します(ネットワーク共有に接続するためSYSTEMは不可)。
画面5 「posershell.exe <パス>¥sigupdate.ps1」を定期的に実行するように更新対象のサーバーのタスクスケジューラにタスクを登録する
[sigupdate.ps1](プレーンテキストで表示)
Param($PackageDir, $LogDir)
if ($PSBoundParameters.Count -ne 2) { Write-host "Error: -PackageDir <path> -LogDir <Path>" ;exit 1}
If ( -not (Test-Path $packagedir)) { Write-host "Error: -PackageDir <path> does not exist." ;exit 1}
If ( -not (Test-Path $LogDir)) { Write-host "Error: -LogDir <path> does not exist." ;exit 1}
function Write-Log {
param (
[string]$Message,
[string]$LogPath = "$env:TEMP\sigupdate.log"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$entry = "[$timestamp] $Message"
Add-Content -Path $LogPath -Value $entry
}
$LogPath = "$LogDir\$(hostname)_sigupdate.log"
if (Test-Path $logPath) {
$logTime = (get-item $logPath).LastWriteTime
} else {
$logTime = get-Date("1900/1/1")
}
Write-Log -Message "Start sigupdate.ps1" -LogPath $LogPath
$package = (Get-ChildItem -Path $packagedir| where {$_.name -eq "mpam-fe.exe"} | Sort Name | %{$_.FullName})
$currentSigVer = [version](Get-MpComputerStatus).AntivirusSignatureVersion
$success = $true
if ($package.Count -gt 0){
$newSigVer = [version](Get-ItemProperty $package).VersionInfo.ProductVersion
if ($newSigVer -gt $currentSigVer) {
$outmsg = "Signature Update is starting... "
$outmsg = $outmsg + "`nCurrent Signature Version: $currentSigVer"
$outmsg = $outmsg + "`nNew Signature Version: $newSigVer"
Write-Output $outmsg
Write-Log -Message $outmsg -LogPath $LogPath
Copy-Item $package -Destination "$env:TEMP\" -Force
Start-Process "$env:TEMP\mpam-fe.exe" -Wait
if (!($LASTEXITCODE -eq 0)) {
$success = $false
$package = "+ " + (Get-Item $package).Name + ": Failed"
} else {
$package = "+ " + (Get-Item $package).Name + ": Success"
}
Write-Output $package
Write-Log -Message $package -LogPath $LogPath
$outmsg = "Current Microsoft Defender Security intelligence:"
$outmsg = $outmsg + "`nVersion: $((Get-MpComputerStatus).AntivirusSignatureVersion)"
$outmsg = $outmsg + "`nEngine Version: $((Get-MpComputerStatus).AMEngineVersion)"
$outmsg = $outmsg + "`nPlatform Version: $((Get-MpComputerStatus).AMProductVersion)"
$outmsg = $outmsg + "`nLast Updated: $((Get-MpComputerStatus).AntivirusSignatureLastUpdated )"
Write-Output $outmsg
Write-Log -Message $outmsg -LogPath $LogPath
} else {
$outmsg = "No update."
Write-Output $outmsg
Write-Log -Message $outmsg -LogPath $LogPath
exit 0
}
}
exit 0
6月の更新は、この連載シリーズの方法で問題なく完了しました。今後、数か月、この方法で1台のマシンの更新管理を運用してみますが、ひとまずこの連載シリーズは完結です。
「どうする!?残る閉域網の更新管理」連載シリーズの目次
この連載で作成したスクリプトとその配置については、左の図を参照して下さい。 |