かつて山市良と呼ばれたおじさんのブログ
セイテクエンジニアのブログ かつて山市良と呼ばれたおじさんのブログ vol.235 Get-VMで状態を取得する裏技|Hyper-V 小技・裏技集
2026年09月17日配信
執筆者:山内 和朗
「Hyper-V小技・裏技集」シリーズでは、Hyper-Vの仮想環境を利用していて、知っていると便利な小技や裏技を紹介します。今回は、いろいろと役に立つGet-VMの使いこなしについて。
Hyper-VのGet-VMコマンドレットを使用すると、Hyper-VホストやHyper-Vホストクラスター上の仮想マシン(VM)に関するさまざまな情報を取得できます。例えば、以下の記事の「Hyper-VホストからVMの(疑似)メモリ使用率を取得する方法」では、Hyper-Vホスト側から、実行中のVMのCPU数、CPU使用率、メモリ割り当て、疑似メモリ使用率を一覧で表示するスクリプトを紹介しました。
vol.207 仮想環境での考慮事項-パフォーマンスカウンターとの付き合い方(5)|セイテク・シス管道場(Web)
VMの状態が“実行中”であるかどうかは、Get-VMのStateプロパティで取得できます。VMの状態としては、主に以下のものがあります。
Off ・・・ オフ
Starting ・・・ 開始中
Running ・・・ 実行中
Saving ・・・ 保存中
Saved ・・・ 保存完了
Paused ・・・ 一時停止
Stopping ・・・ 停止中
VMの状態が“実行中”であったとしても、VMのゲストOSが完全に起動しているとは限りません。例えば、OSがインストールされていないVMであっても、VMを開始すれば“実行中”になります。VMのゲストOSが起動したかどうかについては、以前、統合サービスのKVP(Key Value Pair)データ交換サービスからOSの情報を取得できるかどうかで判断する方法を紹介しました(vol.169のstartandwait-vm.ps1)。
vol.168 知ってる? 使ってる? Hyper-VのKVP|Windows Server 2016 EOSまであと364日
vol.169 KVPでIPアドレスが取得できなくなったのは仕様|Windows Server 2016 EOSまであと362日
実は、KVPデータ交換サービスを使用するよりももっと簡単な方法があります。それは、こちらも統合サービスの1つである「ハートビート」を利用する方法です(画面1)。VMのハートビートはGet-VMのHeartBeatプロパティで取得できます。ハートビートの種類としては、主に以下のものがあります。
($null) ・・・ VMがオフのとき
Unknown ・・・ 不明、VMが保存完了や一時停止のときはUnkown
NoContact ・・・ コンタクトなし、VMのゲストOSが起動完了していないときなど
Disabled ・・・ 利用不可、VMが実行中でVMで統合サービス「ハートビート」が無効になっているとき
LostCommunication ・・・ 通信の切断、VM側でハートビートサービス(WindowsのvmicserviceやLinuxのhv_utils)が停止しているとき
OKApplicatonsUnkown ・・・ OK (アプリケーション データなし)、VMのハートビートは正常、アプリケーションは不明
OKAppkicationsCritical ・・・ OK (アプリケーション データ重大)、VMのハートビートは正常、アプリケーションは異常
アプリケーションの正常性は、SQL ServerなどHyper-Vのアプリケーション正常性機能に対応したアプリケーション(IVmApplicationHealthMonitorインターフェイスを介してステータスを報告するアプリケーション)がある場合にハートビートサービスに通知されます。そのため、通常は“OK*”(または“OkApplicationsHealthy”“OKApplicatonsUnkown”)であれば正常と判断できます。

画面1 VMのゲストOSが起動しているかどうかは、統合サービスの「ハートビート」で判断できる
次の2つのスクリプトは、VMを開始し、ハートビートが“Ok*”になる、つまりゲストOSが完全に起動するまで待機するスクリプトです(画面2)。なお、実はハートビートが“Disabled”の場合もゲストOSが完全に起動していると判断できますが(左側のスクリプトの修正例: $heartBeat -in "Ok*", "Disabled")、ハートビートは既定で有効なので以下のスクリプトでは考慮していません。
| $vmName = "vm01" start-VM -Name $vmName -ErrorAction Stop do { Start-Sleep -Seconds 1 $vm = Get-VM -Name $vmName -ErrorAction Stop $heartheat = $vm.Heartbeat } until ($heartheat -like "Ok*") Write-Host "$($vm.Name) is Up." |
$vmName = "vm01" start-VM -Name $vmName while ($true) { $vm = Get-VM -Name $vmName if ($vm.Heartbeat -notlike "Ok*") { Write-Host "VM '$($vm.Name)' is Up." break } Start-Sleep -Seconds 1 } |
※ -ErrorAction Stop は、PowerShellスクリプト(.ps1)内に記述した場合に、エラーでスクリプト全体を終了します。
※ クラスター上のVMの場合は、所有者ノードを特定し、Get-VMの-ComputerNameパラメーターに所有者ノードのコンピューター名を指定する必要があります。また、Start-VMではなく、Start-ClusterGroupを使用する必要があります(例1、例2)。詳しくは、前回の記事を参照してください。

画面2 VMを開始し、ハートビートが“OK*”になるまで待機するスクリプトの例。Get-VMはDo Untilループの中
上記のスクリプトは、実は、次のように記述したほうが実行コストが少なく、よりスマートです(画面3)。Get-VMの実行場所に注目してください。上記のスクリプトではWhile/Do Untilループの中に記述していますが、以下のスクリプトではループの前に記述しています。ループ中に記述した場合、1秒ごとにハートビートが“OK*”になるまで繰り返しGet-VMを実行することになりますが、ループの前に記述した場合はGet-VMの実行は1回だけです。
| $vmName = "vm01" $vm = Get-VM -Name $vmName -ErrorAction Stop $vm |Start-VM -ErrorAction Stop do { Start-Sleep -Seconds 1 $heartheat = $vm.Heartbeat } until ($heartheat -like "Ok*") Write-Host "$($vm.Name) is Up." |
$vmName = "vm01" $vm = Get-VM -Name $vmName $vm | start-VM while ($vm.Heartbeat -notlike "Ok*") { Start-Sleep -Seconds 1 } Write-Host "$($vm.Name) is Up." |
※ -ErrorAction Stop は、PowerShellスクリプト(.ps1)内に記述した場合に、エラーでスクリプト全体を終了します。
※ クラスター上のVMの場合は、所有者ノードを特定し、Get-VMの-ComputerNameパラメーターに所有者ノードのコンピューター名を指定する必要があります。また、Start-VMではなく、Start-ClusterGroupを使用する必要があります(例3《画面》、例4)。詳しくは、前回の記事を参照してください。

画面3 VMを開始し、ハートビートが“OK*”になるまで待機するスクリプトのより良い例。Get-VMはDo Untilループの外で1回だけ実行
ループの前にGet-VMを記述したスクリプトは$vmが変化しないため無限ループになってしまうので、Get-VMはループの中に書くべきと思うかもしれません。しかし、Get-VMが返す$vmはVirtualMachine(Microsoft.HyperV.PowerShell.VirtualMachine)タイプのオブジェクトであり、そのプロパティの値は動的に変化します(画面4)。Get-Processなど標準的なコマンドレットでも同様の挙動をする場合があるので、スクリプトを記述する際に無駄に繰り返し実行していないか再検討してみてください。ただし、Microsoftなどのサンプルコードでは、Get-VMなど状態を返すコマンドレットをその都度実行する例が一般的です。お使いの環境やHyper-Vの古いバージョンでは状況が異なるかもしれません(一般的な方法で記述したほうがよいかもしれません)ので、ご注意ください。

画面4 Get-VMが返すVirtualMachineオブジェクトのプロパティは参照するたびに最新の値を返す。Nameプロパティ(VM名)も例外ではない
VMがシャットダウンして停止するまで待機するスクリプトも同じ考えで記述できます。VMの停止状態は、Stateプロパティが“Off”になることで判断できます(画面5)。保存が完了するまで待機したい場合は、Stop-VMをSave-VMに、“Off”を“Saved”に置き換えるだけです。
| $vmName = "vm01" $vm = Get-VM -Name $vmName -ErrorAction Stop $vm |Stop-VM -Force -ErrorAction Stop do { Start-Sleep -Seconds 1 } until ($vm.State -like "Off") Write-Host "$($vm.Name) is Off." |
$vmName = "vm01" $vm = Get-VM -Name $vmName -ErrorAction Stop $vm |Stop-VM -Force -ErrorAction Stop while ($vm.State -ne "Off") { Start-Sleep -Seconds 1 } Write-Host "$($vm.Name) is Off." |
※ -ErrorAction Stop は、PowerShellスクリプト(.ps1)内に記述した場合に、エラーでスクリプト全体を終了します。
※ クラスター上のVMの場合は、所有者ノードを特定し、Get-VMの-ComputerNameパラメーターに所有者ノードのコンピューター名を指定する必要があります。また、Start-VMではなく、Start-ClusterGroupを使用する必要があります(例5、例6)。詳しくは、前回の記事を参照してください。

画面5 VMのシャットダウンを開始(Stop-VM)して、オフになるまで待つスクリプトの例
VMの起動や停止を待機するスクリプトは、基本のスクリプトとして覚えておくといろいろと応用できます。例えば、Hyper-VのPowerShellモジュールには再起動のコマンドレットは存在しません(Restert-VMはハードリセットです)。Start-VMとStop-VM、そして今回紹介した待機スクリプトを組み合わせれば、Hyper-VホストからVMの再起動を簡単に実装できます。その例を含め、次回は応用例をいくつか紹介します。
リファレンス(Microsoft Learn):
Get-VM(Hyper-V)| Start-VM(Hyper-V)| Stop-VM(Hyper-V)| Save-VM(Hyper-V)| Restart-VM(Hyper-V)
Hyper-V 小技・裏技集 (1)|(2)|(3)|(4)