将磁盘的当前只读状态设置为“是”

问题描述 投票:0回答:1

我一直在尝试将磁盘设为只读,几天后我做到了。 我从here获得了参考,并将尝试添加更多功能以用于练习目的! 我还看到有些人从 Windows 注册表中执行此操作,这有效还是以后不会出现问题?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        const uint GENERIC_READ = 0x80000000;
        const uint GENERIC_WRITE = 0x40000000;
        const int FILE_SHARE_READ = 0x1;
        const int FILE_SHARE_WRITE = 0x2;

        const uint IOCTL_DISK_SET_DISK_ATTRIBUTES = 0x0007c0f4;
        const ulong DISK_ATTRIBUTE_READ_ONLY = 0x0000000000000002;

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern IntPtr CreateFile(
            string lpFileName,
            uint dwDesiredAccess,
            uint dwShareMode,
            IntPtr SecurityAttributes,
            uint dwCreationDisposition,
            uint dwFlagsAndAttributes,
            IntPtr hTemplateFile
        );

        [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
        private static extern bool DeviceIoControl(
           IntPtr hDevice,
           uint dwIoControlCode,
           IntPtr lpInBuffer,
           uint nInBufferSize,
           IntPtr lpOutBuffer,
           uint nOutBufferSize,
           out uint lpBytesReturned,
           IntPtr lpOverlapped
        );

        [StructLayout(LayoutKind.Sequential)]
        struct SET_DISK_ATTRIBUTES
        {
            public uint Version;
            [MarshalAs(UnmanagedType.I1)]
            public bool Persist;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
            public byte[] Reserved1;
            public ulong Attributes;
            public ulong AttributesMask;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            public uint[] Reserved2;
        };

        public Form1()
        {
            InitializeComponent();
        }

        public IntPtr CreateHandle(int diskNumber)
        {
            string filename = @"\\.\\PhysicalDrive" + diskNumber;
            IntPtr handle = CreateFile(
                filename,
                GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ | FILE_SHARE_WRITE,
                IntPtr.Zero,
                3, // OPEN_EXISTING
                0, // No special flags
                IntPtr.Zero
            );

            if (handle == IntPtr.Zero)
            {
                int errorCode = Marshal.GetLastWin32Error();
                MessageBox.Show("Failed to create handle. Error: " + new Win32Exception(errorCode).Message);
            }
            return handle;
        }

        private void SetReadonly(IntPtr handle)
        {
            if (handle == IntPtr.Zero)
            {
                MessageBox.Show("Handle is invalid.");
                return;
            }

            var sda = new SET_DISK_ATTRIBUTES
            {
                Version = (uint)Marshal.SizeOf<SET_DISK_ATTRIBUTES>(),
                Persist = true,
                AttributesMask = DISK_ATTRIBUTE_READ_ONLY,
                Attributes = DISK_ATTRIBUTE_READ_ONLY,
                Reserved1 = new byte[3],
                Reserved2 = new uint[4]
            };

            IntPtr ptrQuery = Marshal.AllocHGlobal(Marshal.SizeOf(sda));
            try
            {
                Marshal.StructureToPtr(sda, ptrQuery, false);
                uint byteReturned;

                // Set the disk to read-only
                bool res = DeviceIoControl(handle, IOCTL_DISK_SET_DISK_ATTRIBUTES, ptrQuery, (uint)Marshal.SizeOf(sda), IntPtr.Zero, 0, out byteReturned, IntPtr.Zero);
                if (!res)
                {
                    MessageBox.Show("Failed to set readonly. Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message);
                }
            }
            finally
            {
                Marshal.FreeHGlobal(ptrQuery);
            }
        }

        private void DisplayDiskAttributes(int diskNumber,string Msg)
        {
            MessageBox.Show(Msg);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (int.TryParse(textBox1.Text.Trim(), out int diskNumber) && diskNumber >= 0)
            {
                IntPtr handle = CreateHandle(diskNumber);
                SetReadonly(handle); // Set to read-only
                DisplayDiskAttributes(diskNumber, "Set to Read only succesfuul");
            }
            else
            {
                MessageBox.Show("Please enter a valid disk number (e.g., 0, 1, 2).");
            }
        }
    }
}

当我使用 DiskPart 显示属性时,它显示如下:

  1. 当前只读状态:
  2. 只读:
  3. 启动盘:否
  4. 页面文件磁盘:否
  5. 休眠文件盘:无
  6. 故障转储磁盘:否
  7. 集群磁盘:否

但我想让它像:

  1. 当前只读状态:
  2. 只读:否
  3. 启动盘:否
  4. 页面文件磁盘:否
  5. 休眠文件盘:无
  6. 故障转储磁盘:否
  7. 集群磁盘:否

但是我找不到一种方法来使其成为可能,因为Set_Disk_Attribute结构无法做到这一点! 还有其他办法吗? 抱歉写得不好,我是新来的! 谢谢!

c# windows winapi
1个回答
0
投票

与 坚持=假 你应该会得到预期的结果。

© www.soinside.com 2019 - 2024. All rights reserved.