Hyper-V Virtual Machine Backup Script using VBS/VBScript
Link to Text File:
hypervbackups.txt
'================================================================
'Hyper-V Virtual Machine Backup Script using VBS/VBScript
This Script Saves the VMs first
'================================================================
'================================================================
'External Requirements:
'
'Windows Server 2008
'HyperV Role
'indicator_square.gif (http://www.czerno.com/html/windows/indicator_square.gif)
'hyperv.htm (http://www.czerno.com/html/windows/hyperv.htm)
'
'All can be found in a zip file here: (http://www.czerno.com/html/windows/hypervbackups.zip)
'================================================================
'================================================================
'Instructions:
'
'Save this file as what ever name you want
'
'Place indicator_square.gif and hyperv.htm in the same folder as this script
'
'Do not rename indicator_square.gif or hyperv.htm
'
'Do not run the script in the Root of a drive, subfolder only
'================================================================
'================================================================
'Warnings:
'
'If your VM is a Database Server, such as MS SQL Server, or a
'Domain Controller, you may want to Shut the VM down instead of Saving.
'
'The reason for this is that you cannot always restore the Saved State of the VM
'which puts you at risk of DB corruption.
'
'Other alternatives are to add a routine to shutdown the Databases or
'Active Direcitory before saving the state.
'You can also use my
other script, which shuts down the VMs instead of saving the state.
'================================================================
'================================================================
'Note:
'If you want to see the status of the backup, be sure when you schedule
'the task to configure it for Windows Server 2003, Windows XP or Windows 2000
'
'Also, make sure you set the 'Start in folder' when scheduling the task.
'================================================================
On Error Resume Next
'****************************************************************
'Begin User Definable Section
'****************************************************************
'================================================================
' Path to backup VMs to, can be UNC or Local, be careful with spaces
'================================================================
strBackupDir = "\\<servername>\<sharename>"
'================================================================
'Drive Letter, plus colon, where VMs are located
'
'Be sure this drive is limited to only VMs as everything will
'be created in the Shadow Copy.
'
'It's ok if there is more, but it will take longer and use more
'disk space to create the Shadow Copy.
'
'There is a chance, though, if you are linited in space, not all the VMs
'will be in the Shadow Copy.
'================================================================
strVMdrive = "D:"
'================================================================
'Subfolder where VMs are located
'================================================================
strVMfolder = "Virtual Machines"
'================================================================
'Free Drive Letter, plus colon, to mount the Shadow Copy
'================================================================
strTempDrive = "V:"
'================================================================
'Email From address
'================================================================
strEmailFrom = "your@email.com"
'================================================================
'Email to address
'================================================================
strEmailTo = "your@email.com"
'================================================================
'SMTP Server
'================================================================
strSMTP = "your.smtp.server"
'****************************************************************
'End User Defined Section
'****************************************************************
'================================================================
'Load current date (formatted as mm-dd-yyyy)
'into variable strDate
'================================================================
strDate = Month(Now) & "-" & Day(Now) & "-" & Year(Now)
'================================================================
'Determine where the script is being ran from
'================================================================
Set objShell = CreateObject ("WScript.Shell")
set objFSO=CreateObject("Scripting.FileSystemObject")
strPath = Wscript.ScriptFullName
Set objFile = objFSO.GetFile(strPath)
strFolder = objFSO.GetParentFolderName(objFile)
'================================================================
'Setup progress window
'================================================================
Set objExplorer = WScript.CreateObject("InternetExplorer.Application")
objExplorer.Navigate "file:///" & strFolder & "\hyperv.htm"
objExplorer.ToolBar = 0
objExplorer.StatusBar = 0
objExplorer.Width=400
objExplorer.Height = 200
objExplorer.Left = 0
objExplorer.Top = 0
Do While (objExplorer.Busy)
Wscript.Sleep 200
Loop
objExplorer.Visible = 1
'================================================================
'VBScript and Robocopy Log Files
'================================================================
strLogFolder = strFolder & "\vmbackuplogs"
'create Log File folder
Set objFSO = CreateObject("Scripting.FileSystemObject")
If Not objFSO.FolderExists(strLogFolder) Then
Set objFolder = objFSO.CreateFolder(strLogFolder)
End If
'Set objFolder = objFSO.CreateFolder(strLogFolder)
strVBSLog = strLogFolder & "\vmbackup1.log"
strRoboLog = strLogFolder & "\vmbackup2.log"
strLogFile = strFolder & "\" & strDate & "-VMBackupLogFile.txt"
'=============================================================================
'Setup VBS Log File
'=============================================================================
Set objFSO = createobject("scripting.filesystemobject")
Set objStream = objFSO.OpenTextFile(strVBSLog,2,true)
objStream.Writeline((Now) & " --- Hyper-V Virtual Machine Backup Script
Starting")
objStream.Writeline((Now) & " --- Script is being ran from: " & strFolder)
objStream.Writeline(" ")
objExplorer.Document.Body.InnerHTML = "Hyper-V Virtual Machine Backup Script
Starting<br>" _
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 5000
'=============================================================================
'Save Running VMs
'=============================================================================
objStream.Writeline((Now) & " --- Saving Running VMs")
objExplorer.Document.Body.InnerHTML = "Saving Running VMs <br>" _
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 5000
Set WMIObject = GetObject("winmgmts:\\.\root\virtualization")
Set VMList = WMIObject.ExecQuery("SELECT * FROM Msvm_ComputerSystem")
For Each VM In VMList
If VM.Caption = "Virtual Machine" then
VMName = VM.ElementName
checkVMState()
If VM.EnabledState = 2 then
wscript.sleep 1000
VM.RequestStateChange(32769)
Do While theVM <> 32769
checkVMState()
'Wscript.echo theVM
WScript.Sleep 5000
Loop
End if
End if
Next
'=============================================================================
'Create Shadow Copy Commands
'=============================================================================
objStream.Writeline((Now) & " --- " & "Create DiskShadow Commands")
objExplorer.Document.Body.InnerHTML = "Create DiskShadow Commands<br>" _
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 1000
sVSSCmd = "CreateVSS.dsh"
Set oFileSys = CreateObject("Scripting.FileSystemObject")
if oFileSys.FileExists(sVSSCmd) then oFileSys.DeleteFile(sVSSCmd)
set oVSSCmd = oFileSys.CreateTextFile(sVSSCmd, True)
oVSSCmd.WriteLine "DELETE SHADOWS ALL"
oVSSCmd.WriteLine "SET CONTEXT PERSISTENT"
oVSSCmd.WriteLine "SET METADATA " & strFolder & "\" & "VMBackup.cab"
oVSSCmd.WriteLine "SET VERBOSE OFF"
oVSSCmd.WriteLine "BEGIN BACKUP"
oVSSCmd.WriteLine "ADD VOLUME " & strVMdrive & " ALIAS G1"
oVSSCmd.WriteLine "BEGIN BACKUP"
oVSSCmd.WriteLine "CREATE"
oVSSCmd.WriteLine "EXPOSE %G1% " & strTempDrive
oVSSCmd.Close
objStream.Writeline((Now) & " --- " & "Create DiskShadow Commands Complete")
wscript.sleep 1000
objExplorer.Document.Body.InnerHTML = "Creating DiskShadow Commands Complete<br>"
_
& "<img src="".\indicator_square.gif"" />"
'=============================================================================
'Create Shadow Copy Script
'=============================================================================
objStream.Writeline((Now) & " --- " & "Create DiskShadow Scripts")
objExplorer.Document.Body.InnerHTML = "Creating DiskShadow Scripts<br>" _
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 1000
sVSSScript = "CreateVSS.cmd"
Set oFileSys = CreateObject("Scripting.FileSystemObject")
if oFileSys.FileExists(sVSSScript) then oFileSys.DeleteFile(sVSSScript)
set oVSSScript = oFileSys.CreateTextFile(sVSSScript, CopyOverwrite)
oVSSScript.WriteLine "diskshadow /s " & strFolder & "\" & sVSSCmd
oVSSScript.Close
objStream.Writeline((Now) & " --- " & "Create DiskShadow Scripts Complete")
objExplorer.Document.Body.InnerHTML = "Creating DiskShadow Scripts Complete<br>"
_
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 1000
'=============================================================================
'Create Shadow Copy
'=============================================================================
objStream.Writeline((Now) & " --- " & "Running DiskShadow Scripts")
objExplorer.Document.Body.InnerHTML = "Running DiskShadow Scripts<br>" _
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 1000
Result = objShell.run(sVSSScript,1, TRUE)
objStream.Writeline((Now) & " --- " & "DiskShadow Scripts Completed")
objExplorer.Document.Body.InnerHTML = "DiskShadow Scripts Completed<br>" _
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 1000
'=============================================================================
'Start Saved VMs
'=============================================================================
objStream.Writeline((Now) & " --- Starting Saved VMs")
objExplorer.Document.Body.InnerHTML = "Starting Saved VMs <br>" _
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 5000
Set WMIObject = GetObject("winmgmts:\\.\root\virtualization")
Set VMList = WMIObject.ExecQuery("SELECT * FROM Msvm_ComputerSystem")
For Each VM In VMList
If VM.Caption = "Virtual Machine" then
VMName = VM.ElementName
checkVMState()
If VM.EnabledState = 32769 then
wscript.sleep 1000
VM.RequestStateChange(2)
Do While theVM <> 2
checkVMState()
'Wscript.echo theVM
WScript.Sleep 5000
Loop
End if
End if
Next
'=============================================================================
'Robocopy VMs
'=============================================================================
objStream.Writeline((Now) & " --- " & "Running Robocopy Script")
objExplorer.Document.Body.InnerHTML = "Running Robocopy Script<br>" _
& "<img src="".\indicator_square.gif"" />"
sExCmd = "cmd /c robocopy.exe """ & strTempDrive & "\" & strVMfolder & """ """ &
strBackupDir & """ /e /r:10 /w:60 /nfl /purge /log:" & strRoboLog & ""
Result = objShell.run(sExCmd,1, TRUE)
objStream.Writeline((Now) & " --- " & "Robocopy Script Completed")
objExplorer.Document.Body.InnerHTML = "Robocopy Script Completed<br>" _
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 1000
'=============================================================================
'Create Delete Shadow Copy Commands
'=============================================================================
objStream.Writeline((Now) & " --- " & "Create Delete Shadow Copy Commands")
objExplorer.Document.Body.InnerHTML = "Creating Delete Shadow Copy Commands<br>"
_
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 5000
sDVSSCmd = "DeleteVSS.dsh"
Set oFileSys = CreateObject("Scripting.FileSystemObject")
if oFileSys.FileExists(sDVSSCmd) then oFileSys.DeleteFile(sDVSSCmd)
set oDeleteVSSCmd = oFileSys.CreateTextFile(sDVSSCmd, CopyOverwrite)
oDeleteVSSCmd.WriteLine "DELETE SHADOWS ALL"
oDeleteVSSCmd.WriteLine "END BACKUP"
oDeleteVSSCmd.Close
objStream.Writeline((Now) & " --- " & "Create Delete Shadow Copy Commands
Complete")
objExplorer.Document.Body.InnerHTML = "Creating Delete Shadow Copy Commands
Complete<br>" _
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 1000
'=============================================================================
'Create Shadow Copy Delete Script
'=============================================================================
objStream.Writeline((Now) & " --- " & "Create Shadow Copy Delete Script")
objExplorer.Document.Body.InnerHTML = "Creating Shadow Copy Delete Script<br>" _
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 5000
sVSSDelScript = "DeleteVSS.cmd"
Set oFileSys = CreateObject("Scripting.FileSystemObject")
if oFileSys.FileExists(sVSSDelScript) then oFileSys.DeleteFile(sVSSDelScript)
set oVSSScript = oFileSys.CreateTextFile(sVSSDelScript, CopyOverwrite)
oVSSScript.WriteLine "diskshadow /s " & strFolder & "\" & sDVSSCmd
oVSSScript.Close
objStream.Writeline((Now) & " --- " & "Create Shadow Delete Script Complete")
objExplorer.Document.Body.InnerHTML = "Creating Shadow Delete Script Complete<br>"
_
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 1000
'=============================================================================
'Delete Shadow Copy
'=============================================================================
objStream.Writeline((Now) & " --- " & "Delete Shadow Copy ")
objExplorer.Document.Body.InnerHTML = "Deleting Shadow Copy<br>" _
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 5000
Result = objShell.run(sVSSDelScript,1, TRUE)
objStream.Writeline((Now) & " --- " & "Delete Shadow Copy Script Completed")
objExplorer.Document.Body.InnerHTML = "Deleting Shadow Copy Completed<br>" _
& "<img src="".\indicator_square.gif"" />"
wscript.sleep 1000
'=============================================================================
'Backup should now be finished,
'=============================================================================
objStream.Writeline((Now) & " --- " & "Backup should now be finished, Emailing
this Log File")
objExplorer.Document.Body.InnerHTML = "Backup should now be finished, Emailing
the Log File<br>" _
& "<img src="".\indicator_square.gif"" />"
objStream.Writeline((Now) & " --- " & "Robocopy Log is below.")
wscript.sleep 5000
objStream.close
'=============================================================================
'Combine Log Files
'=============================================================================
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objOutputFile = objFSO.CreateTextFile(strLogFile)
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set FileList = objWMIService.ExecQuery _
("ASSOCIATORS OF {Win32_Directory.Name='" & strLogFolder & "'} Where " _
& "ResultClass = CIM_DataFile")
For Each objFile In FileList
Set objTextFile = objFSO.OpenTextFile(objFile.Name, ForReading)
strText = objTextFile.ReadAll
objTextFile.Close
objOutputFile.WriteLine strText
Next
objOutputFile.Close
'=============================================================================
'Email Log File
'=============================================================================
Set objEmail = CreateObject("CDO.Message")
objEmail.From = strEmailFrom
objEmail.To = strEmailTo
objEmail.Subject = strDate & " VM Backups "
objEmail.AddAttachment strLogFile
objEmail.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objEmail.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserver") = _
StrSMTP
objEmail.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objEmail.Configuration.Fields.Update
objEmail.Send
sBOINCCmd = "cmd /c net start boinc"
Result = objShell.run(sBOINCCmd,1, TRUE)
'=============================================================================
'Subs and what not
'=============================================================================
wscript.sleep 1000
objExplorer.Quit
oFileSys.DeleteFile(sVSSCmd)
oFileSys.DeleteFile(sVSSDelScript)
oFileSys.DeleteFile(sVSSScript)
oFileSys.DeleteFile(sDVSSCmd)
wscript.quit
sub checkVMState()
Set WMIObject = GetObject("winmgmts:\\.\root\virtualization")
Set VMCurrent = WMIObject.ExecQuery("SELECT * FROM Msvm_ComputerSystem WHERE
ElementName='" & VMName & "'")
For Each currentVM In VMCurrent
theVM = VMCurrent.ItemIndex(0).EnabledState
Next
Select Case theVM
Case 0
objStream.Writeline((Now) & " --- " & VMName & "'s State is unknown")
objExplorer.Document.Body.InnerHTML = VMName & "'s State is unknown<br>" _
& "<img src="".\indicator_square.gif"" />"
Case 2
objStream.Writeline((Now) & " --- " & VMName & " is Started")
objExplorer.Document.Body.InnerHTML = VMName & " is Started<br>" _
& "<img src="".\indicator_square.gif"" />"
Case 3
objStream.Writeline((Now) & " --- " & VMName & " is Stopped")
objExplorer.Document.Body.InnerHTML = VMName & " is Stopped<br>" _
& "<img src="".\indicator_square.gif"" />"
Case 32768
objStream.Writeline((Now) & " --- " & VMName & " is Paused")
objExplorer.Document.Body.InnerHTML = VMName & " is Paused<br>" _
& "<img src="".\indicator_square.gif"" />"
Case 32769
objStream.Writeline((Now) & " --- " & VMName & " is Suspended")
objExplorer.Document.Body.InnerHTML = VMName & " is Suspended<br>" _
& "<img src="".\indicator_square.gif"" />"
Case 32770
objStream.Writeline((Now) & " --- " & VMName & " is Starting")
objExplorer.Document.Body.InnerHTML = VMName & " is Starting<br>" _
& "<img src="".\indicator_square.gif"" />"
Case 32771
objStream.Writeline((Now) & " --- " & VMName & " is Snapshotting")
objExplorer.Document.Body.InnerHTML = VMName & " is Snapshotting<br>" _
& "<img src="".\indicator_square.gif"" />"
Case 32772
objStream.Writeline((Now) & " --- " & VMName & " is Migrating")
objExplorer.Document.Body.InnerHTML = VMName & " is Migrating<br>" _
& "<img src="".\indicator_square.gif"" />"
Case 32773
objStream.Writeline((Now) & " --- " & VMName & " is Saving")
objExplorer.Document.Body.InnerHTML = VMName & " is Saving<br>" _
& "<img src="".\indicator_square.gif"" />"
Case 32774
objStream.Writeline((Now) & " --- " & VMName & " is Stopping")
objExplorer.Document.Body.InnerHTML = VMName & " is Stopping<br>" _
& "<img src="".\indicator_square.gif"" />"
Case 32775
objStream.Writeline((Now) & " --- " & VMName & " is Deleted")
objExplorer.Document.Body.InnerHTML = VMName & " is Deleted<br>" _
& "<img src="".\indicator_square.gif"" />"
Case 32776
objStream.Writeline((Now) & " --- " & VMName & " is Pausing")
objExplorer.Document.Body.InnerHTML = VMName & " is Started and is now Saving<br>"
_
& "<img src="".\indicator_square.gif"" />"
Case Else
objStream.Writeline((Now) & " --- " & VMName & " is unknown")
objExplorer.Document.Body.InnerHTML = VMName & " is unknown<br>" _
& "<img src="".\indicator_square.gif"" />"
End Select
End sub