mirror of https://github.com/dahall/Vanara.git
VirtualDisk: Added support for mounting specific path or drive when attaching, added properties for mount information, CreateAsync, AttachAsync, VHD set, snapshot and mirror methods.
parent
cc33c451b6
commit
c24dbf8659
|
@ -1,10 +1,13 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.AccessControl;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Vanara.InteropServices;
|
||||
using Vanara.PInvoke.Tests;
|
||||
using static Vanara.PInvoke.Kernel32;
|
||||
using static Vanara.PInvoke.VirtDisk;
|
||||
|
||||
namespace Vanara.IO.Tests
|
||||
|
@ -12,10 +15,10 @@ namespace Vanara.IO.Tests
|
|||
[TestFixture]
|
||||
public class VirtualDiskTests
|
||||
{
|
||||
private static readonly string badfn = Vanara.PInvoke.Tests.TestCaseSources.TempDirWhack + "TestInvalid.vhdx";
|
||||
private static readonly string fn = Vanara.PInvoke.Tests.TestCaseSources.VirtualDisk;
|
||||
private static readonly string tmpcfn = Vanara.PInvoke.Tests.TestCaseSources.TempDirWhack + "TestVHD - Diff.vhd";
|
||||
private static readonly string tmpfn = Vanara.PInvoke.Tests.TestCaseSources.TempDirWhack + "TestVHD.vhd";
|
||||
private static readonly string badfn = TestCaseSources.TempDirWhack + "TestInvalid.vhdx";
|
||||
private static readonly string fn = TestCaseSources.VirtualDisk;
|
||||
private static readonly string tmpcfn = TestCaseSources.TempDirWhack + "TestVHD - Diff.vhd";
|
||||
private static readonly string tmpfn = TestCaseSources.TempDirWhack + "TestVHD.vhd";
|
||||
|
||||
[Test]
|
||||
public async Task CompactAsync1Test()
|
||||
|
@ -34,7 +37,7 @@ namespace Vanara.IO.Tests
|
|||
using var vhd = VirtualDisk.Open(fn, false);
|
||||
var rpt = new Reporter();
|
||||
rpt.NewVal += (o, e) => TestContext.WriteLine($"{DateTime.Now:o} NewVal={e}");
|
||||
await vhd.CompactAsync(VirtualDisk.CompactionMode.Quick, default, rpt);
|
||||
await vhd.CompactAsync(VirtualDisk.CompactionMode.Full, default, rpt);
|
||||
Assert.That(rpt.lastVal, Is.EqualTo(100));
|
||||
}
|
||||
|
||||
|
@ -58,9 +61,9 @@ namespace Vanara.IO.Tests
|
|||
finally
|
||||
{
|
||||
var fn2 = fn.TrimEnd('x');
|
||||
while (System.IO.File.Exists(fn2))
|
||||
while (File.Exists(fn2))
|
||||
{
|
||||
try { System.IO.File.Delete(fn2); } catch { Thread.Sleep(500); }
|
||||
try { File.Delete(fn2); } catch { Thread.Sleep(500); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,9 +76,9 @@ namespace Vanara.IO.Tests
|
|||
{
|
||||
using var vhdp = VirtualDisk.Create(tmpfn, sz);
|
||||
using var vhd = VirtualDisk.CreateDifferencing(tmpcfn, tmpfn);
|
||||
Assert.That(System.IO.File.Exists(tmpcfn));
|
||||
Assert.That(System.IO.File.Exists(tmpfn));
|
||||
Assert.That(System.IO.File.Exists(tmpfn));
|
||||
Assert.That(File.Exists(tmpcfn));
|
||||
Assert.That(File.Exists(tmpfn));
|
||||
Assert.That(File.Exists(tmpfn));
|
||||
Assert.That(vhd.Attached, Is.False);
|
||||
Assert.That(vhd.BlockSize, Is.EqualTo(0x200000));
|
||||
Assert.That(vhd.DiskType, Is.EqualTo(VirtualDisk.DeviceType.Vhd));
|
||||
|
@ -107,8 +110,8 @@ namespace Vanara.IO.Tests
|
|||
}
|
||||
finally
|
||||
{
|
||||
System.IO.File.Delete(tmpcfn);
|
||||
System.IO.File.Delete(tmpfn);
|
||||
File.Delete(tmpcfn);
|
||||
File.Delete(tmpfn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +123,7 @@ namespace Vanara.IO.Tests
|
|||
{
|
||||
using var vhd = VirtualDisk.Create(tmpfn, sz);
|
||||
//vhd.Attach(true);
|
||||
Assert.That(System.IO.File.Exists(tmpfn));
|
||||
Assert.That(File.Exists(tmpfn));
|
||||
Assert.That(vhd.Attached, Is.False);
|
||||
Assert.That(vhd.BlockSize, Is.GreaterThan(0));
|
||||
Assert.That(vhd.DiskType, Is.EqualTo(VirtualDisk.DeviceType.Vhd));
|
||||
|
@ -151,7 +154,7 @@ namespace Vanara.IO.Tests
|
|||
}
|
||||
finally
|
||||
{
|
||||
System.IO.File.Delete(tmpfn);
|
||||
File.Delete(tmpfn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,29 +165,14 @@ namespace Vanara.IO.Tests
|
|||
try
|
||||
{
|
||||
using var vhd = VirtualDisk.Create(tmpfn, sz, false, null);
|
||||
Assert.That(System.IO.File.Exists(tmpfn));
|
||||
Assert.That(File.Exists(tmpfn));
|
||||
Assert.That(vhd.PhysicalSize, Is.GreaterThanOrEqualTo(sz));
|
||||
Assert.That(vhd.ProviderSubtype, Is.EqualTo(VirtualDisk.Subtype.Fixed));
|
||||
Assert.That(vhd.VirtualSize, Is.EqualTo(sz));
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.IO.File.Delete(tmpfn);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateFromSourceTest()
|
||||
{
|
||||
try
|
||||
{
|
||||
using var vhd = VirtualDisk.CreateFromSource(tmpfn, fn);
|
||||
Assert.That(System.IO.File.Exists(tmpfn));
|
||||
vhd.Close();
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.IO.File.Delete(tmpfn);
|
||||
File.Delete(tmpfn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,35 +186,28 @@ namespace Vanara.IO.Tests
|
|||
rpt.NewVal += (o, e) => TestContext.WriteLine($"{DateTime.Now:o} NewVal={e}");
|
||||
vd = await VirtualDisk.CreateFromSourceAsync(tmpfn, fn, default, rpt);
|
||||
Assert.That(rpt.lastVal, Is.EqualTo(100));
|
||||
Assert.That(System.IO.File.Exists(tmpfn));
|
||||
TestContext.WriteLine($"New file sz: {new System.IO.FileInfo(tmpfn).Length}");
|
||||
Assert.That(File.Exists(tmpfn));
|
||||
TestContext.WriteLine($"New file sz: {new FileInfo(tmpfn).Length}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
vd?.Close();
|
||||
try { System.IO.File.Delete(tmpfn); } catch { }
|
||||
try { File.Delete(tmpfn); } catch { }
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DetachTest()
|
||||
public void CreateFromSourceTest()
|
||||
{
|
||||
const int sz = 0x03010400;
|
||||
try
|
||||
{
|
||||
using (var vhd = VirtualDisk.Create(tmpfn, sz))
|
||||
{
|
||||
Assert.That(vhd.Attached, Is.False);
|
||||
vhd.Attach(true, false, true, null);
|
||||
Assert.That(vhd.Attached, Is.True);
|
||||
}
|
||||
Assert.That(VirtualDisk.IsAttached(tmpfn), Is.True);
|
||||
Assert.That(() => VirtualDisk.Detach(tmpfn), Throws.Nothing);
|
||||
Assert.That(VirtualDisk.IsAttached(tmpfn), Is.False);
|
||||
using var vhd = VirtualDisk.CreateFromSource(tmpfn, fn);
|
||||
Assert.That(File.Exists(tmpfn));
|
||||
vhd.Close();
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.IO.File.Delete(tmpfn);
|
||||
File.Delete(tmpfn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,14 +218,14 @@ namespace Vanara.IO.Tests
|
|||
try
|
||||
{
|
||||
using var vhd = VirtualDisk.Create(tmpfn, sz, true, null);
|
||||
Assert.That(System.IO.File.Exists(tmpfn));
|
||||
Assert.That(File.Exists(tmpfn));
|
||||
Assert.That(vhd.VirtualSize, Is.EqualTo(sz));
|
||||
vhd.Expand(sz * 2);
|
||||
Assert.That(vhd.VirtualSize, Is.EqualTo(sz * 2));
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.IO.File.Delete(tmpfn);
|
||||
File.Delete(tmpfn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,7 +272,7 @@ namespace Vanara.IO.Tests
|
|||
}
|
||||
finally
|
||||
{
|
||||
System.IO.File.Delete(lfn);
|
||||
File.Delete(lfn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -309,7 +290,44 @@ namespace Vanara.IO.Tests
|
|||
}
|
||||
finally
|
||||
{
|
||||
System.IO.File.Delete(lfn);
|
||||
File.Delete(lfn);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetVHDSetInformationTestAsync()
|
||||
{
|
||||
var newfn = tmpfn + "s";
|
||||
try
|
||||
{
|
||||
using VirtualDisk vhd = await MakeSet();
|
||||
VirtualDiskSetInformation si = default;
|
||||
Assert.That(() => si = vhd.GetVHDSetInformation(), Throws.Nothing);
|
||||
Assert.That(si?.Path, Is.Not.Null);
|
||||
vhd.Close();
|
||||
foreach (FileInfo a in si.AllPaths.Select(s => new FileInfo(Path.Combine(Path.GetDirectoryName(newfn), s))).OrderByDescending(f => f.CreationTime))
|
||||
//await VirtualDisk.MergeAsync(a.FullName, newfn);
|
||||
File.Delete(a.FullName);
|
||||
}
|
||||
finally
|
||||
{
|
||||
File.Delete(newfn);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<VirtualDisk> MakeSet()
|
||||
{
|
||||
var newfn = tmpfn + "x";
|
||||
File.Copy(fn, newfn);
|
||||
try
|
||||
{
|
||||
await VirtualDisk.ConvertToVHDSetAsync(newfn);
|
||||
Assert.That(File.Exists(tmpfn + "s"));
|
||||
return VirtualDisk.Open(tmpfn + "s", false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
File.Delete(newfn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,15 +338,15 @@ namespace Vanara.IO.Tests
|
|||
try
|
||||
{
|
||||
using (var vhdp = VirtualDisk.Create(tmpfn, sz))
|
||||
Assert.That(System.IO.File.Exists(tmpfn));
|
||||
Assert.That(File.Exists(tmpfn));
|
||||
using var vhd = VirtualDisk.CreateDifferencing(tmpcfn, tmpfn);
|
||||
Assert.That(System.IO.File.Exists(tmpcfn));
|
||||
Assert.That(File.Exists(tmpcfn));
|
||||
vhd.Merge(1, 2);
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.IO.File.Delete(tmpcfn);
|
||||
System.IO.File.Delete(tmpfn);
|
||||
File.Delete(tmpcfn);
|
||||
File.Delete(tmpfn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,18 +357,32 @@ namespace Vanara.IO.Tests
|
|||
try
|
||||
{
|
||||
using (var vhdp = VirtualDisk.Create(tmpfn, sz))
|
||||
Assert.That(System.IO.File.Exists(tmpfn));
|
||||
Assert.That(File.Exists(tmpfn));
|
||||
using var vhd = VirtualDisk.CreateDifferencing(tmpcfn, tmpfn);
|
||||
Assert.That(System.IO.File.Exists(tmpcfn));
|
||||
Assert.That(File.Exists(tmpcfn));
|
||||
vhd.MergeWithParent();
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.IO.File.Delete(tmpcfn);
|
||||
System.IO.File.Delete(tmpfn);
|
||||
File.Delete(tmpcfn);
|
||||
File.Delete(tmpfn);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MirrorTestAsync()
|
||||
{
|
||||
var mvhd = TestCaseSources.TempDirWhack + "mirror.vhdx";
|
||||
using (var vhd = VirtualDisk.Open(fn, true))
|
||||
{
|
||||
vhd.MirrorAsync(mvhd).Wait();
|
||||
Assert.That(File.Exists(mvhd));
|
||||
vhd.BreakMirror();
|
||||
}
|
||||
Task.Delay(500);
|
||||
File.Delete(mvhd);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OpenAttachRawTest()
|
||||
{
|
||||
|
@ -373,23 +405,56 @@ namespace Vanara.IO.Tests
|
|||
[Test]
|
||||
public void OpenAttachTest()
|
||||
{
|
||||
using var vhd = VirtualDisk.Open(fn, true);
|
||||
Assert.That(vhd.Attached, Is.False);
|
||||
var beforeDrives = GetLogicalDrives();
|
||||
vhd.Attach("T:\\", true, true, GetWorldFullFileSecurity());
|
||||
Assert.That(vhd.Attached, Is.True);
|
||||
Assert.That(beforeDrives, Is.Not.EqualTo(GetLogicalDrives()));
|
||||
TestContext.WriteLine(vhd.PhysicalPath);
|
||||
TestContext.WriteLine(vhd.VolumeGuidPath);
|
||||
TestContext.WriteLine(vhd.VolumeMountPoint);
|
||||
Assert.That(vhd.PhysicalPath, Is.Not.Null); // must be attached
|
||||
vhd.Detach();
|
||||
Assert.That(vhd.Attached, Is.False);
|
||||
vhd.Attach(true, true, true);
|
||||
Assert.That(vhd.Attached, Is.True);
|
||||
Assert.That(beforeDrives, Is.EqualTo(GetLogicalDrives()));
|
||||
vhd.Close();
|
||||
Assert.That(vhd.Attached, Is.False);
|
||||
}
|
||||
|
||||
/*[Test]
|
||||
public void SetSnapshotInformationAsyncTest()
|
||||
{
|
||||
var vhd = MakeSet().Result;
|
||||
var newfn = vhd.ImagePath;
|
||||
vhd.Dispose();
|
||||
try
|
||||
{
|
||||
using var vhd = VirtualDisk.Open(fn, true);
|
||||
Assert.That(vhd.Attached, Is.False);
|
||||
vhd.Attach(true, true, false, GetWorldFullFileSecurity());
|
||||
Assert.That(vhd.Attached, Is.True);
|
||||
TestContext.WriteLine(vhd.PhysicalPath);
|
||||
Assert.That(vhd.PhysicalPath, Is.Not.Null); // must be attached
|
||||
vhd.Detach();
|
||||
Assert.That(vhd.Attached, Is.False);
|
||||
vhd.Attach();
|
||||
Assert.That(vhd.Attached, Is.True);
|
||||
vhd.Close();
|
||||
Assert.That(vhd.Attached, Is.False);
|
||||
VirtualDisk.SetSnapshotInformationAsync(new VirtualDiskSnapshotInformation(newfn, Guid.NewGuid())).Wait();
|
||||
}
|
||||
finally
|
||||
{
|
||||
File.Delete(newfn);
|
||||
}
|
||||
}*/
|
||||
|
||||
// [Test] Don't know how to create a file that shows query changes
|
||||
public void QueryChangesTest()
|
||||
{
|
||||
using var vhd = MakeSet().Result;
|
||||
var newfn = vhd.ImagePath;
|
||||
try
|
||||
{
|
||||
vhd.ResilientChangeTrackingEnabled = true;
|
||||
vhd.TakeSnapshot(Guid.NewGuid(), true);
|
||||
QUERY_CHANGES_VIRTUAL_DISK_RANGE[] chgs = vhd.QueryChanges("rctX:e59e6991:208a:44d9:ae6a:2f14351d792f:00000000");
|
||||
}
|
||||
finally
|
||||
{
|
||||
vhd.Dispose();
|
||||
File.Delete(newfn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,17 +476,56 @@ namespace Vanara.IO.Tests
|
|||
try
|
||||
{
|
||||
using var vhd = VirtualDisk.Create(tmpfn, sz, true, null);
|
||||
Assert.That(System.IO.File.Exists(tmpfn));
|
||||
Assert.That(File.Exists(tmpfn));
|
||||
Assert.That(vhd.VirtualSize, Is.EqualTo(sz));
|
||||
vhd.Resize(sz * 2);
|
||||
Assert.That(vhd.VirtualSize, Is.EqualTo(sz * 2));
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.IO.File.Delete(tmpfn);
|
||||
File.Delete(tmpfn);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SnapshotTest()
|
||||
{
|
||||
VirtualDisk vhd = await MakeSet();
|
||||
var newfn = vhd.ImagePath;
|
||||
try
|
||||
{
|
||||
var id = Guid.NewGuid();
|
||||
vhd.TakeSnapshot(id);
|
||||
vhd.DeleteSnapshot(id);
|
||||
}
|
||||
finally
|
||||
{
|
||||
vhd?.Dispose();
|
||||
File.Delete(newfn);
|
||||
}
|
||||
}
|
||||
|
||||
/*[Test]
|
||||
public void GetSnapshotInformationTest()
|
||||
{
|
||||
var vhd = MakeSet().Result;
|
||||
var newfn = vhd.ImagePath;
|
||||
try
|
||||
{
|
||||
var id = Guid.NewGuid();
|
||||
vhd.TakeSnapshot(id);
|
||||
vhd.Dispose();
|
||||
vhd = null;
|
||||
var si = VirtualDisk.GetSnapshotInformation(newfn, id);
|
||||
Assert.That(si.FilePath, Is.Not.Null);
|
||||
}
|
||||
finally
|
||||
{
|
||||
vhd?.Dispose();
|
||||
File.Delete(newfn);
|
||||
}
|
||||
}*/
|
||||
|
||||
[Test]
|
||||
public void UnsafeResizeTest()
|
||||
{
|
||||
|
@ -429,13 +533,13 @@ namespace Vanara.IO.Tests
|
|||
try
|
||||
{
|
||||
using var vhd = VirtualDisk.Create(tmpfn, sz * 2, true, null);
|
||||
Assert.That(System.IO.File.Exists(tmpfn));
|
||||
Assert.That(File.Exists(tmpfn));
|
||||
Assert.That(vhd.VirtualSize, Is.EqualTo(sz * 2));
|
||||
Assert.That(() => vhd.UnsafeResize(sz), Throws.Exception);
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.IO.File.Delete(tmpfn);
|
||||
File.Delete(tmpfn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -452,6 +556,12 @@ namespace Vanara.IO.Tests
|
|||
Assert.That(!res);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ValidatePersistentReservationSupportTest()
|
||||
{
|
||||
Assert.That(VirtualDisk.ValidatePersistentReservationSupport(fn), Is.False);
|
||||
}
|
||||
|
||||
private static FileSecurity GetFileSecurity(string sddl)
|
||||
{
|
||||
var sd = new FileSecurity();
|
||||
|
|
|
@ -1,154 +1,282 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Vanara.Management;
|
||||
using Vanara.Management;
|
||||
|
||||
namespace Vanara.IO
|
||||
namespace Vanara.IO;
|
||||
|
||||
public partial class VirtualDisk
|
||||
{
|
||||
public partial class VirtualDisk
|
||||
private static readonly System.Management.ManagementScope scope = new(@"root\virtualization\v2", null);
|
||||
|
||||
/// <summary>Compaction options for <see cref="CompactAsync(CompactionMode, CancellationToken, IProgress{int})"/>.</summary>
|
||||
public enum CompactionMode : ushort
|
||||
{
|
||||
private static readonly System.Management.ManagementScope scope = new(@"root\virtualization\v2", null);
|
||||
/// <summary>Full.</summary>
|
||||
Full = 0,
|
||||
|
||||
/// <summary>Compaction options for <see cref="CompactAsync(CompactionMode, CancellationToken, IProgress{int})"/>.</summary>
|
||||
public enum CompactionMode : ushort
|
||||
/// <summary>Quick.</summary>
|
||||
Quick,
|
||||
|
||||
/// <summary>Retrimmed</summary>
|
||||
Retrim,
|
||||
|
||||
/// <summary>Pretrimmed</summary>
|
||||
Pretrimmed,
|
||||
|
||||
/// <summary>Prezeroed</summary>
|
||||
Prezeroed
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an existing virtual hard disk to a different type or format. This method creates a new virtual hard disk and does not
|
||||
/// convert the source virtual hard disk in place.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// The fully qualified path of the source virtual hard disk file to convert. This file will not be modified as a result of this operation.
|
||||
/// </param>
|
||||
/// <param name="targetType">The format for the target virtual hard disk.</param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token that can be used to cancel the operation. This value can be <see cref="CancellationToken.None"/> to disable cancellation.
|
||||
/// </param>
|
||||
/// <param name="progress">
|
||||
/// A class that implements <see cref="IProgress{T}"/> that can be used to report on progress. This value can be <c>null</c> to disable
|
||||
/// progress reporting.
|
||||
/// </param>
|
||||
public static async Task ConvertAsync(string path, DeviceType targetType, CancellationToken cancellationToken = default, IProgress<int> progress = default)
|
||||
{
|
||||
var dest = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(path), $"{System.IO.Path.GetFileNameWithoutExtension(path)}.{targetType.ToString().ToLower()}");
|
||||
if (string.Equals(path, dest, StringComparison.InvariantCultureIgnoreCase))
|
||||
return;
|
||||
VirtualDisk vhd = Open(path, true, true);
|
||||
Subtype subType = vhd.ProviderSubtype;
|
||||
vhd.Close();
|
||||
var data = new VirtualDiskSettingData(subType, targetType, dest);
|
||||
await ConvertAsync(path, data, cancellationToken, progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an existing virtual hard disk to a different type or format. This method creates a new virtual hard disk and does not
|
||||
/// convert the source virtual hard disk in place.
|
||||
/// </summary>
|
||||
/// <param name="sourcePath">
|
||||
/// The fully qualified path of the source virtual hard disk file to convert. This file will not be modified as a result of this operation.
|
||||
/// </param>
|
||||
/// <param name="destinationSettings">The settings, including path, for the target virtual hard disk.</param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token that can be used to cancel the operation. This value can be <see cref="CancellationToken.None"/> to disable cancellation.
|
||||
/// </param>
|
||||
/// <param name="progress">
|
||||
/// A class that implements <see cref="IProgress{T}"/> that can be used to report on progress. This value can be <c>null</c> to disable
|
||||
/// progress reporting.
|
||||
/// </param>
|
||||
public static async Task ConvertAsync(string sourcePath, VirtualDiskSettingData destinationSettings, CancellationToken cancellationToken = default, IProgress<int> progress = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
/// <summary>Full.</summary>
|
||||
Full = 0,
|
||||
|
||||
/// <summary>Quick.</summary>
|
||||
Quick,
|
||||
|
||||
/// <summary>Retrimmed</summary>
|
||||
Retrim,
|
||||
|
||||
/// <summary>Pretrimmed</summary>
|
||||
Pretrimmed,
|
||||
|
||||
/// <summary>Prezeroed</summary>
|
||||
Prezeroed
|
||||
System.Management.ManagementBaseObject output = await scope.CallJobMethodAsync(cancellationToken, progress, "Msvm_ImageManagementService", "ConvertVirtualHardDisk", ("SourcePath", sourcePath), ("VirtualDiskSettingData", destinationSettings.GetInstanceText()));
|
||||
output.GetResultOrThrow(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an existing virtual hard disk to a different type or format. This method creates a new virtual hard disk and does not
|
||||
/// convert the source virtual hard disk in place.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// The fully qualified path of the source virtual hard disk file to convert. This file will not be modified as a result of this operation.
|
||||
/// </param>
|
||||
/// <param name="targetType">The format for the target virtual hard disk.</param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token that can be used to cancel the operation. This value can be <see cref="CancellationToken.None"/> to disable cancellation.
|
||||
/// </param>
|
||||
/// <param name="progress">
|
||||
/// A class that implements <see cref="IProgress{T}"/> that can be used to report on progress. This value can be <c>null</c> to
|
||||
/// disable progress reporting.
|
||||
/// </param>
|
||||
public static async Task ConvertAsync(string path, DeviceType targetType, CancellationToken cancellationToken = default, IProgress<int> progress = default)
|
||||
catch (Exception ex)
|
||||
{
|
||||
var dest = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(path), $"{System.IO.Path.GetFileNameWithoutExtension(path)}.{targetType.ToString().ToLower()}");
|
||||
if (string.Equals(path, dest, StringComparison.InvariantCultureIgnoreCase))
|
||||
return;
|
||||
var vhd = Open(path, true, true);
|
||||
var subType = vhd.ProviderSubtype;
|
||||
vhd.Close();
|
||||
var data = new VirtualDiskSettingData(subType, targetType, dest);
|
||||
await ConvertAsync(path, data, cancellationToken, progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an existing virtual hard disk to a different type or format. This method creates a new virtual hard disk and does not
|
||||
/// convert the source virtual hard disk in place.
|
||||
/// </summary>
|
||||
/// <param name="sourcePath">
|
||||
/// The fully qualified path of the source virtual hard disk file to convert. This file will not be modified as a result of this operation.
|
||||
/// </param>
|
||||
/// <param name="destinationSettings">The settings, including path, for the target virtual hard disk.</param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token that can be used to cancel the operation. This value can be <see cref="CancellationToken.None"/> to disable cancellation.
|
||||
/// </param>
|
||||
/// <param name="progress">
|
||||
/// A class that implements <see cref="IProgress{T}"/> that can be used to report on progress. This value can be <c>null</c> to
|
||||
/// disable progress reporting.
|
||||
/// </param>
|
||||
public static async Task ConvertAsync(string sourcePath, VirtualDiskSettingData destinationSettings, CancellationToken cancellationToken = default, IProgress<int> progress = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Management.ManagementBaseObject output = await scope.CallJobMethodAsync(cancellationToken, progress, "Msvm_ImageManagementService", "ConvertVirtualHardDisk", ("SourcePath", sourcePath), ("VirtualDiskSettingData", destinationSettings.GetInstanceText()));
|
||||
output.GetResultOrThrow(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to convert virtual disk.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Determines whether a virtual hard disk file is valid.</summary>
|
||||
/// <param name="path">
|
||||
/// The fully qualified path of the virtual hard disk file to validate. This file will not be modified as a result of this operation.
|
||||
/// </param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token that can be used to cancel the operation. This value can be <see cref="CancellationToken.None"/> to disable cancellation.
|
||||
/// </param>
|
||||
/// <param name="progress">
|
||||
/// A class that implements <see cref="IProgress{T}"/> that can be used to report on progress. This value can be <c>null</c> to
|
||||
/// disable progress reporting.
|
||||
/// </param>
|
||||
/// <returns><c>true</c> if operation completed without error or cancellation; <c>false</c> otherwise.</returns>
|
||||
public static async Task<bool> ValidateAsync(string path, CancellationToken cancellationToken = default, IProgress<int> progress = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Management.ManagementBaseObject output = await scope.CallJobMethodAsync(cancellationToken, progress, "Msvm_ImageManagementService", "ValidateVirtualHardDisk", ("Path", path));
|
||||
return output.GetResultOrThrow(true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Reduces the size of a virtual hard disk (VHD) backing store file.</summary>
|
||||
/// <param name="mode">The mode.</param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token that can be used to cancel the operation. This value can be <see cref="CancellationToken.None"/> to disable cancellation.
|
||||
/// </param>
|
||||
/// <param name="progress">
|
||||
/// A class that implements <see cref="IProgress{T}"/> that can be used to report on progress. This value can be <c>null</c> to
|
||||
/// disable progress reporting.
|
||||
/// </param>
|
||||
public async Task CompactAsync(CompactionMode mode, CancellationToken cancellationToken = default, IProgress<int> progress = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Management.ManagementBaseObject output = await scope.CallJobMethodAsync(cancellationToken, progress, "Msvm_ImageManagementService", "CompactVirtualHardDisk", ("Path", ImagePath), ("Mode", (ushort)mode));
|
||||
output.GetResultOrThrow(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to compact virtual disk.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Creates a new VHD Set file alongside the existing virtual hard disk.</summary>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token that can be used to cancel the operation. This value can be <see cref="CancellationToken.None"/> to disable cancellation.
|
||||
/// </param>
|
||||
/// <param name="progress">
|
||||
/// A class that implements <see cref="IProgress{T}"/> that can be used to report on progress. This value can be <c>null</c> to
|
||||
/// disable progress reporting.
|
||||
/// </param>
|
||||
public async Task ConvertToVHDSetAsync(CancellationToken cancellationToken = default, IProgress<int> progress = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Management.ManagementBaseObject output = await scope.CallJobMethodAsync(cancellationToken, progress, "Msvm_ImageManagementService", "ConvertVirtualHardDiskToVHDSet", ("VirtualHardDiskPath", ImagePath));
|
||||
output.GetResultOrThrow(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to create virtual disk set file.", ex);
|
||||
}
|
||||
throw new InvalidOperationException("Failed to convert virtual disk.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Converts a virtual hard disk file by creating a new VHD Set file alongside the existing virtual hard disk.</summary>
|
||||
/// <param name="path">The path to the virtual hard disk file. The new VHD Set file will have the same filename but with the .VHDS extension.</param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token that can be used to cancel the operation. This value can be <see cref="CancellationToken.None"/> to disable cancellation.
|
||||
/// </param>
|
||||
/// <param name="progress">
|
||||
/// A class that implements <see cref="IProgress{T}"/> that can be used to report on progress. This value can be <c>null</c> to disable
|
||||
/// progress reporting.
|
||||
/// </param>
|
||||
/// <exception cref="System.InvalidOperationException">Failed to create virtual disk set file.</exception>
|
||||
public static async Task ConvertToVHDSetAsync(string path, CancellationToken cancellationToken = default, IProgress<int> progress = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Management.ManagementBaseObject output = await scope.CallJobMethodAsync(cancellationToken, progress, "Msvm_ImageManagementService", "ConvertVirtualHardDiskToVHDSet", ("VirtualHardDiskPath", path));
|
||||
output.GetResultOrThrow(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to create virtual disk set file.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merges a child virtual hard disk in a differencing chain with one or more parent virtual hard disks in the chain. See Remarks for
|
||||
/// usage restrictions for this method.
|
||||
/// <para>If the user executing this function does not have permission to update the virtual machines, then this function will fail.</para>
|
||||
/// </summary>
|
||||
/// <param name="sourcePath">A fully qualified path that specifies the location of the virtual hard disk file to merge.</param>
|
||||
/// <param name="destPath">
|
||||
/// A fully qualified path that specifies the location of the parent virtual hard disk file into which data is to be merged. This could
|
||||
/// be the immediate parent virtual hard disk of the merging file or the parent disk image a few levels up the differencing chain.
|
||||
/// </param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token that can be used to cancel the operation. This value can be <see cref="CancellationToken.None"/> to disable cancellation.
|
||||
/// </param>
|
||||
/// <param name="progress">
|
||||
/// A class that implements <see cref="IProgress{T}"/> that can be used to report on progress. This value can be <c>null</c> to disable
|
||||
/// progress reporting.
|
||||
/// </param>
|
||||
public static async Task MergeAsync(string sourcePath, string destPath, CancellationToken cancellationToken = default, IProgress<int> progress = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Management.ManagementBaseObject output = await scope.CallJobMethodAsync(cancellationToken, progress, "Msvm_ImageManagementService", "MergeVirtualHardDisk", ("SourcePath", sourcePath), ("DestinationPath", destPath));
|
||||
output.GetResultOrThrow(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to merge virtual disks.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Optimizes a VHD Set file to use less disk space.</summary>
|
||||
/// <param name="path">A fully-qualified path that specifies the location of the VHD Set file.</param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token that can be used to cancel the operation. This value can be <see cref="CancellationToken.None"/> to disable cancellation.
|
||||
/// </param>
|
||||
/// <param name="progress">
|
||||
/// A class that implements <see cref="IProgress{T}"/> that can be used to report on progress. This value can be <c>null</c> to disable
|
||||
/// progress reporting.
|
||||
/// </param>
|
||||
/// <exception cref="System.InvalidOperationException">Failed to create virtual disk set file.</exception>
|
||||
public static async Task OptimizeVHDSetAsync(string path, CancellationToken cancellationToken = default, IProgress<int> progress = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Management.ManagementBaseObject output = await scope.CallJobMethodAsync(cancellationToken, progress, "Msvm_ImageManagementService", "OptimizeVHDSet", ("VHDSetPath", path));
|
||||
output.GetResultOrThrow(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to optimize virtual disk set file.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Determines whether a virtual hard disk file is valid.</summary>
|
||||
/// <param name="path">
|
||||
/// The fully qualified path of the virtual hard disk file to validate. This file will not be modified as a result of this operation.
|
||||
/// </param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token that can be used to cancel the operation. This value can be <see cref="CancellationToken.None"/> to disable cancellation.
|
||||
/// </param>
|
||||
/// <param name="progress">
|
||||
/// A class that implements <see cref="IProgress{T}"/> that can be used to report on progress. This value can be <c>null</c> to disable
|
||||
/// progress reporting.
|
||||
/// </param>
|
||||
/// <returns><c>true</c> if operation completed without error or cancellation; <c>false</c> otherwise.</returns>
|
||||
public static async Task<bool> ValidateAsync(string path, CancellationToken cancellationToken = default, IProgress<int> progress = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Management.ManagementBaseObject output = await scope.CallJobMethodAsync(cancellationToken, progress, "Msvm_ImageManagementService", "ValidateVirtualHardDisk", ("Path", path));
|
||||
return output.GetResultOrThrow(true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Validates whether a file system can support a virtual hard disk with persistent reservations enabled.</summary>
|
||||
/// <param name="path">
|
||||
/// A fully-qualified path that specifies the location of a disk image file or a directory in which a disk image file might be placed.
|
||||
/// </param>
|
||||
/// <returns><see langword="true"/> if the file system can support a virtual hard disk with persistent reservations enabled.</returns>
|
||||
public static bool ValidatePersistentReservationSupport(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
return scope.CallJobMethodAsync(default, default, "Msvm_ImageManagementService", "ValidatePersistentReservationSupport", ("Path", path)).Result.GetResultOrThrow(true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Reduces the size of a virtual hard disk (VHD) backing store file.</summary>
|
||||
/// <param name="mode">The mode.</param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token that can be used to cancel the operation. This value can be <see cref="CancellationToken.None"/> to disable cancellation.
|
||||
/// </param>
|
||||
/// <param name="progress">
|
||||
/// A class that implements <see cref="IProgress{T}"/> that can be used to report on progress. This value can be <c>null</c> to disable
|
||||
/// progress reporting.
|
||||
/// </param>
|
||||
public async Task CompactAsync(CompactionMode mode, CancellationToken cancellationToken = default, IProgress<int> progress = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Management.ManagementBaseObject output = await scope.CallJobMethodAsync(cancellationToken, progress, "Msvm_ImageManagementService", "CompactVirtualHardDisk", ("Path", ImagePath), ("Mode", (ushort)mode));
|
||||
output.GetResultOrThrow(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to compact virtual disk.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Retrieves information about a VHD Set file.</summary>
|
||||
/// <returns>The information for the requested VHD Set file as an <see cref="VirtualDiskSetInformation"/> instance.</returns>
|
||||
/// <exception cref="System.InvalidOperationException">Failed to get virtual disk set information.</exception>
|
||||
public VirtualDiskSetInformation GetVHDSetInformation()
|
||||
{
|
||||
try
|
||||
{
|
||||
var info = new uint[] { 0, 1, 2 };
|
||||
System.Management.ManagementBaseObject output = scope.CallJobMethodAsync(default, default, "Msvm_ImageManagementService", "GetVHDSetInformation", ("VHDSetPath", ImagePath), ("AdditionalInformation", info)).Result;
|
||||
output.GetResultOrThrow(true);
|
||||
return VirtualDiskSetInformation.Parse(Convert.ToString(output.Properties["Information"].Value));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to get virtual disk set information.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Retrieves information about a VHD Snapshot within a VHD Set file.</summary>
|
||||
/// <param name="path">A fully-qualified path that specifies the location of the VHD Set file.</param>
|
||||
/// <param name="snapshotId">The snapshot identifier.</param>
|
||||
/// <returns>The information for the requested VHD Set file as an <see cref="VirtualDiskSnapshotInformation"/> instance.</returns>
|
||||
/// <exception cref="System.InvalidOperationException">Failed to get virtual disk set information.</exception>
|
||||
// TODO: Fix problem with it failing regardless of what parameters are supplied
|
||||
internal static VirtualDiskSnapshotInformation GetSnapshotInformation(string path, Guid snapshotId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var info = new uint[] { 2 };
|
||||
System.Management.ManagementBaseObject output = scope.CallJobMethodAsync(default, default, "Msvm_ImageManagementService", "GetVHDSnapshotInformation",
|
||||
("VHDSetPath", path), ("AdditionalInformation", info), ("SnapshotIds", new[] { snapshotId.ToString("D") })).Result;
|
||||
output.GetResultOrThrow(true);
|
||||
return VirtualDiskSnapshotInformation.Parse(Convert.ToString(output.Properties["SnapshotInformation"].Value));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to get virtual disk snapshot information.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Sets the snapshot information asynchronous.</summary>
|
||||
/// <param name="info">The information.</param>
|
||||
/// <exception cref="System.InvalidOperationException">Failed to set virtual disk snapshot information.</exception>
|
||||
// TODO: Fix problem with it failing regardless of what parameters are supplied
|
||||
internal static async Task SetSnapshotInformationAsync(VirtualDiskSnapshotInformation info)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Management.ManagementBaseObject output = await scope.CallJobMethodAsync(default, default, "Msvm_ImageManagementService", "SetVHDSnapshotInformation",
|
||||
("Information", info.GetInstanceText()));
|
||||
output.GetResultOrThrow(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to set virtual disk snapshot information.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Create listener events for states in RequestStateChange
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,28 @@
|
|||
using System.Runtime.Serialization;
|
||||
using Vanara.Management;
|
||||
|
||||
namespace Vanara.IO;
|
||||
|
||||
/// <summary>Provides information about a VHD Set file.</summary>
|
||||
[DataContract(Name = "Msvm_VHDSetInformation", Namespace = @"root\virtualization\v2")]
|
||||
public class VirtualDiskSetInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of all files encompassed by the VHD Set file, including any unreferenced files and any parents of the root virtual hard
|
||||
/// disk. All files listed after the root virtual hard disk are unmanaged by this VHD Set file. This field may be empty if this
|
||||
/// information was not specifically requested.
|
||||
/// </summary>
|
||||
public string[] AllPaths { get; internal set; }
|
||||
|
||||
/// <summary>The path of the VHD Set file.</summary>
|
||||
public string Path { get; internal set; }
|
||||
|
||||
/// <summary>A list of GUIDs representing all of the snapshots contained by this VHD Set file.</summary>
|
||||
[IgnoreDataMember]
|
||||
public Guid[] SnapshotIdList => Array.ConvertAll(Ids, s => Guid.Parse(s));
|
||||
|
||||
[DataMember(Name = "SnapshotIdList")]
|
||||
internal string[] Ids { get; set; }
|
||||
|
||||
internal static VirtualDiskSetInformation Parse(string embeddedInstance) => ManagementExtensions.Parse<VirtualDiskSetInformation>(embeddedInstance);
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
using System.Runtime.Serialization;
|
||||
using Vanara.Management;
|
||||
|
||||
namespace Vanara.IO;
|
||||
|
||||
/// <summary>Provides information about a snapshot within a VHD Set file.</summary>
|
||||
[DataContract(Name = "Msvm_VHDSnapshotInformation", Namespace = @"root\virtualization\v2")]
|
||||
public class VirtualDiskSnapshotInformation
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="VirtualDiskSnapshotInformation"/> class.</summary>
|
||||
/// <param name="vhdsFilePath">The path of the VHD Set file.</param>
|
||||
/// <param name="snapshotId">
|
||||
/// A GUID that uniquely identifies this snapshot within the VHD Set file.
|
||||
/// <para>
|
||||
/// If the supplied Snapshot Id already exists, the existing Snapshot entry will be overwritten with the new entry. Otherwise, the new
|
||||
/// entry will be added to the VHD Set file.
|
||||
/// </para>
|
||||
/// </param>
|
||||
/// <param name="resilientChangeTrackingId">The optional resilient change tracking ID associated with this snapshot.</param>
|
||||
public VirtualDiskSnapshotInformation(string vhdsFilePath, Guid snapshotId, string resilientChangeTrackingId = null)
|
||||
{
|
||||
FilePath = vhdsFilePath;
|
||||
SnapshotId = snapshotId;
|
||||
ResilientChangeTrackingId = resilientChangeTrackingId;
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="VirtualDiskSnapshotInformation"/> class.</summary>
|
||||
public VirtualDiskSnapshotInformation() { }
|
||||
|
||||
/// <summary>Gets or sets the date and time of this snapshot's creation.</summary>
|
||||
[IgnoreDataMember]
|
||||
public DateTime? CreationTime
|
||||
{
|
||||
get => ManagementExtensions.CimToDateTime(CreationTimeString);
|
||||
// set => CreationTimeString = value.HasValue ? value.Value.DateTimeToCim() : null;
|
||||
}
|
||||
|
||||
/// <summary>The path of the VHD Set file.</summary>
|
||||
public string FilePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of file paths representing all of the files on which this snapshot depends. This field will be empty unless specifically
|
||||
/// requested. The first entry is the file's immediate parent, with the last entry being the root.
|
||||
/// </summary>
|
||||
public string[] ParentPathsList { get; internal set; }
|
||||
|
||||
/// <summary>Gets or sets the resilient change tracking ID, if any, associated with this snapshot.</summary>
|
||||
public string ResilientChangeTrackingId { get; set; }
|
||||
|
||||
/// <summary>A GUID that uniquely identifies this snapshot within the VHD Set file.</summary>
|
||||
[IgnoreDataMember]
|
||||
public Guid? SnapshotId
|
||||
{
|
||||
get => Guid.TryParse(Id, out var id) ? id : null;
|
||||
set => Id = value?.ToString("D");
|
||||
}
|
||||
|
||||
/// <summary>The path of the file represented by this snapshot. This field may be empty if there is no file associated with this snapshot.</summary>
|
||||
public string SnapshotPath { get; set; }
|
||||
|
||||
[DataMember(Name = "CreationTime")]
|
||||
internal string CreationTimeString { get; set; }
|
||||
|
||||
[DataMember(Name = "SnapshotId")]
|
||||
internal string Id { get; set; }
|
||||
|
||||
internal static VirtualDiskSnapshotInformation Parse(string embeddedInstance) => ManagementExtensions.Parse<VirtualDiskSnapshotInformation>(embeddedInstance);
|
||||
|
||||
/// <summary>Gets the embedded instance string usable by WMI</summary>
|
||||
/// <returns>Embedded instance string usable by WMI.</returns>
|
||||
internal string GetInstanceText(string serverName = ".") => ManagementExtensions.GetInstanceText(this, serverName);
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Vanara.IO
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue