Hyper-V Virtual Machine Backup Script using VBS/VBScript
Link to Text File:
hypervbackups-shutdown.txt
'================================================================
'Hyper-V Virtual Machine Backup Script using VBS/VBScript
This Script Shuts down 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-shutdown.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:
'
'This Script assumes all of your VMs are always set to run. I could not find a
way to
'determine if the VM was set to Automatically start with Hyper-V
'
'================================================================
'================================================================
'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"
'OR
'strBackupDir = "F:\Foldername"
'================================================================
'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, 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 = "mailserver"
'****************************************************************
'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"
strCreateVSSLog = strLogFolder & "\vmbackup3CreateVSS.log"
strDeleteVSSLog = strLogFolder & "\vmbackup4DeleteVSS.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
'=============================================================================
'Shutdown Running VMs
'=============================================================================
objStream.Writeline((Now) & " --- Shutdown Running VMs")
objExplorer.Document.Body.InnerHTML = "Shutdown 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
Set vmshut = WMIObject.ExecQuery("SELECT * FROM Msvm_ShutdownComponent WHERE
SystemName='" & VM.Name & "'")
vmReturn = vmshut.ItemIndex(0).InitiateShutdown(True,"Scripted Shutdown")
Do While theVM <> 3
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 & " >" &
strCreateVSSLog & ""
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 " & sVSSScript & " <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 VMs
'We are assuming all VMs need to be started. I cannot find a way to query
'Hyper-V if the VM is set to Automatically start or not.
'=============================================================================
objStream.Writeline((Now) & " --- Starting VMs")
objExplorer.Document.Body.InnerHTML = "Starting 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 60000
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 & " >" &
strDeleteVSSLog & ""
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
wscript.sleep 1000
objExplorer.Quit
oFileSys.DeleteFile(sVSSCmd)
oFileSys.DeleteFile(sVSSDelScript)
oFileSys.DeleteFile(sVSSScript)
oFileSys.DeleteFile(sDVSSCmd)
wscript.quit
'=============================================================================
'Subs and what not
'=============================================================================
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
'wscript.echo theVM
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