diff --git a/Duplicati/Library/Main/Duplicati.Library.Main.csproj b/Duplicati/Library/Main/Duplicati.Library.Main.csproj
index a66515822..fd09f8f5d 100644
--- a/Duplicati/Library/Main/Duplicati.Library.Main.csproj
+++ b/Duplicati/Library/Main/Duplicati.Library.Main.csproj
@@ -41,6 +41,7 @@
+
diff --git a/Duplicati/Library/Snapshots/Duplicati.Library.Snapshots.csproj b/Duplicati/Library/Snapshots/Duplicati.Library.Snapshots.csproj
index 1d48574dd..a5992193d 100644
--- a/Duplicati/Library/Snapshots/Duplicati.Library.Snapshots.csproj
+++ b/Duplicati/Library/Snapshots/Duplicati.Library.Snapshots.csproj
@@ -38,6 +38,7 @@
false
+
..\..\..\packages\NUnit.3.2.1\lib\net45\nunit.framework.dll
True
@@ -63,7 +64,7 @@
-
+
diff --git a/Duplicati/Library/Snapshots/HyperVBackup.cs b/Duplicati/Library/Snapshots/HyperVBackup.cs
deleted file mode 100644
index 978344c8c..000000000
--- a/Duplicati/Library/Snapshots/HyperVBackup.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Management;
-using System.Text;
-
-namespace Duplicati.Library.Snapshots
-{
-
- //Original code: HVBackup Project
- public class HyperVBackup
- {
- private string _wmiQuery;
- private readonly string _wmiScope;
- private readonly string _vmIdField;
- private readonly string _wmiHost = "localhost"; //We could backup remote Hyper-V Machines in the future
- private readonly bool _wmiv2Namespace;
-
- public List RequestedVmNames = new List();
- readonly IDictionary _hyperVMachines = new Dictionary();
-
- public HyperVBackup()
- {
- //Set the namespace depending off host OS
- _wmiv2Namespace = Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 2;
- //Set the scope to use in MWI. V2 for Server 2012 or newer.
- _wmiScope = _wmiv2Namespace ? $"\\\\{_wmiHost}\\root\\virtualization\\v2"
- : $"\\\\{_wmiHost}\\root\\virtualization";
- //Set the VM ID Selector Field for the WMI Query
- _vmIdField = _wmiv2Namespace ? "VirtualSystemIdentifier" : "SystemName";
-
- }
-
- public HyperVBackup(List reqVmNames)
- {
- _wmiv2Namespace = Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 2;
- _wmiScope = _wmiv2Namespace ? $"\\\\{_wmiHost}\\root\\virtualization\\v2"
- : $"\\\\{_wmiHost}\\root\\virtualization";
- _vmIdField = _wmiv2Namespace ? "VirtualSystemIdentifier" : "SystemName";
- //Store requested VM's
- RequestedVmNames = reqVmNames;
- }
-
- public IDictionary GetHyperVMachines()
- {
- //Set the WMI Query according the WMI Namespace
- SetWmiQueryVmidField();
- //We MOSearcher to search for the Hyper-V Machines
- using (ManagementObjectSearcher moSearcher = new ManagementObjectSearcher(new ManagementScope(_wmiScope), new ObjectQuery(_wmiQuery)))
- {
- using (var moCollection = moSearcher.Get())
- foreach (var mObject in moCollection)
- using (mObject)
- _hyperVMachines.Add((string)mObject[_vmIdField], (string)mObject["ElementName"]);
- }
-
- return _hyperVMachines;
- }
-
- private void SetWmiQueryVmidField()
- {
- _wmiQuery = _wmiv2Namespace ? "SELECT VirtualSystemIdentifier, ElementName FROM Msvm_VirtualSystemSettingData WHERE VirtualSystemType = 'Microsoft:Hyper-V:System:Realized'"
- : "SELECT SystemName, ElementName FROM Msvm_VirtualSystemSettingData WHERE SettingType = 3";
-
- //Temporary Stringbuilder to build up the VM selectors
- var sb = new StringBuilder();
-
- if (RequestedVmNames == null || !RequestedVmNames.Any()) return;
- foreach (var vmName in RequestedVmNames)
- {
- if (sb.Length > 0)
- sb.Append(" OR ");
- sb.Append($"ElementName = \'{vmName.Replace("'", "''")}\'");
- }
- _wmiQuery += $" AND ({sb})";
- }
- //private string GetWMIScope(string host = "localhost")
- //{
- // //string scopeFormatStr;
- // //if (IsNameSpaceWMIV2)
- // // scopeFormatStr = "\\\\{0}\\root\\virtualization\\v2";
- // //else
- // // scopeFormatStr = "\\\\{0}\\root\\virtualization";
- // //return (string.Format(scopeFormatStr, host));
- //}
- }
-}
diff --git a/Duplicati/Library/Snapshots/HyperVUtility.cs b/Duplicati/Library/Snapshots/HyperVUtility.cs
new file mode 100644
index 000000000..4ca477b1f
--- /dev/null
+++ b/Duplicati/Library/Snapshots/HyperVUtility.cs
@@ -0,0 +1,270 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Management;
+using System.Text;
+
+using System.Globalization;
+
+namespace Duplicati.Library.Snapshots
+{
+
+ //Original code: HVBackup Project
+ public class HyperVUtility
+ {
+ private string _wmiQuery;
+ private readonly ManagementScope _wmiScope;
+ private readonly string _vmIdField;
+ private readonly string _wmiHost = "localhost"; //We could backup remote Hyper-V Machines in the future
+ private readonly bool _wmiv2Namespace;
+
+ public List RequestedVmNames = new List();
+ readonly IDictionary _hyperVMachines = new Dictionary();
+
+ public HyperVUtility()
+ {
+ //Set the namespace depending off host OS
+ _wmiv2Namespace = Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 2;
+ //Set the scope to use in MWI. V2 for Server 2012 or newer.
+ _wmiScope = _wmiv2Namespace
+ ? new ManagementScope(string.Format("\\\\{0}\\root\\virtualization\\v2", _wmiHost))
+ : new ManagementScope(string.Format("\\\\{0}\\root\\virtualization", _wmiHost));
+ //Set the VM ID Selector Field for the WMI Query
+ _vmIdField = _wmiv2Namespace ? "VirtualSystemIdentifier" : "SystemName";
+
+ }
+
+ public HyperVUtility(List reqVmNames)
+ {
+ _wmiv2Namespace = Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 2;
+ _wmiScope = _wmiv2Namespace
+ ? new ManagementScope(string.Format("\\\\{0}\\root\\virtualization\\v2", _wmiHost))
+ : new ManagementScope(string.Format("\\\\{0}\\root\\virtualization", _wmiHost));
+ _vmIdField = _wmiv2Namespace ? "VirtualSystemIdentifier" : "SystemName";
+ //Store requested VM's
+ RequestedVmNames = reqVmNames;
+ }
+
+ ///
+ /// We query the Hyper-V for all requested Virtual Machines
+ ///
+ /// List of Hyper-V Machines
+ public IDictionary GetHyperVMachines()
+ {
+ ManagementObjectCollection moCollection = GetWmiObjects(WmiQueryHyperVMachines());
+ foreach (ManagementBaseObject mObject in moCollection)
+ using (mObject)
+ _hyperVMachines.Add((string)mObject[_vmIdField], (string)mObject["ElementName"]);
+
+ return _hyperVMachines;
+ }
+
+ ///
+ /// We build up the wmi-query to retrieve all Virtual Machines
+ ///
+ /// WMI query
+ private string WmiQueryHyperVMachines()
+ {
+ string wmiQuery = _wmiv2Namespace
+ ? "SELECT VirtualSystemIdentifier, ElementName FROM Msvm_VirtualSystemSettingData WHERE VirtualSystemType = 'Microsoft:Hyper-V:System:Realized'"
+ : "SELECT SystemName, ElementName FROM Msvm_VirtualSystemSettingData WHERE SettingType = 3";
+
+ //Temporary Stringbuilder to build up the VM selectors
+ var sb = new StringBuilder();
+
+ if (RequestedVmNames == null || !RequestedVmNames.Any()) return null;
+ foreach (var vmName in RequestedVmNames)
+ {
+ if (sb.Length > 0)
+ sb.Append(" OR ");
+ sb.Append(string.Format("ElementName = \'{0}\'", vmName.Replace("'", "''")));
+ }
+ wmiQuery += string.Format(" AND ({0})", sb);
+
+ return wmiQuery;
+ }
+#region Wmi helpers
+ ///
+ /// Executes the WMI Query
+ ///
+ ///
+ /// A collection of results
+ private ManagementObjectCollection GetWmiObjects(string query)
+ {
+ ManagementObjectSearcher moSearcher = new ManagementObjectSearcher(_wmiScope, new ObjectQuery(query));
+ ManagementObjectCollection resultset = moSearcher.Get();
+ return resultset;
+ }
+#endregion Wmi helpers
+
+
+
+
+
+
+#region Recovery Virtual Machines
+ public void CreateHyperVMachine()
+ {
+ ManagementObject sysMan = GetMsVM_VirtualSystemManagementService("MsVM_VirtualSystemManagementService", null);
+ }
+
+ ///
+ /// Please refer to https://blogs.msdn.microsoft.com/sergeim/2008/06/03/prepare-vm-create-vm-programmatically-hyper-v-api-c-version/
+ ///
+ ///
+ ///
+ ///
+ private ManagementObject GetMsVM_VirtualSystemManagementService(string className, string where)
+ {
+ var query = @where != null
+ ? string.Format("select * from {0} where {1}", className, where)
+ : string.Format("select * from {0}", className);
+
+ ManagementObjectCollection resultset = GetWmiObjects(query);
+
+ if (resultset.Count != 1)
+ throw new InvalidOperationException(string.Format("Cannot locate {0} where {1}", className, where));
+
+ try
+ {
+ ManagementObjectCollection.ManagementObjectEnumerator en = resultset.GetEnumerator();
+ en.MoveNext();
+ return en.Current as ManagementObject;
+ }
+ catch (Exception)
+ {
+ throw new InvalidOperationException(string.Format("Failure retrieving {0} where {1}", className, where));
+ }
+ }
+
+ #endregion
+
+ ///
+ /// Please refer to https://blogs.msdn.microsoft.com/sergeim/2008/06/03/prepare-vm-create-vm-programmatically-hyper-v-api-c-version/
+ ///
+ ///
+ ///
+ ///
+ public void CreateVm(string displayName)
+ {
+ string notes = "Created" + DateTime.Now;
+
+ ManagementObject sysMan = GetMsVM_VirtualSystemManagementService();
+ // Create VM with empty settings
+ ManagementBaseObject definition = sysMan.InvokeMethod(Constants.DefineVirtualSystem, sysMan.GetMethodParameters(Constants.DefineVirtualSystem), null); //Empty set
+ uint retCode = (uint)definition["returnvalue"];
+
+ if (retCode != Constants.ERROR_SUCCESS)
+ throw new InvalidOperationException("DefineVirtualSystem failed");
+
+ // Obtain WMI root\virtualization:ComputerSystem object.
+ // we will need "Name" of it, which is GUID
+
+ string vmPath = definition["DefinedSystem"] as string;
+ ManagementObject computerSystemTemplate = new ManagementObject(vmPath);
+ string vmName = (string)computerSystemTemplate["name"];
+
+ // this is GUID; will need to locate settings for this VM
+ ManagementObject settings = GetMsvm_VirtualSystemSettingData(vmName);
+
+ // Now, set settings of this MSVM_ComputerSystem as we like
+
+ settings["elementname"] = displayName;
+ settings["notes"] = notes;
+ settings["BIOSGUID"] = new Guid();
+ settings["BIOSSerialNumber"] = "1234567890";
+ settings["BIOSNumLock"] = "true";
+
+ // settings["…"] = …;
+ // … set whatever you like; see list at
+ // http://msdn.microsoft.com/en-us/library/cc136944(VS.85).aspx
+
+ settings.Put();
+
+ // Now, set the settings which were build above to newly created ComputerSystem
+ ManagementBaseObject inParams = sysMan.GetMethodParameters(Constants.ModifyVirtualSystem);
+ string settingsText = settings.GetText(TextFormat.WmiDtd20);
+ inParams["ComputerSystem"] = computerSystemTemplate;
+ inParams["SystemSettingData"] = settingsText;
+ ManagementBaseObject resultToCheck = sysMan.InvokeMethod(Constants.ModifyVirtualSystem, inParams, null);
+
+ // Almost done – now apply the settings to newly created ComputerSystem
+ ManagementObject settingsAsSet = (ManagementObject)resultToCheck["ModifiedSettingData"];
+
+ // Optionally print settingsAsSet here
+
+ Log(string.Format("Created: VM with name {0} and GUID name {1}", displayName, vmName));
+
+ } // CreateVm
+
+ private ManagementObject GetMsVM_VirtualSystemManagementService()
+ {
+ return GetWmiObject("MsVM_VirtualSystemManagementService", null);
+ }
+
+ private ManagementObject GetMsvm_VirtualSystemSettingData(string vmName)
+ {
+ return GetWmiObject("Msvm_VirtualSystemSettingData", string.Format("systemname = '{0}'", vmName));
+ }
+
+ #region Wmi Helpers
+
+ private ManagementObject GetWmiObject(string classname, string where)
+ {
+ ManagementObjectCollection resultset = GetWmiObjects(classname, where);
+
+ if (resultset.Count != 1)
+ throw new InvalidOperationException(string.Format("Cannot locate {0} where {1}", classname, where));
+
+ ManagementObjectCollection.ManagementObjectEnumerator en = resultset.GetEnumerator();
+ en.MoveNext();
+ ManagementObject result = en.Current as ManagementObject;
+
+ if (result == null) throw new InvalidOperationException("Failure retrieving " +classname + " where " +where);
+
+ return result;
+ }
+
+ private ManagementObjectCollection GetWmiObjects(string className, string where)
+ {
+ string query;
+ ManagementScope scope = new ManagementScope(@"root\virtualization", null);
+ if (where != null)
+ {
+ query = string.Format("select * from {0} where {1}", className, where);
+ } else {
+ query = string.Format("select * from {0}", className);
+ }
+
+ ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, new ObjectQuery(query));
+ ManagementObjectCollection resultset = searcher.Get();
+ return resultset;
+ }
+ #endregion Wmi helpers
+
+ private static void Log(string message, params object[] data)
+ {
+ Console.WriteLine(message, data);
+ }
+
+ private static void Oops(object sender, UnhandledExceptionEventArgs e)
+ {
+ Console.BackgroundColor = ConsoleColor.White;
+ Console.ForegroundColor = ConsoleColor.Black;
+ Exception ex = e.ExceptionObject as Exception;
+ Log(ex.Message);
+ Console.ResetColor();
+ Log(ex.ToString());
+ }
+
+ } // class MainCreateVm
+
+ class Constants
+ {
+ internal const string DefineVirtualSystem = "DefineVirtualSystem";
+ internal const string ModifyVirtualSystem = "ModifyVirtualSystem";
+ internal const uint ERROR_SUCCESS = 0;
+ internal const uint ERROR_INV_ARGUMENTS = 87;
+ }
+}
+
diff --git a/Duplicati/Library/Snapshots/WindowsSnapshot.cs b/Duplicati/Library/Snapshots/WindowsSnapshot.cs
index 011f31fe7..f98cfbd38 100644
--- a/Duplicati/Library/Snapshots/WindowsSnapshot.cs
+++ b/Duplicati/Library/Snapshots/WindowsSnapshot.cs
@@ -115,12 +115,15 @@ namespace Duplicati.Library.Snapshots
//Do not hardcode the VM in the future, the front-end will provide this.
var requestedVMs = new List {"TESTTS-CLNT"};
//Make an hyper V Backup object with the requested VMs
- var hyperVBackup = new HyperVBackup(requestedVMs);
+ var hyperVUtility = new HyperVUtility(requestedVMs);
//Retrieve all information about VMs
- _hyperVMachines = hyperVBackup.GetHyperVMachines();
+ _hyperVMachines = hyperVUtility.GetHyperVMachines();
////Add the HyperV vss-writer; This is already implicitly included in the vss-writers
//Enabling this vss-writer will disable all other vss-writers
//m_backup.EnableWriterClasses(hyperVWriterGuid));
+
+ //attempt to create a vm
+ hyperVUtility.CreateVm("createtest");
}
m_backup.StartSnapshotSet();
@@ -135,17 +138,17 @@ namespace Duplicati.Library.Snapshots
//Gather information on all Vss writers
m_backup.GatherWriterMetadata();
- //If we are backup up Hyper V Machines then we need to update our sourcepaths
+#region HyperVBackup
+ //Update the sourcepaths if we're backing up Hyper-V Machines
if (options.ContainsKey("hyperv-backup-vm"))
{
- //We will need the Hyper-V WriterMetaData to find the corresponding sourcepaths
+ //Find sourcepaths in Hyper-V WriterMetaData
var m_backup_wmd = m_backup.WriterMetadata.FirstOrDefault(o => o.WriterId.Equals(HyperVWriterGuid));
if (m_backup_wmd != null)
foreach (var component in m_backup_wmd.Components)
{
- //For all the components found cross reference the requested Hyper-V Machines to backup
+ //Cross reference the requested Hyper-V Machines to backup and add the sources
if (!_hyperVMachines.ContainsKey(component.ComponentName)) continue;
- //Each component is in fact a Hyper-V Machine, which contains several files.
int m_sourcepathsStartPos = m_sourcepaths.Length;
int i = 0;
Array.Resize(ref m_sourcepaths, m_sourcepaths.Length + component.Files.Count());
@@ -159,7 +162,7 @@ namespace Duplicati.Library.Snapshots
//Now clean up the sourcepaths
m_sourcepaths = m_sourcepaths.Where(x => !string.IsNullOrEmpty(x)).ToArray();
}
-
+#endregion
m_backup.FreeWriterMetadata();
}