Hyper-V 找了很多資料,想用軟體控制“恢複快照”的操作,但都不盡如人意,自己做了一點優化,從恢複到完成約10秒,成功後才傳回。源碼是VB.NET,工程需要真實添加引用(工程-引用[右鍵]-添加引用-程式集)找到:
System.Management
然後添加一個工程子產品:
Imports System
Imports System.Collections.Generic
Imports System.Management
#Region "Return Value Of RequestStateChange Method Of the Msvm_ComputerSystem Class"
'Return Value of RequestStateChange Method of the Msvm_ComputerSystem Class
'This method returns one of the following values.
'Completed with No Error (0)
'DMTF Reserved (7–4095)
'Method Parameters Checked - Transition Started (4096)
'Failed (32768)
'Access Denied (32769)
'Not Supported (32770)
'Status is unknown (32771)
'Timeout (32772)
'Invalid parameter (32773)
'System is in use (32774)
'Invalid state for this operation (32775)
'Incorrect data type (32776)
'System is not available (32777)
'Out of memory (32778)
'Common Utilities for the Virtualization Samples https://msdn.microsoft.com/en-us/library/cc723869(v=vs.85).aspx
'C# 實作 Hyper-V 虛拟機 管理 - PeterZhang - 部落格園 http://www.cnblogs.com/Peter-Zhang/archive/2011/09/17/2179634.html
'通過Wmi實作Hyper-V遠端管理(一) - 那家小夥 - 部落格園 https://www.cnblogs.com/lsqandzy/p/5685926.html
'Hyper-V WMI Provider https://msdn.microsoft.com/en-us/library/cc136992(VS.85).aspx
'Hyper-V WMI Classes https://msdn.microsoft.com/en-us/library/cc136986(v=vs.85).aspx
'GetSummaryInformation method of the Msvm_VirtualSystemManagementService class https://msdn.microsoft.com/en-us/library/cc160706(VS.85).aspx
'擷取hyperv和vmware虛機狀态 / 藍訊 http://www.lxway.com/452014012.htm
'Hyper-V WMI: Creating/Applying/Deleting Virtual Machine Snapshots – Taylor Brown's Blog https://blogs.msdn.microsoft.com/taylorb/2008/06/16/hyper-v-wmi-creatingapplyingdeleting-virtual-machine-snapshots/
'ApplyVirtualSystemSnapshot method of the Msvm_VirtualSystemManagementService class https://technet.microsoft.com/zh-cn/library/cc136767.aspx/
#End Region
Public Class VMManagement
Public Shared Property HostServer As String = "hostServer"
Public Shared Property UserName As String = "username"
Public Shared Property Password As String = "password"
Public Shared Function GetVMState(ByVal vmName As String) As VMState
Dim vmState As VMState = VMState.Undefined
Dim co As ConnectionOptions = New ConnectionOptions()
co.Username = UserName
co.Password = Password
Dim manScope As ManagementScope = New ManagementScope(String.Format("\\{0}\root\virtualization", HostServer), co)
manScope.Connect()
Dim queryObj As ObjectQuery = New ObjectQuery("SELECT * FROM Msvm_ComputerSystem")
Dim vmSearcher As ManagementObjectSearcher = New ManagementObjectSearcher(manScope, queryObj)
Dim vmCollection As ManagementObjectCollection = vmSearcher.Get
For Each vm As ManagementObject In vmCollection
'Debug.Print(vm("ElementName").ToString & " state: " & vm("EnabledState").ToString)
If String.Compare(vm("ElementName").ToString, vmName, True) = 0 Then
vmState = ConvertStrToVMState(vm("EnabledState").ToString)
Exit For
End If
Next
Return vmState
End Function
Public Shared Function StartUp(ByVal vmName As String) As Boolean
Return ChangeVMState(vmName, VMState.Enabled)
End Function
Public Shared Function ShutDown(ByVal vmName As String) As Boolean
Return ChangeVMState(vmName, VMState.Disabled)
End Function
Public Shared Function RollBack(ByVal vmName As String, ByVal snapShotName As String) As Boolean
Dim co As ConnectionOptions = New ConnectionOptions()
co.Username = UserName
co.Password = Password
Dim manScope As ManagementScope = New ManagementScope(String.Format("\\{0}\root\virtualization", HostServer), co)
manScope.Connect()
Dim queryObj As ObjectQuery = New ObjectQuery("SELECT * FROM Msvm_ComputerSystem")
Dim vmSearcher As ManagementObjectSearcher = New ManagementObjectSearcher(manScope, queryObj)
Dim vmCollection As ManagementObjectCollection = vmSearcher.Get()
Dim opResult As Object = Nothing
' loop the virtual machines
Dim vm As ManagementObject
For Each vm In vmCollection
Debug.Print("find vm name:" & vm("ElementName").ToString)
' find the vmName virtual machine, then get the list of snapshot
If String.Compare(vm("ElementName").ToString, vmName, True) <> 0 Then Continue For
Dim queryObj1 As ObjectQuery = New ObjectQuery(String.Format("SELECT * FROM Msvm_VirtualSystemSettingData WHERE SystemName='{0}' and SettingType=5", vm("Name").ToString))
Dim vmSearcher1 As ManagementObjectSearcher = New ManagementObjectSearcher(manScope, queryObj1)
Dim vmCollection1 As ManagementObjectCollection = vmSearcher1.Get()
Dim snapshot As ManagementObject = Nothing
' find and record the snapShot object
Dim snap As ManagementObject
For Each snap In vmCollection1
Debug.Print("find snap name:" & snap("ElementName").ToString)
If String.Compare(snap("ElementName").ToString, snapShotName, True) <> 0 Then Continue For
snapshot = snap
Exit For
Next
Dim queryObj2 As ObjectQuery = New ObjectQuery("SELECT * FROM Msvm_VirtualSystemManagementService")
Dim vmSearcher2 As ManagementObjectSearcher = New ManagementObjectSearcher(manScope, queryObj2)
Dim vmCollection2 As ManagementObjectCollection = vmSearcher2.Get()
Dim virtualSystemService As ManagementObject = Nothing
For Each o As ManagementObject In vmCollection2
Debug.Print(o.ToString)
virtualSystemService = o
Exit For
Next
If ConvertStrToVMState(vm("EnabledState").ToString) <> VMState.Disabled Then
'關機
ShutDown(vm("ElementName").ToString)
'Threading.Thread.Sleep(1000)
For i As Integer = 0 To 100 Step 1
Debug.Print(Now & vbTab & GetVMState(vmName).ToString)
If GetVMState(vmName) = VMState.Disabled Then Exit For
Threading.Thread.Sleep(345)
Next
End If
'Threading.Thread.Sleep(10000)
Debug.Print("vm.Path {0} ", vm.Path.Path)
Debug.Print("snapshot.Path {0} ", snapshot.Path.Path)
'
'Dim inParams As ManagementBaseObject = virtualSystemService.GetMethodParameters("ApplyVirtualSystemSnapShot")
'inParams("ComputerSystem") = vm.Path.Path
'inParams("SnapshotSettingData") = snapshot.Path.Path
'opResult = virtualSystemService.InvokeMethod("ApplyVirtualSystemSnapShot", inParams, Nothing)
'
'Dim obj(1) As Object
'obj(0) = vm.Path
'obj(1) = snapshot.Path
'opResult = virtualSystemService.InvokeMethod("ApplyVirtualSystemSnapShot", obj)
'
'應用快照
opResult = virtualSystemService.InvokeMethod("ApplyVirtualSystemSnapShot", New Object() {vm.Path, snapshot.Path}) '此操作的無效狀态
If opResult.ToString = "0" Then
'Threading.Thread.Sleep(1000)
For i As Integer = 0 To 100 Step 1
Debug.Print(Now & vbTab & GetVMState(vmName).ToString)
If GetVMState(vmName) = VMState.Suspended Then Exit For
Threading.Thread.Sleep(345)
Next
'Threading.Thread.Sleep(10000)
'開機
StartUp(vm("ElementName").ToString)
For i As Integer = 0 To 100 Step 1
Debug.Print(Now & vbTab & GetVMState(vmName).ToString)
If GetVMState(vmName) = VMState.Enabled Then Exit For
Threading.Thread.Sleep(345)
Next
End If
Exit For
Next
'\\WQSERVER\root\virtualization:Msvm_VirtualSystemManagementService.CreationClassName="Msvm_VirtualSystemManagementService",Name="vmms",SystemCreationClassName="Msvm_ComputerSystem",SystemName="WQSERVER"
'vm.Path \\WQSERVER\root\virtualization:Msvm_ComputerSystem.CreationClassName="Msvm_ComputerSystem",Name="6EDCD1EB-F2E1-4706-9050-7E5ED649186B"
'snapshot.Path \\WQSERVER\root\virtualization:Msvm_VirtualSystemSettingData.InstanceID="Microsoft:0E284464-6774-4A3A-AF5B-F544F716BB80"
'Debug.Print("return:" & opResult("ReturnValue").ToString)
Debug.Print(opResult.ToString)
Return "0" = opResult.ToString
End Function
Public Shared Function GetVMSnapShotList(ByVal vmName As String) As List(Of SnapShot)
Dim shotList As New List(Of SnapShot)
Dim co As ConnectionOptions = New ConnectionOptions()
co.Username = UserName
co.Password = Password
Dim manScope As ManagementScope = New ManagementScope(String.Format("\\{0}\root\virtualization", HostServer), co)
manScope.Connect()
Dim queryObj As ObjectQuery = New ObjectQuery("SELECT * FROM Msvm_ComputerSystem")
Dim vmSearcher As ManagementObjectSearcher = New ManagementObjectSearcher(manScope, queryObj)
Dim vmCollection As ManagementObjectCollection = vmSearcher.Get()
Dim str As String = ""
' loop through the machines
Dim vm As ManagementObject
For Each vm In vmCollection
str += "Snapshot of " + vm("ElementName").ToString + "\r\n"
'Get the snaplist
If String.Compare(vm("ElementName").ToString, vmName, True) = 0 Then
Dim queryObj1 As ObjectQuery = New ObjectQuery(String.Format("SELECT * FROM Msvm_VirtualSystemSettingData WHERE SystemName='{0}' and SettingType=5", vm("Name").ToString))
Dim vmSearcher1 As ManagementObjectSearcher = New ManagementObjectSearcher(manScope, queryObj1)
Dim vmCollection1 As ManagementObjectCollection = vmSearcher1.Get()
Dim snap As ManagementObject
For Each snap In vmCollection1
Dim ss As SnapShot = New SnapShot()
ss.Name = snap("ElementName").ToString
ss.CreationTime = DateTime.ParseExact(snap("CreationTime").ToString.Substring(0, 14), "yyyyMMddHHmmss", Nothing).ToLocalTime()
ss.Notes = snap("Notes").ToString
shotList.Add(ss)
Next
End If
Next
Return shotList
End Function
Private Shared Function ChangeVMState(ByVal vmName As String, ByVal toState As VMState) As Boolean
Dim toStateCode As String = ConvertVMStateToStr(toState)
If toStateCode = String.Empty Then
Return False
End If
Dim co As ConnectionOptions = New ConnectionOptions()
co.Username = UserName
co.Password = Password
Dim manScope As ManagementScope = New ManagementScope(String.Format("\\{0}\root\virtualization", HostServer), co)
manScope.Connect()
Dim queryObj As ObjectQuery = New ObjectQuery("SELECT * FROM Msvm_ComputerSystem")
Dim vmSearcher As ManagementObjectSearcher = New ManagementObjectSearcher(manScope, queryObj)
Dim vmCollection As ManagementObjectCollection = vmSearcher.Get()
Dim o As Object = Nothing
Dim vm As ManagementObject
For Each vm In vmCollection
If String.Compare(vm("ElementName").ToString, vmName, True) = 0 Then
o = vm.InvokeMethod("RequestStateChange", New Object() {toStateCode})
Exit For
End If
Next
Return "0" = o.ToString
End Function
Private Shared Function ConvertStrToVMState(ByVal statusCode As String) As VMState
Select Case statusCode
Case "0" : Return VMState.Unknown
Case "2" : Return VMState.Enabled
Case "3" : Return VMState.Disabled
Case "32768" : Return VMState.Paused
Case "32769" : Return VMState.Suspended
Case "32770" : Return VMState.Starting
Case "32771" : Return VMState.Snapshotting
Case "32773" : Return VMState.Saving
Case "32775" : Return VMState.InvalidOperation
Case "32774" : Return VMState.Stopping
Case "32776" : Return VMState.Pausing
Case "32777" : Return VMState.Resuming
End Select
Return VMState.Undefined
End Function
Private Shared Function ConvertVMStateToStr(ByVal vmState As VMState) As String
Select Case vmState
Case VMState.Unknown : Return "0"
Case VMState.Enabled : Return "2"
Case VMState.Disabled : Return "3"
Case VMState.Paused : Return "32768"
Case VMState.Suspended : Return "32769"
Case VMState.Starting : Return "32770"
Case VMState.Snapshotting : Return "32771"
Case VMState.Saving : Return "32773"
Case VMState.Stopping : Return "32774"
Case VMState.InvalidOperation : Return "32775"
Case VMState.Pausing : Return "32776"
Case VMState.Resuming : Return "32777"
End Select
Return "0"
End Function
End Class
'/ <summary>
'/- Undefined --> "Not defined"
'/0 Unknown --> "Unknown"
'/2 Enabled --> "Running"
'/3 Diabled --> "Off"
'/32768 Paused --> "Paused"
'/32769 Suspended --> "Saved"
'/32770 Starting --> "Starting"
'/32771 Snapshotting --> "Snapshooting
'/32773 Saving --> "Saving"
'/32774 Stopping --> "Shuting down
'/32776 Pausing --> "Pausing"
'/32777 Resuming --> "Resuming"
'/ </summary>
Public Enum VMState
Undefined
Unknown
Enabled
Disabled
Paused
Suspended
Starting
Snapshotting
Saving
Stopping
InvalidOperation
Pausing
Resuming
End Enum
Public Class SnapShot
Public Property Name() As String
Public Property CreationTime() As DateTime
Public Property Notes() As String
End Class
'再添加測試代碼:
Public Module ModMain
Public Sub Main()
VMManagement.HostServer = "虛拟機主控端計算機名或IP"
VMManagement.UserName = "使用者名"
VMManagement.Password = "密碼"
Console.WriteLine(VMManagement.GetVMState("虛拟機名").ToString)
Console.WriteLine(VMManagement.RollBack("虛拟機名", "快照名"))
Console.ReadKey()
End Sub
End Module