gpt4 book ai didi

c# - 如何在 C# 中调用 GetVirtualDiskInformation

转载 作者:太空宇宙 更新时间:2023-11-03 15:19:46 25 4
gpt4 key购买 nike

完整的极简主义(非工作)代码:http://pastebin.com/GPdSxyrt

我正在尝试 PInvoke GetVirtualDiskInformation ( https://msdn.microsoft.com/en-us/library/windows/desktop/dd323670(v=vs.85).aspx ) 并使用我的代码:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct GetVirtualDiskInfo
{
public GetVirtualDiskInfoVersion Version; //GET_VIRTUAL_DISK_INFO_VERSION
public GetVirtualDiskInfoUnion Union;
}

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
public struct GetVirtualDiskInfoUnion
{
[FieldOffset(0)] public GetVirtualDiskInfoSize Size;
[FieldOffset(0)] public Guid Identifier; //GUID
[FieldOffset(0)] public GetVirtualDiskInfoParentLocation ParentLocation;
[FieldOffset(0)] public Guid ParentIdentifier; //GUID
[FieldOffset(0)] public uint ParentTimestamp; //ULONG
[FieldOffset(0)] public VirtualStorageType VirtualStorageType; //VIRTUAL_STORAGE_TYPE
[FieldOffset(0)] public uint ProviderSubtype; //ULONG
[FieldOffset(0)] public bool Is4kAligned; //BOOL
[FieldOffset(0)] public bool IsLoaded; //BOOL
[FieldOffset(0)] public GetVirtualDiskInfoPhysicalDisk PhysicalDisk;
[FieldOffset(0)] public uint VhdPhysicalSectorSize; //ULONG
[FieldOffset(0)] public ulong SmallestSafeVirtualSize; //ULONGLONG
[FieldOffset(0)] public uint FragmentationPercentage; //ULONG
[FieldOffset(0)] public Guid VirtualDiskId; //GUID
[FieldOffset(0)] public GetVirtualDiskInfoChangeTrackingState ChangeTrackingState;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct GetVirtualDiskInfoSize
{
public ulong VirtualSize; //ULONGLONG
public ulong PhysicalSize; //ULONGLONG
public uint BlockSize; //ULONG
public uint SectorSize; //ULONG
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct GetVirtualDiskInfoParentLocation
{
public bool ParentResolved; //BOOL
public char ParentLocationBuffer; //WCHAR[1] //TODO
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct GetVirtualDiskInfoPhysicalDisk
{
public uint LogicalSectorSize; //ULONG
public uint PhysicalSectorSize; //ULONG
public bool IsRemote; //BOOL
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct GetVirtualDiskInfoChangeTrackingState
{
public bool Enabled; //BOOL
public bool NewerChanges; //BOOL
public char MostRecentId; //WCHAR[1] //TODO
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct VirtualStorageType
{
public VirtualStorageDeviceType DeviceId; //ULONG
public Guid VendorId; //GUID
}

public enum GetVirtualDiskInfoVersion
{
Unspecified = 0,
Size = 1,
Identifier = 2,
ParentLocation = 3,
ParentIdentifier = 4,
ParentTimestamp = 5,
VirtualStorageType = 6,
ProviderSubtype = 7,
Is4KAligned = 8,
PhysicalDisk = 9,
VhdPhysicalSectorSize = 10,
SmallestSafeVirtualSize = 11,
Fragmentation = 12,
IsLoaded = 13,
VirtualDiskId = 14,
ChangeTrackingState = 15
}

public enum VirtualStorageDeviceType
{
Unknown = 0,
Iso = 1,
Vhd = 2,
Vhdx = 3,
Vhdset = 4
}

[DllImport("virtdisk.dll", CharSet = CharSet.Unicode)]
public static extern uint GetVirtualDiskInformation
(
[In] VirtualDiskSafeHandle virtualDiskHandle,
[In, Out] ref uint virtualDiskInfoSize,
[In, Out] ref GetVirtualDiskInfo virtualDiskInfo,
[In, Out] ref uint sizeUsed
);

我这样调用 GetVirtualDiskInformation:

var info = new GetVirtualDiskInfo {Version = infoVersion};
infoSize = (uint) Marshal.SizeOf(info);
var result = NativeMethods.GetVirtualDiskInformation(handle, ref infoSize, ref info, ref sizeUsed);

显然 handle 确实包含一个有效的 VirtualDiskSafeHandle 在这里。

问题是我的输出结构完全搞砸了。数据无处不在。例如,根据它,VHD 的 LogicalSectorSize 为 257,它有一个负的 VirtualSize

我哪里做错了,我怎样才能让它正常工作?

编辑:

错误的具体例子:

我创建了一个全新的 VHDX 作为差异(无父级,无源),将其最大大小设置为 50MB,LogicalSectorSize 为 512,PhysicalSectorSize 为 4096,BlockSize 到 2MB,它是 VendorId (GUID) 到 new Guid("EC984AEC-A0F9-47e9-901F-71415A66345B")。它从未被附加,它在磁盘上的大小恰好为 4096KB。

我期望在执行时:

var info = new GetVirtualDiskInfo {Version = GetVirtualDiskInfoVersion.Size};
infoSize = (uint) Marshal.SizeOf(info);
var result = NativeMethods.GetVirtualDiskInformation(handle, ref infoSize, ref info, ref sizeUsed);

info.Union.Size 将返回:

VirtualSize = 52428800
PhysicalSize = 4194304
BlockSize = 2097152
SectorSize = 512

我得到的是“足够接近”。除了 VirtualSize 之外的所有值都是正确的,它返回 52428801。现在额外的一个字节可能是预期的,但我对此表示怀疑。无论如何,接下来的几个例子会产生更糟糕的结果:

var info = new GetVirtualDiskInfo {Version = GetVirtualDiskInfoVersion.VirtualStorageType};
infoSize = (uint) Marshal.SizeOf(info);
var result = NativeMethods.GetVirtualDiskInformation(handle, ref infoSize, ref info, ref sizeUsed);

info.Union.VirtualStorageType 的预期结果:

DeviceId = 2 //2 Symbolizes VHDX, which is how I created it
VendorId = "EC984AEC-A0F9-47e9-901F-71415A66345B" //As a GUID

实际结果:

DeviceId = 257
VendorId = "EC984AEC-A0F9-47e9-901F-71415A66345B" //As a GUID

换句话说,GUID 可以,DeviceId 不行。 257 甚至不是有效值。

最后一个例子:

var info = new GetVirtualDiskInfo {Version = GetVirtualDiskInfoVersion.PhysicalDisk};
infoSize = (uint) Marshal.SizeOf(info);
var result = NativeMethods.GetVirtualDiskInformation(handle, ref infoSize, ref info, ref sizeUsed);

预期 info.Union.PhysicalDisk 返回:

LogicalSectorSize = 512
PhysicalSectorSize = 4096
IsRemote = false

实际结果:

LogicalSectorSize  = 257
PhysicalSectorSize = 512
IsRemote = false

所以第一个值又是完全错误的。 257 不是可接受的值,第二个值也是错误的,我希望是 4096。

EDIT2 将 VirtualStorageDeviceType 添加到初始代码。

EDIT3 完整示例在这里:http://pastebin.com/GPdSxyrt

EDIT4

我发现问题出在 C 中的字段是 WCHAR[1]。如果我在结构 GetVirtualDiskInfoUnion 中注释掉 ChangeTrackingState,那么一切正常。

仍然,我不确定在 C# 中如何设置它们,它们似乎不是 char 也不是 IntPtr 我试过的,那怎么办准确翻译成?

最佳答案

我没有解决方案,但注意到如果您在结构的最后添加任何 uint 字段,它也可以正常工作。我的定义是:


公共(public)结构 GetVirtualDiskInfoUnion
{
[FieldOffset(0)] public GetVirtualDiskInfoSize 大小;
[FieldOffset(0)] 公共(public) Guid 标识符;//GUID
[FieldOffset(0)] public GetVirtualDiskInfoParentLocation ParentLocation;
[FieldOffset(0)] public Guid ParentIdentifier;//GUID
[FieldOffset(0)] public uint ParentTimestamp;//乌龙
[FieldOffset(0)] public VirtualStorageType VirtualStorageType;//虚拟存储类型
[FieldOffset(0)] public uint ProviderSubtype;//乌龙
[FieldOffset(0)] public bool Is4kAligned;// bool 值
[FieldOffset(0)] public bool IsLoaded;// bool 值
[FieldOffset(0)] public GetVirtualDiskInfoPhysicalDisk PhysicalDisk;
[FieldOffset(0)] public uint VhdPhysicalSectorSize;//乌龙
[FieldOffset(0)] public ulong SmallestSafeVirtualSize;//乌隆隆
[FieldOffset(0)] public uint FragmentationPercentage;//乌龙
[FieldOffset(0)] public Guid VirtualDiskId;//GUID
[FieldOffset(0)] public GetVirtualDiskInfoChangeTrackingState ChangeTrackingState;
[FieldOffset(0)] public uint 保留;//乌龙

关于c# - 如何在 C# 中调用 GetVirtualDiskInformation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37736999/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com