PowerShellで複数サーバーのOS情報・PSビルド取得時にRPC server is unavailable(0x800706BA)を解決する方法

複数のWindows ServerからOS情報とPowerShellのビルド番号を一括取得しようとすると、Get-WmiObjectで「The RPC server is unavailable (0x800706BA)」が出て止まることがあります。本記事ではCSVの読み方とExport-Csvの出力作法を正したうえで、RPC/WMI/WinRMの切り分けと安定化のコツを実務目線で整理します。

目次

やりたいことと、つまずきやすいポイント

サーバー台数が増えてくると、運用台帳や監査対応のために「複数サーバーのOS情報(WMI)」「PowerShellのビルド番号」を一括で集めたくなります。典型的には次のような流れです。

  • サーバー一覧(CSVまたはテキスト)を読み込む
  • 各サーバーへ問い合わせて、OS情報(例:Win32_OperatingSystem)を取得する
  • 同じサーバーから $PSVersionTable.PSVersion.Build を取得する
  • 結果をCSVにまとめる

ところが、実務では次の2系統の問題が絡み合ってハマりがちです。

  • スクリプト側の問題:CSVの読み方が曖昧、ヘッダー行をホスト名として扱ってしまう、Export-Csvに出力データを渡していない
  • 環境側の問題:WMIはRPC/DCOM依存のため、到達性・DNS・ファイアウォール・WMI許可が揃っていないと「RPC server is unavailable (0x800706BA)」になりやすい

まずは「スクリプトの形」を正して、次に「通信として通る状態か」を切り分けるのが最短ルートです。

入力が“CSV”か“テキスト”かで、読み方を固定する

最初に決めたいのは、サーバー一覧ファイルの形式です。ここが曖昧だと、ヘッダー行や区切り文字が原因で無駄なエラーが増えます。

ファイル形式例推奨コマンドよくある事故
CSV(ヘッダーあり)ComputerName
SVR01
Import-CsvGet-Contentで回してヘッダー文字列までホスト名扱い
テキスト(1行=1台)SVR01
SVR02
Get-Contentコメント行・空行を拾って余計な接続失敗が増える

CSVのサンプル(おすすめ)

最低限、ホスト名(またはFQDN)を表す列名を1つ決めます。ここでは ComputerName を使います。

ComputerName
SVR01
SVR02
SVR03

列を増やすのも簡単です(部署、役割、備考など)。

ComputerName,Role,Note
SVR01,ADDS,DC1
SVR02,File,NYC
SVR03,Web,IIS

なぜGet-ContentでCSVを回すと失敗しやすいのか

CSVは先頭行がヘッダーであることが多く、Get-Contentでそのままループすると、ヘッダー(例:ComputerName)がホスト名として処理されます。結果として、存在しないホストへ問い合わせてしまい、WMI/RPCの失敗(0x800706BA)を“増やす”要因になります。

Export-Csvで「何も出力されない」原因はほぼこれ

Export-Csvは、出力するオブジェクト(データ)がパイプで渡されて初めてCSVを書きます。パスだけ指定しても、書き出す対象がなければ空のままです。

やりがち結果理由
Export-Csv -Path C:\out.csvほぼ何も出ない出力するオブジェクトを渡していない
$obj | Export-Csv -Path C:\out.csv期待通り出るパイプでオブジェクトを渡している

さらに、ループ内で -Append している場合も、毎回「そのループで作ったオブジェクト」を渡さないと出力されません。実務では、いったん結果を全部オブジェクト化して最後に1回だけExport-Csv する形が安定します(途中で落ちても原因が追いやすく、出力の列ズレも減ります)。

まず動く“型”:WMIでOS情報、Invoke-CommandでPSビルドを取ってCSV化

ここでは、入力がCSV(ヘッダー付き)で、列名が ComputerName である前提のサンプルを紹介します。WMIとWinRM(PowerShell Remoting)は要件が異なるため、両方の成否を列で分けて記録すると切り分けが楽になります。

実用スクリプト(エラーも記録してCSVに残す)

param(
  [string]$ServerListPath = 'C:\servers.csv',
  [string]$OutPath        = 'C:\server_inventory.csv'
)

# サーバー一覧をCSVとして読み込む(ヘッダー行も列として扱える)

$servers = Import-Csv -Path $ServerListPath

$results = foreach ($row in $servers) {
$computer = $row.ComputerName

# ---- WMI: OS情報(RPC/DCOM) ----

$os = $null
$wmiError = $null
try {
$os = Get-WmiObject -ComputerName $computer -Class Win32_OperatingSystem -ErrorAction Stop
} catch {
$wmiError = $_.Exception.Message
}

# ---- WinRM: PowerShellビルド(PowerShell Remoting) ----

$psBuild = $null
$winrmError = $null
try {
$psBuild = Invoke-Command -ComputerName $computer -ScriptBlock {
$PSVersionTable.PSVersion.Build
} -ErrorAction Stop
} catch {
$winrmError = $_.Exception.Message
}

# WMIのLastBootUpTimeはDMTF形式なので、取れたときだけDateTimeに変換

$lastBoot = $null
if ($os -and $os.LastBootUpTime) {
$lastBoot = [Management.ManagementDateTimeConverter]::ToDateTime($os.LastBootUpTime)
}

[pscustomobject]@{
CollectedAt  = (Get-Date)
ComputerName = $computer


OSCaption    = if ($os) { $os.Caption } else { $null }
OSVersion    = if ($os) { $os.Version } else { $null }
OSBuild      = if ($os) { $os.BuildNumber } else { $null }
LastBoot     = $lastBoot

PSBuild      = $psBuild

WMIOk        = [bool]$os
WinRMOk      = ($psBuild -ne $null)

WMIError     = $wmiError
WinRMError   = $winrmError


}
}

# まとめて1回でCSV出力(列が安定し、速度も出やすい)

$results |
Export-Csv -Path $OutPath -NoTypeInformation -Encoding UTF8

このスクリプトが“実務で効く”理由

  • Import-Csvでヘッダー行を正しく処理するため、ヘッダーをホスト名として誤処理しません。
  • 各サーバーについて、WMI(RPC/DCOM)とWinRM(PowerShell Remoting)の成功/失敗を分けて残すので、問題がネットワークなのか、WinRM設定なのかが見えます。
  • 例外(エラー)を握りつぶさず、WMIError / WinRMError に文字列として残すので、あとから原因調査ができます。

入力ファイルが“テキスト”しかない場合の対応

サーバー一覧が「1行=1台」のテキストで、ヘッダーが不要なら、次のように空行・コメント行を除外してから回すと安全です。

$servers = Get-Content -Path 'C:\servers.txt' |
  Where-Object { $_ -and ($_ -notmatch '^\s*#') }

foreach ($computer in $servers) {

# 上のサンプルと同様に処理

}

「RPC server is unavailable (0x800706BA)」を最短で切り分ける

0x800706BA は、スクリプト文法が正しくても起きます。WMI(Get-WmiObject)はRPC/DCOMを使うため、リモート側・ネットワーク側・FW側のどこかが欠けると失敗します。切り分けは「名前解決→疎通→ポート→OS側設定→権限」の順が効率的です。

切り分けチェック表(現場でよく当たる順)

疑う順ありがちな原因確認コマンド例(実行元)対処の方向性
名前解決DNSが引けない / hosts未登録 / 別セグメントで名前が違うResolve-DnsName SVR01
nslookup SVR01
FQDNで統一、DNS登録、台帳の表記揺れを直す
疎通サーバー停止 / ルーティング不可 / ICMP遮断(参考)Test-Connection SVR01 -Count 1停止・隔離・経路の確認(ICMPは通らなくてもWMIが通る場合あり)
RPCエンドポイントTCP 135が遮断Test-NetConnection SVR01 -Port 135ネットワークFWまたはWindows FWで許可
動的ポートRPC/DCOMの動的ポート帯が遮断(環境依存。135だけ開けても失敗する)FW設計の見直し、もしくはWinRM(5985/5986)への切替を検討
Windows FWWMI用受信規則が無効(対象サーバー側)
Get-NetFirewallRule -DisplayGroup 'Windows Management Instrumentation (WMI)'
「Windows Management Instrumentation (WMI-In)」等の有効化(GPO推奨)
サービスRPC / WMIサービス停止、破損(対象サーバー側)
Get-Service RpcSs, Winmgmt
サービス起動、イベントログ確認、WMIリポジトリ調査
権限WMI名前空間権限不足、UACリモート制限(エラーが0x80070005等になることも)実行アカウントを見直す、WMI権限付与、ローカル管理者利用

まず試す“軽い”事前チェック(スクリプトに組み込むと効く)

大量台数に対していきなりWMIを投げると、落ちたときの待ち時間が長くなりがちです。現場では「到達性」「ポート」の簡易チェックを先に入れて、失敗するサーバーを早めに判定すると全体が回りやすくなります。

$computer = 'SVR01'

# DNS/名前解決(失敗したら台帳の表記揺れを疑う)

Resolve-DnsName $computer -ErrorAction SilentlyContinue

# RPCエンドポイント(WMIで最低限必要)

Test-NetConnection $computer -Port 135

# WinRM(Invoke-Commandを使うなら)

Test-WSMan $computer

ここで Test-NetConnection -Port 135 が失敗するなら、WMIはほぼ確実に通りません。逆に135が通っても、動的ポート帯やWindows FWの設定次第でWMIが失敗することがあります。

WMI(RPC/DCOM)とWinRM(WSMan)の違いを理解すると迷いが減る

同じ「リモートで情報を取る」でも、WMIとPowerShell Remotingでは使う仕組みが違います。どちらを“主戦力”にするかを決めると、ネットワーク要件の整理が進みます。

手段代表コマンド通信主なポート向いている場面
WMI(従来)Get-WmiObjectRPC/DCOMTCP 135 + 動的ポート既存運用でWMIが通る、WinRMを有効化できない
CIM(WSMan)Get-CimInstanceWSMan(WinRM)5985/5986FWが厳しい環境、WinRMを統制できる
PowerShell RemotingInvoke-CommandWSMan(WinRM)5985/5986リモートで複合処理(OS情報+PS情報など)をまとめて実行したい

PowerShell 7で実行する場合の注意(Get-WmiObjectが使えない)

管理端末や踏み台でPowerShell 7(pwsh)を使っている場合、Get-WmiObject は標準では利用できません。その場合はCIM系コマンドレット(Get-CimInstance)へ寄せるのが基本です。

ただし、Get-CimInstanceは「どう接続するか」で要件が変わります。RPC/DCOMを使う(=WMIと同系統)のか、WSMan(WinRM)を使うのかを意識して選びます。

# RPC/DCOMでCIM(=WMIと同じく、ネットワーク要件は厳しめ)
$opt = New-CimSessionOption -Protocol Dcom
$cs  = New-CimSession -ComputerName $computer -SessionOption $opt
Get-CimInstance -CimSession $cs -ClassName Win32_OperatingSystem

# WSManでCIM(WinRMが必要。RPCを避けたいならこちらが本命)

Get-CimInstance -ComputerName $computer -ClassName Win32_OperatingSystem

「0x800706BAを避けたい」目的なら、単にGet-WmiObjectをGet-CimInstanceに置き換えるだけでは解決しないことがあります。RPC/DCOMの経路を使っていないか、またはWinRMを使う設計にできないかを合わせて確認するのがポイントです。

「WMIがネットワーク的に厳しい」環境では、WinRM/WSManに寄せると、開けるポートが固定化できて運用が楽になるケースが多いです(もちろん、WinRMを有効にするための社内ルール・監査要件は別途確認が必要です)。

安定化の定石:WinRMでリモート実行し、サーバー“内部”でOS情報も取る

「WMIが通らない(0x800706BA)けれど、WinRMは許可できる」なら、OS情報の取得を“リモートWMI”ではなくリモートセッション内でのローカル取得に寄せるのが効果的です。つまり、管理端末→サーバーへの通信はWinRMだけにして、サーバー側でGet-CimInstanceを実行します。

WinRM一本化サンプル(OS情報+PSビルドを1回の接続で取得)

param(
  [string]$ServerListPath = 'C:\servers.csv',
  [string]$OutPath        = 'C:\server_inventory_winrm.csv'
)

$servers = Import-Csv -Path $ServerListPath

$results = foreach ($row in $servers) {
$computer = $row.ComputerName

try {
Invoke-Command -ComputerName $computer -ErrorAction Stop -ScriptBlock {
$os = Get-CimInstance -ClassName Win32_OperatingSystem


  [pscustomobject]@{
    CollectedAt  = (Get-Date)
    ComputerName = $env:COMPUTERNAME

    OSCaption    = $os.Caption
    OSVersion    = $os.Version
    OSBuild      = $os.BuildNumber
    LastBoot     = $os.LastBootUpTime

    PSBuild      = $PSVersionTable.PSVersion.Build
  }
}


} catch {
[pscustomobject]@{
CollectedAt  = (Get-Date)
ComputerName = $computer


  OSCaption    = $null
  OSVersion    = $null
  OSBuild      = $null
  LastBoot     = $null
  PSBuild      = $null

  Error        = $_.Exception.Message
}


}
}

$results |
Export-Csv -Path $OutPath -NoTypeInformation -Encoding UTF8

WinRM一本化が向く/向かない判断基準

  • 向く:ネットワークFWが厳しく、動的ポートを開けられない/GPOでWinRMを統制できる/対象台数が多い
  • 向かない:WinRMが原則禁止/サーバーが古くWinRM設定が困難/ドメイン外や認証要件が複雑

Import-CsvのDelimiterエラーを確実に直す

Import-Csv : Cannot bind parameter 'Delimiter'... "String must be exactly one character long." は、ほぼ例外なく「-Delimiterに1文字以外を渡している」のが原因です。パスを渡す場所を間違えるケースが非常に多いので、コマンドを分解して確認します。

例判定理由
Import-Csv -Delimiter "C:\servers.csv"NG-Delimiterは区切り文字(1文字)用。パスを渡している
Import-Csv -Path "C:\servers.csv"OKパスは-Pathに渡す(既定区切りはカンマ)
Import-Csv -Path "C:\servers.csv" -Delimiter ";"OK区切りがセミコロンのCSVなら1文字で指定

「CSVのはずなのに列が1列に潰れる」場合は、区切り文字がカンマではない(セミコロンなど)か、ダブルクォートの崩れでCSVとして成立していない可能性があります。まずはエディタで先頭数行を見て、区切り文字とヘッダーを確認するのが早道です。

運用で差が出る安定化テクニック

結果CSVに“状態列”を入れて、後工程を楽にする

単に値を集めるだけだと、途中で失敗したサーバーの再実行や、ネットワーク担当への依頼が面倒になります。次のような列を入れておくと、後からの調査が格段に楽です。

  • CollectedAt:いつ採取したか(監査で効く)
  • WMIOk / WinRMOk:どの経路で取れたか
  • WMIError / WinRMError:失敗理由の要約(切り分けの一次情報)

台数が多い場合は“同時実行数”を意識する

台数が多いと、サーバー側・ネットワーク側の負荷や、実行元の待ち時間がボトルネックになります。PowerShell Remotingなら Invoke-Command -ComputerName に配列を渡し、-ThrottleLimit で同時実行数を制御できます(過剰に上げると、逆にタイムアウトや一時的なエラーが増えることがあります)。

$computers = (Import-Csv 'C:\servers.csv').ComputerName

Invoke-Command -ComputerName $computers -ThrottleLimit 20 -ScriptBlock {

# ここに採取処理

}

権限・認証で詰まったときの観点

  • ドメイン環境では、対象サーバーのローカル管理者権限(またはWMI名前空間権限)が必要になることが多い
  • ワークグループやローカルアカウント運用では、UACリモート制限などで挙動が変わるため、標準化した実行アカウントを用意したほうが安定しやすい
  • WinRMを使う場合は、WinRM有効化(Enable-PSRemoting)やGPO設定、認証方式(Kerberos/NTLM)も合わせて確認する

最後に:直す順番を間違えない

「RPC server is unavailable (0x800706BA)」に遭遇したときは、まずスクリプトをImport-Csvで読み、Export-Csvへオブジェクトを渡す形に整えます。そのうえで、WMIが通らないなら到達性・TCP135・動的ポート・WMI受信規則を順に潰し、環境的に難しいならWinRM(WSMan)へ寄せるのが現実的です。原因を“文字列のエラー”として残す設計にしておくと、次回以降の運用も一気に楽になります。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次