天天看點

推薦:VB.NET控制Hyper-V恢複快照

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
           

繼續閱讀