如何以编程方式从C#更改Fat32分区的卷序列。我找到了this example,但是它是用C ++编写的,我不太清楚。有人可以回答C#代码段吗?

更新:
我可以从上面的示例中看到C ++函数,我认为可以将端口定向到C#

void CVolumeSerialDlg::ChangeSerialNumber(DWORD Drive, const DWORD newSerial)
{
  const max_pbsi = 3;

  struct partial_boot_sector_info
  {
    LPSTR Fs; // file system name

    DWORD FsOffs; // offset of file system name in the boot sector

    DWORD SerialOffs; // offset of the serialnumber in the boot sector

  };

  partial_boot_sector_info pbsi[max_pbsi] =
  {
   {"FAT32", 0x52, 0x43},
   {"FAT",   0x36, 0x27},
   {"NTFS",  0x03, 0x48}
  };

  TCHAR szDrive[12];

  char Sector[512];

  DWORD i;

  sprintf(szDrive, "%c:\\", Drive & 0xFF);

  if (!disk.Open(szDrive))
  {
    ShowErrorString("Could not open disk!");
    return;
  }

  // read sector
  if (!disk.ReadSector(0, Sector))
  {
    ShowErrorString("Could not read sector!");
    return;
  }

  // try to search for a valid boot sector
  for (i=0;i<max_pbsi;i++)
  {
    if (strncmp(pbsi[i].Fs, Sector+pbsi[i].FsOffs, strlen(pbsi[i].Fs)) == 0)
    {
      // we found a valid signature
      break;
    }
  }

  if (i >= max_pbsi)
  {
    MessageBox(_T("Cannot change serial number of this file system!"),
       _T("Error"), MB_ICONERROR);
    return;
  }

  // patch serial number
  *(PDWORD)(Sector+pbsi[i].SerialOffs) = newSerial;

  // write boot sector
  if (!disk.WriteSector(0, Sector))
  {
    ShowErrorString("Could not write sector!");
    return;
  }

  ShowErrorString("Volume serial number changed successfully!\r"
        "You might want to restart your system for changes to take effect!");
}

最佳答案

没有保证,要小心。

void ChangeSerialNumber(char volume, uint newSerial)
{
    var fsInfo = new[]
    {
        new { Name = "FAT32", NameOffs = 0x52, SerialOffs = 0x43 },
        new { Name = "FAT", NameOffs = 0x36, SerialOffs = 0x27 },
        new { Name = "NTFS", NameOffs = 0x03, SerialOffs = 0x48 }
    };

    using (var disk = new Disk(volume))
    {
        var sector = new byte[512];
        disk.ReadSector(0, sector);

        var fs = fsInfo.FirstOrDefault(
                f => Strncmp(f.Name, sector, f.NameOffs)
            );
        if (fs == null) throw new NotSupportedException("This file system is not supported");

        var s = newSerial;
        for (int i = 0; i < 4; ++i, s >>= 8) sector[fs.SerialOffs + i] = (byte)(s & 0xFF);

        disk.WriteSector(0, sector);
    }
}

bool Strncmp(string str, byte[] data, int offset)
{
    for(int i = 0; i < str.Length; ++i)
    {
        if (data[i + offset] != (byte)str[i]) return false;
    }
    return true;
}

class Disk : IDisposable
{
    private SafeFileHandle handle;

    public Disk(char volume)
    {
        var ptr = CreateFile(
            String.Format("\\\\.\\{0}:", volume),
            FileAccess.ReadWrite,
            FileShare.ReadWrite,
            IntPtr.Zero,
            FileMode.Open,
            0,
            IntPtr.Zero
            );

        handle = new SafeFileHandle(ptr, true);

        if (handle.IsInvalid) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
    }

    public void ReadSector(uint sector, byte[] buffer)
    {
        if (buffer == null) throw new ArgumentNullException("buffer");
        if (SetFilePointer(handle, sector, IntPtr.Zero, EMoveMethod.Begin) == INVALID_SET_FILE_POINTER) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

        uint read;
        if (!ReadFile(handle, buffer, buffer.Length, out read, IntPtr.Zero)) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        if (read != buffer.Length) throw new IOException();
    }

    public void WriteSector(uint sector, byte[] buffer)
    {
        if (buffer == null) throw new ArgumentNullException("buffer");
        if (SetFilePointer(handle, sector, IntPtr.Zero, EMoveMethod.Begin) == INVALID_SET_FILE_POINTER) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

        uint written;
        if (!WriteFile(handle, buffer, buffer.Length, out written, IntPtr.Zero)) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        if (written != buffer.Length) throw new IOException();
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (handle != null) handle.Dispose();
        }
    }

    enum EMoveMethod : uint
    {
        Begin = 0,
        Current = 1,
        End = 2
    }

    const uint INVALID_SET_FILE_POINTER = 0xFFFFFFFF;

    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern IntPtr CreateFile(
        string fileName,
        [MarshalAs(UnmanagedType.U4)] FileAccess fileAccess,
        [MarshalAs(UnmanagedType.U4)] FileShare fileShare,
        IntPtr securityAttributes,
        [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
        int flags,
        IntPtr template);

    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern uint SetFilePointer(
         [In] SafeFileHandle hFile,
         [In] uint lDistanceToMove,
         [In] IntPtr lpDistanceToMoveHigh,
         [In] EMoveMethod dwMoveMethod);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool ReadFile(SafeFileHandle hFile, [Out] byte[] lpBuffer,
        int nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);

    [DllImport("kernel32.dll")]
    static extern bool WriteFile(SafeFileHandle hFile, [In] byte[] lpBuffer,
        int nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten,
        [In] IntPtr lpOverlapped);
}


使用例如ChangeSerialNumber('D', 0x12345678);

10-08 12:57