using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.AccessControl;
using System.Security.Principal;
class VhdxBackupManager
{
    const string VhdxPath = @"D:\Backup.vhdx";
    const string AdminAccount = "Administrators";
    static char _currentDriveLetter = 'E'; // 默认起始盘符
    public static void ExecuteSafeBackup()
    {
        try
        {
            // 0. 确保VHDX文件存在
            if (!File.Exists(VhdxPath))
            {
                CreateNewVhdx();
                SetVhdxPermissions();
            }
            // 1. 寻找可用盘符
            char driveLetter = FindAvailableDriveLetter();
            
            // 2. 挂载可读写VHDX
            MountVhdx(driveLetter, readOnly: false);
            
            // 3. 执行备份操作
            File.Copy("C:\\Data\\important.txt", $"{driveLetter}:\\important.txt", true);
            
            // 4. 卸载并重新挂载为只读
            DismountVhdx(driveLetter);
            MountVhdx(driveLetter, readOnly: true);
        }
        catch (Exception ex)
        {
            DismountVhdx(_currentDriveLetter); // 尝试卸载当前盘符
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
    // 动态查找可用盘符(从E到Z)
    private static char FindAvailableDriveLetter()
    {
        var usedDrives = DriveInfo.GetDrives()
            .Select(d => d.Name[0])
            .ToList();
        for (char c = 'E'; c <= 'Z'; c++)
        {
            if (!usedDrives.Contains(c))
            {
                _currentDriveLetter = c;
                return c;
            }
        }
        throw new InvalidOperationException("没有可用的驱动器盘符");
    }
    // 挂载虚拟磁盘方法
    private static void MountVhdx(char driveLetter, bool readOnly)
    {
        var script = $@"
            select vdisk file={VhdxPath}
            attach vdisk {(readOnly ? "readonly" : "")}
            assign letter={driveLetter}
            exit
        ";
        ExecuteDiskPart(script);
        
        // 验证挂载是否成功
        if (!Directory.Exists($"{driveLetter}:\\"))
        {
            throw new Exception($"挂载到 {driveLetter}: 失败");
        }
    }
    // 卸载虚拟磁盘方法
    private static void DismountVhdx(char driveLetter)
    {
        var script = $@"
            select vdisk file={VhdxPath}
            detach vdisk
            exit
        ";
        ExecuteDiskPart(script);
    }
    // 原有权限设置方法保持不变
    private static void SetVhdxPermissions()
    {
        var fileInfo = new FileInfo(VhdxPath);
        FileSecurity fSecurity = fileInfo.GetAccessControl();
        // 禁用继承并清除所有现有权限
        fSecurity.SetAccessRuleProtection(true, false);
        AuthorizationRuleCollection rules = fSecurity.GetAccessRules(true, true, typeof(NTAccount));
        foreach (FileSystemAccessRule rule in rules)
        {
            fSecurity.RemoveAccessRule(rule);
        }
        // 添加SYSTEM完全控制(挂载操作需要)
        fSecurity.AddAccessRule(new FileSystemAccessRule(
            new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null),
            FileSystemRights.FullControl,
            AccessControlType.Allow));
        // 添加管理员组只读权限
        fSecurity.AddAccessRule(new FileSystemAccessRule(
            new NTAccount(AdminAccount),
            FileSystemRights.Read | FileSystemRights.ExecuteFile,
            InheritanceFlags.None,
            PropagationFlags.None,
            AccessControlType.Allow));
        // 禁止Everyone写入
        fSecurity.AddAccessRule(new FileSystemAccessRule(
            new SecurityIdentifier(WellKnownSidType.WorldSid, null),
            FileSystemRights.Write,
            AccessControlType.Deny));
        fileInfo.SetAccessControl(fSecurity);
    }
    private static void CreateNewVhdx()
    {
        var script = $@"
            create vdisk file={VhdxPath} maximum=10240 type=expandable
            select vdisk file={VhdxPath}
            attach vdisk
            create partition primary
            format quick fs=ntfs label=BackupDrive
            detach vdisk
            exit
        ";
        ExecuteDiskPart(script);
    }
    private static void ExecuteDiskPart(string script)
    {
        var tempFile = Path.GetTempFileName();
        File.WriteAllText(tempFile, script);
        using (var process = new Process())
        {
            process.StartInfo = new ProcessStartInfo
            {
                FileName = "diskpart",
                Arguments = $"/s {tempFile}",
                UseShellExecute = false,
                CreateNoWindow = true
            };
            process.Start();
            process.WaitForExit(15000);
            
            if (process.ExitCode != 0)
            {
                File.Delete(tempFile);
                throw new Exception("diskpart执行失败,返回码:" + process.ExitCode);
            }
        }
        File.Delete(tempFile);
    }
}