Hyper-VとVMwareを共存させる際にPSで簡単に切り替える方法
2018/04/25
本エントリーの目次
現在はPCやサーバーの仮想化が広く浸透し、テストや実稼働環境に仮想化技術を使っている方も多いと思います。
そして特に開発やテストを行っているときには、このように思うことがあるはず。
Hyper-VとVMwareを共存させたい!
VMwareにかぎった話ではないんですが、Hyper-Vと他の仮想化ソリューションを同じ環境に有効化・インストールした場合、どちらかの仮想化ソリューションが起動できなくなります。
たとえばHyper-VとVMwareを共存させている環境下でHyper-Vの機能を有効にしている場合、VMwareの仮想マシンを起動しようとした場合、以下のようなメッセージが表示され、VMwareの仮想マシンを起動することはできません。
これとは反対に、Hyper-VとVMwareを共存させている環境下でHyper-Vの機能を無効にしている場合、Hyper-Vの仮想マシンを起動しようとした場合、以下のようなメッセージが表示され、Hyper-Vの仮想マシンを起動することはできません。(Hyper-Vの無効化 = VMwareの有効化状態と考えてください)
これは仮想化に使用する技術・アーキテクチャーが違うために仕方のないことで、どうしようもありません。
そうは言っても、開発やテストによっては両者を使い分けたいこともあるでしょう。
幸いなことに両者を切り替えながらの運用であれば可能なので、使い分けの際は片方の機能を無効化することで動作させることが可能です。
具体的には、Hyper-Vの仮想マシンを使いたいときは、『コントロールパネル』 → 『プログラムと機能』 → 『Windowsの機能の有効化または無効化』と展開し、『Hyper-V』にチェックを入れてHyper-Vの機能を有効化します。
VMwareなど、Hyper-V以外の仮想化ソリューションを使用したい時には、『Hyper-V』のチェックをはずしてHyper-Vの機能を無効化すればOK!
ただこの作業、ちょっと面倒ですよね。
そこでよく行われているのがBCDEditコマンドを使用しての、Hyper-Vの機能の有効化・無効化切り替え処理です。
BCDEditコマンドを使用してHyper-Vの機能の有効・無効を切り替える方法
これについての詳細は、マイナビニュースさんのWin 7/8/8.1編: Hyper-VとVMwareを共存させるに書いてありますが、簡単に言うと、BCDEditコマンドを使用して『hypervisorlaunchtype』属性の値を書き換え、OSを再起動させて変更した設定値を読みこませる、といった内容です。
これであれば、いちいちコントロールパネルを開いて…といった手間がなくなるので、少し楽になります。
ただこの処理では現在の設定値(Hyper-Vの機能の有効・無効状態)を問わず、コンピューターの再起動が実行されてしまいます。
だからたとえば既にHyper-Vの機能が有効状態であったとしても、Hyper-Vの機能有効化処理を実行すると再起動が行われてしまうんです。
これは時間がもったいないなぁ、なんて思ったわけ。
Hyper-Vの仮想マシンを起動していると、PCの終了時には仮想マシンの保存処理が、起動時には保存状態の仮想マシンの復帰処理が動作するため、それなりに時間がかかります。
これが多数の仮想マシンを起動している状態で、低速のディスクに仮想HDD(VHDXなど)を配置している状態の場合、かなりの時間となってしまうことも。
そこでこのあたりについて対話的に処理をすすめ、不要な再起動を避けられるような、Hyper-Vと他の仮想化ソリューションを切り替えるPowerShellスクリプトを作りました。
はじめに
これからご紹介するスクリプトには、PowerShellを使用しています。
最近のWindowsの初期設定では、PowerShell自体はインストールされていますが、実行ができない設定となっています。
そのためPowerShellを起動して以下のコマンドを実行し、Restrictedと表示されるようであれば、PowerShellスクリプトの実行ポリシーを変更してください。
1 | Get-ExecutionPolicy |
PowerShellスクリプトの実行ポリシーの変更は以下のコマンドで行います。
RemoteSignedなど、動作可能なポリシーに変更してください。(セキュリティーの低下が懸念される場合には、-Scopeパラメーターも併用すると良いかもしれません。)
1 | Set-ExecutionPolicy RemoteSigned |
また当該スクリプトはWindows 10 Professional、PowerShell v5(詳細バージョンは以下のとおり)の環境下で、UACデフォルト状態とOFFのパターンにて正常に動作することを確認しています。
1 2 3 4 5 | PS C:\> $PSVersionTable.PSVersion Major Minor Build Revision ----- ----- ----- -------- 5 1 14393 0 |
ただOSのバージョンやPowerShell、.NET Frameworkのバージョンによっては、正常に動作しない可能性もあります。
その場合にはお手数ですが、ご自身の環境に合わせて修正してお使いください。
Hyper-Vと他の仮想化ソリューションの切り替えを対話的に行うPowerShellスクリプト
まずは今回ご紹介するHyper-Vと他の仮想化ソリューションの切り替えを対話的に行うPowerShellスクリプトの動作について。
PowerShellスクリプトの動作
今回ご紹介するスクリプトは以下のような動作をします。
Hyper-Vの機能が『Windowsの機能の有効化または無効化』で一度も有効化されていない状態
Hyper-Vの機能が『Windowsの機能の有効化または無効化』で一度も有効化されていない状態では、BCDEditコマンドを使用しても『hypervisorlaunchtype』属性が見つからないようです。
この状態では、その旨をメッセージで通知するのみで、それ以外の処理は一切行いません。
Hyper-Vの機能が有効状態
Hyper-Vの機能が有効状態であればその旨を通知し、無効化するかどうかを確認します。
『はい』を選択した場合には、コンピューターをただちに再起動するかどうかを確認。
再起動を要求した場合には、ただちにコンピューターの再起動が行われます。
Hyper-Vの機能が無効状態
Hyper-Vの機能が無効状態であればその旨を通知し、有効化するかどうかを確認します。
『はい』を選択した場合には、コンピューターをただちに再起動するかどうかを確認。
再起動を要求した場合には、ただちにコンピューターの再起動が行われます。
PowerShellスクリプト本体
テキストエディターを開いて以下の内容を記述し、ファイル名を『set-vm-launch-type.ps1』として保存してください。
あとは『set-vm-launch-type.ps1』スクリプトを管理者権限で実行すれば、先にご紹介した仕様のとおりに動作します。
(このスクリプトは内部で管理者権限が必要なコマンドを実行しているため、管理者権限での実行が必要です。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | #MessageBox.Showメソッドを使用するためにインポート Add-Type -AssemblyName System.Windows.Forms #BCDEDITコマンドが返却するHyper-Vの状態キー Set-Variable -name HYPER_V_LAUNCH_TYPE -value ("hypervisorlaunchtype") -Option Constant #BCDEDITコマンドが返却するHyper-Vの属性値 Set-Variable -name HYPER_V_LAUNCH_TYPE_AUTO -value ("Auto") -Option Constant Set-Variable -name HYPER_V_LAUNCH_TYPE_OFF -value ("Off") -Option Constant <# 管理者権限で実行されているかどうかを判定するメソッド 管理者権限で実行されていれば、$Trueを返却する #> function Get-RunAsAdministrator(){ return (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) } <# メッセージボックスの表示メソッド パラメーターは.NET FrameworkのMessageBox.Showメソッドを参照 #> function Show-Msgbox([string]$Text,[string]$Caption = "",[System.Windows.Forms.MessageBoxButtons]$MessageBoxButtons = [System.Windows.Forms.MessageBoxButtons]::OK, ` [System.Windows.Forms.MessageBoxIcon]$MessageBoxIcon = [System.Windows.Forms.MessageBoxIcon]::Information, ` [System.Windows.Forms.MessageBoxDefaultButton]$MessageBoxDefaultButton = [System.Windows.Forms.MessageBoxDefaultButton]::Button1){ [System.Windows.Forms.MessageBox]::Show($Text, $Caption, $MessageBoxButtons, $MessageBoxIcon,$MessageBoxDefaultButton) } #管理者権限で実行しているか if (!(Get-RunAsAdministrator)){ Show-Msgbox -text "このPowerShellスクリプトを実行するには、管理者権限が必要です。" -caption "報告" exit } #BCDEDITコマンドでHyper-Vの機能の状態を取得 #$HyperVisorLaunchTypeには、"Auto"、"Off"、""のどれかが取得される #""の場合、Hyper-Vの機能が追加されていない状態。 $HyperVisorLaunchType = [string]((bcdedit | Select-String $HYPER_V_LAUNCH_TYPE) -replace ($HYPER_V_LAUNCH_TYPE + " +")) $SetLaunchType = "" switch ($HyperVisorLaunchType){ "" { #現在Hyper-Vが『Windowsの機能の有効化または無効化』で有効化されていない Show-Msgbox -text "Hyper-Vの機能が『Windowsの機能の有効化または無効化』で有効化されていません。`r`n(hypervisorlaunchtype属性が見つかりません)" -caption "報告" }$HYPER_V_LAUNCH_TYPE_AUTO{ #現在Hyper-Vが有効状態 if ([System.Windows.Forms.DialogResult]::Yes -eq ` (Show-Msgbox -text "Hyper-Vの機能は現在有効(hypervisorlaunchtype = $HyperVisorLaunchType)です。`r`n`r`nHyper-Vの機能を無効化しますか?" -caption "確認" ` -MessageBoxIcon Question -MessageBoxDefaultButton Button2 -MessageBoxButtons YesNo)){ $SetLaunchType = $HYPER_V_LAUNCH_TYPE_OFF } }$HYPER_V_LAUNCH_TYPE_OFF{ #現在Hyper-Vが無効状態 if ([System.Windows.Forms.DialogResult]::Yes -eq ` (Show-Msgbox -text "Hyper-Vの機能は現在無効(hypervisorlaunchtype = $HyperVisorLaunchType)です。`r`n`r`nHyper-Vの機能を有効化しますか?" -caption "確認" ` -MessageBoxIcon Question -MessageBoxDefaultButton Button2 -MessageBoxButtons YesNo)){ $SetLaunchType = $HYPER_V_LAUNCH_TYPE_AUTO } }default{ Show-Msgbox -text ("予期していない" + $HYPER_V_LAUNCH_TYPE + "属性の値を検出しました。") -caption "報告" -MessageBoxIcon Exclamation } } if($SetLaunchType){ #設定変更要求があったのでBCDEDITコマンドを実行 bcdedit /set hypervisorlaunchtype $SetLaunchType #設定変更の適用には、PCの再起動が必要。 if ([System.Windows.Forms.DialogResult]::Yes -eq (Show-Msgbox -text "設定変更の適用には、コンピューターの再起動が必要です。`r`n今すぐにコンピューターを再起動しますか?" -caption "確認" ` -MessageBoxIcon Question -MessageBoxDefaultButton Button2 -MessageBoxButtons YesNo)){ Restart-Computer } } |
ちなみに管理者権限で実行しなかった場合には、以下のメッセージを表示して処理を中止します。
管理者権限で実行するのが面倒なんだけど?
たしかにPowerShellを管理者権限で実行するのは少し面倒かもしれませんね。
そこで先のスクリプトを管理者権限で実行するスクリプトも用意しました。
以下の内容を記述したファイルを、先のスクリプトと同じディレクトリーに配置してください。
1 2 3 4 5 6 | #指定されたパスのPowerShellスクリプトを管理者権限で実行するメソッド function Sudo([string] $Path){ Start-Process powershell -ArgumentList "`"& '$Path'`"" -Verb runas } #管理者権限で実行 sudo -Path (Join-Path $PSScriptRoot "set-vm-launch-type.ps1") |
このsudo.ps1スクリプトを通常権限で実行すると、set-vm-launch-type.ps1スクリプトを管理者権限で実行します。
ダブルクリックで実行したいんだけど?
この場合には、sudo.ps1のショートカットを作成し、プロパティのリンク先(例 C:\xxxx\sudo.ps1)の内容を以下のように書き換えればOK!
1 | powershell -command "&'C:\xxxx\sudo.ps1'" |
今回ご紹介した対話的なスクリプトであれば、誤って不要なコンピューターの再起動をすることがなくなるはず。
そのため多少ですが、時間のムダが減ると思います。
Hyper-Vと他の仮想化ソリューションを共存させている方はぜひご活用くださーい!