我需要使用 c# 实现一个硬盘分区程序。以下是我的代码的一部分。
我认为它有效,因为它返回true
的值DeviceIOcontrol
没有错误,但问题是我的程序没有显示任何内容。
我从 Medo 的主页、MSDN 和 pinvoke 站点获得了很多帮助。
public static bool partitionDisk(string path)
{
var signature = new byte[4];
System.Security.Cryptography.RandomNumberGenerator.Create().GetBytes(signature);
using (SafeFileHandle handle = NativeMethods2.CreateFile(path, (NativeMethods2.FILE_SHARE_READ|NativeMethods.GENERIC_READ ) | (NativeMethods.GENERIC_WRITE | NativeMethods2.FILE_SHARE_WRITE), 0, IntPtr.Zero, NativeMethods2.OPEN_EXISTING, 0, IntPtr.Zero))
{
if (handle.IsInvalid) { throw new Win32Exception(); }
var newdi = new NativeMethods2.DRIVE_LAYOUT_INFORMATION_EX();
newdi.PartitionStyle = NativeMethods2.PARTITION_STYLE.PARTITION_STYLE_MBR;
newdi.PartitionCount = 4;
newdi.DriveLayoutInformaiton.Mbr.Signature = BitConverter.ToInt32(signature, 0);
newdi.PartitionEntry = new NativeMethods2.PARTITION_INFORMATION_EX[0x16];
newdi.PartitionEntry[0] = new NativeMethods2.PARTITION_INFORMATION_EX();
newdi.PartitionEntry[0].PartitionStyle = NativeMethods2.PARTITION_STYLE.PARTITION_STYLE_MBR;
newdi.PartitionEntry[0].StartingOffset = 1048576; // check by diskpart
newdi.PartitionEntry[0].PartitionLength = 0xFFFFFFFFFFfffff; //int64 max
newdi.PartitionEntry[0].PartitionNumber = 1;
newdi.PartitionEntry[0].RewritePartition = true;
newdi.PartitionEntry[0].DriveLayoutInformaiton.Mbr.BootIndicator = false;
newdi.PartitionEntry[0].DriveLayoutInformaiton.Mbr.HiddenSectors = 0; //sector size
newdi.PartitionEntry[0].DriveLayoutInformaiton.Mbr.PartitionType = 0x07;// PARTITION_IFS (NTFS partition or logical drive)
newdi.PartitionEntry[0].DriveLayoutInformaiton.Mbr.RecognizedPartition = true;
for (int k = 2; k < newdi.PartitionCount; k++)
{
newdi.PartitionEntry[k] = new NativeMethods2.PARTITION_INFORMATION_EX();
newdi.PartitionEntry[k].DriveLayoutInformaiton.Mbr.BootIndicator = false;
newdi.PartitionEntry[k].DriveLayoutInformaiton.Mbr.HiddenSectors = 0;
newdi.PartitionEntry[k].PartitionLength = 0;
newdi.PartitionEntry[k].PartitionNumber = k;
newdi.PartitionEntry[k].DriveLayoutInformaiton.Mbr.PartitionType = 0;
newdi.PartitionEntry[k].DriveLayoutInformaiton.Mbr.RecognizedPartition = false;
newdi.PartitionEntry[k].RewritePartition = true;
newdi.PartitionEntry[k].StartingOffset = 0;
}
Int32 bytesOut = 0;
if (NativeMethods2.DeviceIoControl(handle, NativeMethods2.IOCTL_DISK_SET_DRIVE_LAYOUT, ref newdi, Marshal.SizeOf(newdi), IntPtr.Zero, 0, ref bytesOut, IntPtr.Zero) == false) { throw new Win32Exception(); }
}
}
private static class NativeMethods2
{
public const int GENERIC_READ = -2147483648;
public const int GENERIC_WRITE = 1073741824;
public const int OPEN_EXISTING = 3;
public const int FILE_SHARE_READ = 0x0000000001;
public const int FILE_SHARE_WRITE = 0x0000000002;
public const int IOCTL_DISK_UPDATE_PROPERTIES = 0x70140;
public const int IOCTL_DISK_SET_DRIVE_LAYOUT_EX = 0x7C054;
public enum PARTITION_STYLE
{
PARTITION_STYLE_MBR = 0,
PARTITION_STYLE_GPT = 1,
PARTITION_STYLE_RAW = 2,
}
[StructLayout(LayoutKind.Sequential)]
public struct DRIVE_LAYOUT_INFORMATION_EX
{
public PARTITION_STYLE PartitionStyle;
public int PartitionCount;
public DRIVE_LAYOUT_INFORMATION_UNION DriveLayoutInformaiton;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 0x16)]
public PARTITION_INFORMATION_EX[] PartitionEntry;
}
[StructLayout(LayoutKind.Sequential)]
public struct PARTITION_INFORMATION_EX
{
public PARTITION_STYLE PartitionStyle;
public long StartingOffset;
public long PartitionLength;
public int PartitionNumber;
public bool RewritePartition;
public PARTITION_INFORMATION_UNION DriveLayoutInformaiton;
}
[StructLayout(LayoutKind.Sequential)]
public struct PARTITION_INFORMATION_MBR
{
public byte PartitionType;
public bool BootIndicator;
public bool RecognizedPartition;
public Int32 HiddenSectors;
}
[StructLayout(LayoutKind.Sequential)]
public struct PARTITION_INFORMATION_GPT
{
public Guid PartitionType; //GUID
public Guid PartitionId; //GUID
public Int64 Attributes;
public char[] Name;
}
[StructLayout(LayoutKind.Sequential)]
public struct PARTITION_INFORMATION
{
public long StartingOffset;
public long PartitionLength;
public int HiddenSectors;
public int PartitionNumber;
public byte PartitionType;
[MarshalAs(UnmanagedType.I1)]
public bool BootIndicator;
[MarshalAs(UnmanagedType.I1)]
public bool RecognizedPartition;
[MarshalAs(UnmanagedType.I1)]
public bool RewritePartition;
}
[StructLayout(LayoutKind.Explicit)]
public struct DRIVE_LAYOUT_INFORMATION_UNION
{
[FieldOffset(0)]
public DRIVE_LAYOUT_INFORMATION_MBR Mbr;
[FieldOffset(0)]
public DRIVE_LAYOUT_INFORMATION_GPT Gpt;
}
[StructLayout(LayoutKind.Sequential)]
public struct DRIVE_LAYOUT_INFORMATION_MBR
{
public Int32 Signature;
}
[StructLayout(LayoutKind.Sequential)]
public struct DRIVE_LAYOUT_INFORMATION_GPT
{
public Guid DiskId;
public Int64 StartingUsableOffset;
public Int64 UsableLength;
public ulong MaxPartitionCount;
}
[StructLayout(LayoutKind.Explicit)]
public struct PARTITION_INFORMATION_UNION
{
[FieldOffset(0)]
public PARTITION_INFORMATION_MBR Mbr;
[FieldOffset(0)]
public PARTITION_INFORMATION_GPT Gpt;
}
[DllImportAttribute("kernel32.dll", EntryPoint = "CreateFileW", SetLastError = true)]
public static extern SafeFileHandle CreateFile([MarshalAsAttribute(UnmanagedType.LPWStr)] string lpFileName, Int32 dwDesiredAccess, Int32 dwShareMode, IntPtr lpSecurityAttributes, Int32 dwCreationDisposition, Int32 dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImportAttribute("kernel32.dll", EntryPoint = "DeviceIoControl", SetLastError = true)]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
public static extern Boolean DeviceIoControl(SafeFileHandle hDevice, Int32 dwIoControlCode, ref DRIVE_LAYOUT_INFORMATION_EX lpInBuffer, int nInBufferSize, IntPtr lpOutBuffer, Int32 nOutBufferSize, ref Int32 lpBytesReturned, IntPtr lpOverlapped);
}
private static class NativeMethods
{
public const int GENERIC_READ = -2147483648;
public const int GENERIC_WRITE = 1073741824;
public const int OPEN_EXISTING = 3;
public const int IOCTL_DISK_CREATE_DISK = 0x7C058;
public enum PARTITION_STYLE
{
PARTITION_STYLE_MBR = 0,
PARTITION_STYLE_GPT = 1,
PARTITION_STYLE_RAW = 2,
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct CREATE_DISK
{
public PARTITION_STYLE PartitionStyle;
public CREATE_DISK_UNION_MBR_GPT MbrGpt;
}
[StructLayoutAttribute(LayoutKind.Explicit)]
public struct CREATE_DISK_UNION_MBR_GPT
{
[FieldOffset(0)]
public CREATE_DISK_MBR Mbr;
[FieldOffset(0)]
public CREATE_DISK_GPT Gpt;
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct CREATE_DISK_MBR
{
public Int32 Signature;
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct CREATE_DISK_GPT
{
public Guid DiskId;
public Int32 MaxPartitionCount;
}
[DllImportAttribute("kernel32.dll", EntryPoint = "CreateFileW", SetLastError = true)]
public static extern SafeFileHandle CreateFile([MarshalAsAttribute(UnmanagedType.LPWStr)] string lpFileName, Int32 dwDesiredAccess, Int32 dwShareMode, IntPtr lpSecurityAttributes, Int32 dwCreationDisposition, Int32 dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImportAttribute("kernel32.dll", EntryPoint = "DeviceIoControl", SetLastError = true)]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
public static extern Boolean DeviceIoControl(SafeFileHandle hDevice, Int32 dwIoControlCode, ref CREATE_DISK lpInBuffer, int nInBufferSize, IntPtr lpOutBuffer, Int32 nOutBufferSize, ref Int32 lpBytesReturned, IntPtr lpOverlapped);
}
...并调用该函数:
DiskIO.partitionDisk("//./PHYSICALDRIVE2")