Hyper-V 虛擬化技術(Hyper-V 2.0) Part II
上一篇Hyper-V 虛擬化技術(Hyper-V 2.0) Part I講解的是整體運作的機制
這篇並不會像上一篇一樣長篇大論,因為只會稍微的講解WMI與Hyper-V的關係
在此引用這個網站的圖片,來做一個簡單的圖解
http://www.msservermag.com.tw/technicwords/021128.aspx
微軟的MSDN中,有提供Hyper-V WMI Provider的文件可以參考
http://msdn.microsoft.com/en-us/library/cc136992(VS.85).aspx
在啟用Hyper-V後,會新增root\virtualization這個命名空間,我們可以透過PowerShell去查詢該命名空間底下所有的Object
指令是Get-Wmiobject –Namespace “root\virtualization” –Computer Hostname –list
下圖這個範例,示範了如何透過WMI去查詢Guest OS的狀態
Get-WmiObject -Class Msvm_ComputerSystem -Namespace "root\virtualization" -ComputerName Hostname
其中的EnabledState就是回傳的狀態值,2代表正常
這邊看似沒甚麼了不起,GUI介面就可以得知的東西
呃…確實是如此,因為GUI介面就已經幫你寫好查詢的方法跟回傳,這裡只是大概講解Hyper-V Manager
是如何去取得Guest OS的狀態之類
但是如果是GUI介面所沒有的呢:P
或者你要用Job的方式從Host去控制Guest OS,而不是透過Guest OS的Job去控制呢?
這裡的命令,其實都是透過WMI去控制的
接著來示範一個很奇特的範例,來驗證第一張圖,WMI的架構
我們先透過一個VBScript去使用Windows Script Host去呼叫CIMOM
然後,對Guest OS做鍵盤輸入的動作,首先先將下列VBScript存成PressKey.vbs
如對此VBScript不放心,您可以直接至Microsoft MSDN中複製
http://msdn.microsoft.com/en-us/library/cc136956(v=vs.85).aspx
option explicit
dim objWMIService
dim fileSystem
const wmiSuccessful = 0
Main()
'-----------------------------------------------------------------
' Main routine
'-----------------------------------------------------------------
Sub Main()
dim computer, objArgs, vmName, computerSystem, keycode, keyboard
set fileSystem = Wscript.CreateObject("Scripting.FileSystemObject")
computer = "."
set objWMIService = GetObject("winmgmts:\\" & computer & "\root\virtualization")
set objArgs = WScript.Arguments
if WScript.Arguments.Count = 2 then
vmName= objArgs.Unnamed.Item(0)
keycode = objArgs.Unnamed.Item(1)
else
WScript.Echo "usage: cscript PressKey.vbs vmName keycode"
WScript.Quit
end if
set computerSystem = GetComputerSystem(vmName)
set keyboard = GetComputerKeyboard(computerSystem)
if PressKey(keyboard, keycode) then
WriteLog "Done"
WScript.Quit(0)
else
WriteLog "PressKey failed"
WScript.Quit(1)
end if
End Sub
'-----------------------------------------------------------------
' Retrieve Msvm_VirtualComputerSystem from base on its ElementName
'
'-----------------------------------------------------------------
Function GetComputerSystem(vmElementName)
dim query
On Error Resume Next
query = Format1("select * from Msvm_ComputerSystem where ElementName = '{0}'", vmElementName)
set GetComputerSystem = objWMIService.ExecQuery(query).ItemIndex(0)
if (Err.Number <> 0) then
WriteLog Format1("Err.Number: {0}", Err.Number)
WriteLog Format1("Err.Description:{0}",Err.Description)
WScript.Quit(1)
end if
End Function
'-----------------------------------------------------------------
' Retrieve Msvm_Keyboard from given computer system
'
'-----------------------------------------------------------------
Function GetComputerKeyboard(computerSystem)
dim query
On Error Resume Next
query = Format1("ASSOCIATORS OF {{0}} WHERE resultClass = Msvm_Keyboard", computerSystem.Path_.Path)
set GetComputerKeyboard = objWMIService.ExecQuery(query).ItemIndex(0)
if (Err.Number <> 0) then
WriteLog Format1("Err.Number: {0}", Err.Number)
WriteLog Format1("Err.Description:{0}",Err.Description)
WScript.Quit(1)
end if
End Function
'-----------------------------------------------------------------
' Press the key with the given key code on the given keyboard
'-----------------------------------------------------------------
Function PressKey(keyboard, keyCode)
WriteLog Format2("PressKey({0}, {1})", keyboard.ElementName, keyCode)
dim objInParam, objOutParams
PressKey = false
set objInParam = keyboard.Methods_("PressKey").InParameters.SpawnInstance_()
objInParam.keyCode = keyCode
set objOutParams = keyboard.ExecMethod_("PressKey", objInParam)
if objOutParams.ReturnValue = wmiSuccessful then
WriteLog Format2("The key with code '{0}' is typed on {1}.", keyCode, keyboard.ElementName)
PressKey = true
end if
End Function
'-----------------------------------------------------------------
' Create the console log files.
'-----------------------------------------------------------------
Sub WriteLog(line)
dim fileStream
set fileStream = fileSystem.OpenTextFile(".\PressKey.log", 8, true)
WScript.Echo line
fileStream.WriteLine line
fileStream.Close
End Sub
'------------------------------------------------------------------------------
' The string formatting functions to avoid string concatenation.
'------------------------------------------------------------------------------
Function Format2(myString, arg0, arg1)
Format2 = Format1(myString, arg0)
Format2 = Replace(Format2, "{1}", arg1)
End Function
'------------------------------------------------------------------------------
' The string formatting functions to avoid string concatenation.
'------------------------------------------------------------------------------
Function Format1(myString, arg0)
Format1 = Replace(myString, "{0}", arg0)
End Function
接著我們會需要這張表去對應Virtial Key相對應的Uint32的值
http://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx
這張表的值是16進位,將其換算成十進位後,加上256,會可以輸入該值到Guest OS中
像範例中,我會Daniel-AD這部Guest OS輸入鍵盤324,d這個字母在表列中為0x44
也就是256+68=324,接著他就會在Guest OS中輸入d這個字母
你也可以透過Powershell去轉換這個數值
PowerShell的語法function To-UInt32{[UInt32]("0x{0:x}" -f $args[0])+256}
這可以新增一個To UInt32的轉換方法
接著可以透過To-UInt32 0x44去取得相對應的值