Системные диски для клонирования дисков - PullRequest
0 голосов
/ 08 мая 2018

Я пытаюсь найти способ клонировать активный системный диск Windows на другой диск, не вынуждая пользователя перевести диск в автономный режим, как требует Clonezilla.

Я думаю о Microsoft Volume Shadow Copy Service (VSS) хотя бы на часть ответа.(Я полностью открыт для лучшей мысли / решения.)

Прежде чем продолжить с примером кода, я немного колеблюсь с VSS (интерфейс .Net использует AlphaVSS, доступную через диспетчер пакетов NuGet), как две утилиты, которые используют VSS (Shadow Copy и еще один инструмент), неправильно копировали диск.Не все файлы были скопированы, особенно файлы sys в корне, и полные права доступа также не скопированы.Простое сравнение диска Araxis показывает неточность копии.Кроме того, я не могу загрузиться с клонированного диска.У меня появляется сообщение о том, что накопитель не может загрузиться и его нужно починить.

Пример довольно сложен для подражания.Я ожидал увидеть включение переключателей (подкаталоги против, нет, разрешения и т. Д., И т. Д.)

Я смотрел на dotNetDiskImager, но это USB для файла изображения и файла изображения дляUSB диск.Модификация кода, так что переход на диск был полным провалом.Нельзя просто тупо копировать сектора.Нужно знать, что вы копируете, и вносить изменения.Это не простая задача просто скопировать секторы, следовательно, возвращаясь к VSS.

Есть лучшие мысли?

Вот обновленный код AlphaVSS, который исправляет ошибки компилятора в результате AlphaVSSпроисходит синхронно, а не асинхронно.Я также перевел код на C # из VB.

    [System.Runtime.InteropServices.DllImport("kernel32.dll", EntryPoint="CopyFileEx", ExactSpelling=false, CharSet=System.Runtime.InteropServices.CharSet.Auto, SetLastError=true)]
    private static extern int CopyFileEx(string lpExistingFileName, string lpNewFileName, CopyProgressRoutine_Delegate lpProgressRoutine, Int32 lpData, Int32 lpBool, Int32 dwCopyFlags);

    private delegate long CopyProgressRoutine_Delegate(long totalFileSize, long totalBytesTransferred, long streamSize, long streamBytesTransferred, Int32 dwStreamNumber, Int32 dwCallbackReason, Int32 hSourceFile, Int32 hDestinationFile, Int32 lpData);

    private CopyProgressRoutine_Delegate m_oCPR;

    public void Main()
    {

        //
        // Display Setting
        Console.BackgroundColor = ConsoleColor.White;
        Console.Clear();
        Console.SetWindowSize(90, 30);
        Console.SetWindowPosition(0, 0);
        Console.ForegroundColor = ConsoleColor.DarkGreen;
        // Prevent example from ending if CTL+C is pressed.
        Console.TreatControlCAsInput = true;

StartPoint:

        Console.Clear();
        Console.WriteLine("*******************************************************************");
        Console.WriteLine("**                                                               **");
        Console.WriteLine("** Greetings,                                                    **");
        Console.WriteLine("**                                                               **");
        Console.WriteLine("** This small app is only for primary basic Testing              **");
        Console.WriteLine("** of VSS using Dot.Net Technology                               **");
        Console.WriteLine("** The app is base on the AlphaVSS open project:                 **");
        Console.Write("** ");
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.Write("http://www.codeplex.com/alphavss");
        Console.ForegroundColor = ConsoleColor.DarkGreen;
        Console.WriteLine("                              **");
        Console.WriteLine("**                                                               **");
        Console.WriteLine("** The application is designed only for internal purposes!!      **");
        Console.WriteLine("** In no way use on production servers.                          **");
        Console.Write("** ");
        Console.ForegroundColor = ConsoleColor.DarkRed;
        Console.Write("Any use is at your own risk!!!");
        Console.ForegroundColor = ConsoleColor.DarkGreen;
        Console.WriteLine("                                **");
        Console.WriteLine("**                                                               **");
        Console.WriteLine("** Have Fun,                                                     **");
        Console.WriteLine("** Ariely Ronen                                                  **");
        Console.WriteLine("** ____________________________________________________________  **");
        Console.WriteLine("**                                                               **");
        Console.WriteLine("** Do you want to start the TEST                                 **");
        Console.WriteLine("** by selecting the file you want to copy? (y/n)                 **");
        Console.WriteLine("**                                                               **");
        Console.WriteLine("*******************************************************************");

        ConsoleKeyInfo MyConsoleKeyInfo = new ConsoleKeyInfo();
        MyConsoleKeyInfo = Console.ReadKey();
        if (!(MyConsoleKeyInfo.Key.ToString() == "Y"))
        {
            return;
        }

SelectFileToCopy:

        Console.Clear();
        Console.Write("Starting Test Ver 0.01");


        FolderBrowserDialog sDestFolder = new FolderBrowserDialog();
        string sDestFolderPath = null;

        sDestFolder.Description = "Select a destination folder (where the file will be copy to).";
        // Do not show the button for new folder
        sDestFolder.ShowNewFolderButton = false;
        DialogResult dlgResult = sDestFolder.ShowDialog();
        if (dlgResult == Windows.Forms.DialogResult.OK)
        {
            sDestFolderPath = sDestFolder.SelectedPath;
        }
        else
        {
            sDestFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments).ToString();
        }

        OpenFileDialog oOFD = new OpenFileDialog();
        string sFileName = null;

        // copy progress handler
        // we add the function "CopyProgressRoutine" to the Delegate "CopyProgressRoutine_Delegate"
        // so every time the event come the function run
        m_oCPR = new CopyProgressRoutine_Delegate(CopyProgressRoutine);

        oOFD.ValidateNames = false;
        oOFD.Title = "Select an in-use file you would like to copy.";
        oOFD.Filter = "All files (*.*)|*.*";
        if (oOFD.ShowDialog == DialogResult.OK)
        {
            sFileName = oOFD.FileName;

            Console.Clear();
            Console.WriteLine("File to Copy: ");
            Console.WriteLine(sFileName);
            Console.WriteLine();
            Console.WriteLine("The file will be copy to:");
            Console.WriteLine(sDestFolderPath);
            Console.WriteLine();

            Console.WriteLine("Press any key to continue.");
            Console.ReadKey();
            Console.Clear();

            // Lets Start to copy
            PerformVSSCopy(sFileName, sDestFolderPath);
        }

        Console.WriteLine();
        Console.WriteLine("Press 1 to go to Start Point,2 to go to Select new File To Copy, any other key to exit.");
        MyConsoleKeyInfo = Console.ReadKey();
        switch (MyConsoleKeyInfo.Key.ToString())
        {
            case "D1":
                goto StartPoint;
            case "D2":
                goto SelectFileToCopy;
            default:

            break;
        }

    }

    private Int32 CopyProgressRoutine(long totalFileSize, long totalBytesTransferred, long streamSize, long streamBytesTransferred, Int32 dwStreamNumber, Int32 dwCallbackReason, Int32 hSourceFile, Int32 hDestinationFile, Int32 lpData)
    {
        double dPerc = 100;

        if (totalFileSize != 0)
        {
            dPerc = (totalBytesTransferred / (double)totalFileSize) * 100;
        }

        Console.CursorLeft = 0;
        Console.Write("Copied " + totalBytesTransferred + " of " + totalFileSize + " [" + dPerc.ToString("0.0") + "%]");

        return 0;
    }

    private void PerformVSSCopy(string sFilename, string sDestFolder)
    {
        // Based on the documention from 
        // http://msdn.microsoft.com/en-us/library/aa384589(VS.85).aspx
        // and the help of those on 
        // http://www.codeplex.com/alphavss

        // The parts I have marked and INFO ONLY are not required for the 
        // VSS Copy to work, they just give insight into the process

        Alphaleonis.Win32.Vss.IVssImplementation oVSSImpl = null;
        Alphaleonis.Win32.Vss.IVssBackupComponents oVSS = null;
        string sVolume = null;
        IO.FileInfo oFI = new IO.FileInfo(sFilename);
        Guid gSnapshot = new Guid();
        Guid gSnapshotSet = new Guid();
        string sVSSFile = null;
        string sDestFile = null;
        Alphaleonis.Win32.Vss.VssSnapshotProperties oProps = null;

        try
        {

            // Load the Implementation specifi for this machine i.e Windowx XP , Vista, 32 or 64 Bit
            oVSSImpl = Alphaleonis.Win32.Vss.VssUtils.LoadImplementation();

            // This is the main man for VSS Backups.
            Console.WriteLine("Initializing VssBackupComponents Object");
            oVSS = oVSSImpl.CreateVssBackupComponents;
            oVSS.InitializeForBackup(null);

            // Tell VSS that we are requesting a backup with particular options
            Console.WriteLine("Setting Backup State");
            oVSS.SetBackupState(false, true, Alphaleonis.Win32.Vss.VssBackupType.Full, false);

            // Tell all VSS Writers that we want their MetaData. We wait until all Writers have responded.
            Console.WriteLine("Gat Writers Metadata");
            oVSS.GatherWriterMetadata();
            // INFO ONLY : Enumerate who responded to our GatherWriterMetadata request

            // Create the Snapshot Set that we will place all our Snapshotted volumes into. (even tho here will only snapshot one volume)
            Console.WriteLine("Starting Snapshot Set");
            gSnapshotSet = oVSS.StartSnapshotSet();

            // Add a Snapshot for the required Volume
            sVolume = oFI.Directory.Root.Name;
            Console.WriteLine("Add To Snapshot Set the Volume: " + sVolume);
            gSnapshot = oVSS.AddToSnapshotSet(sVolume, Guid.Empty);

            // Notify all VSS Writers that the backup is about to start, we wait untuil they have indicated they are ready.
            Console.WriteLine("VSS Writers Prepare For Backup .");
            oVSS.PrepareForBackup();

            //Request that the Snapshot are created and wait until they are ready.
            Console.WriteLine("Do Snapshot Set [this can take some time]");
            oVSS.DoSnapshotSet();

            // --------------------------------------------------------------
            // --------------------------------------------------------------
            // Now we can start copying the file.
            // --------------------------------------------------------------
            // We need the properties to tell us how to access our files in the snapshot
            oProps = oVSS.GetSnapshotProperties(gSnapshot);
            sVSSFile = sFilename.Replace(sVolume, oProps.SnapshotDeviceObject + "\\");
            sDestFile = IO.Path.Combine(sDestFolder, IO.Path.GetFileName(sFilename));

            // INFO ONLY Lets check the Properties of the snapshot set

            // Copy, but the normal .NET routines will not work here. Back to the API !!!
            Console.WriteLine("Copying file using API Routines.");
            Console.WriteLine();
            CopyFileEx(sVSSFile, sDestFile, m_oCPR, 0, 0, 0);
            Console.WriteLine();
            Console.WriteLine("Done !");
            // --------------------------------------------------------------
            // --------------------------------------------------------------

            // Release the snapshot set, we could also just call Dispose on the VssBackupComponents object
            // For clarity, I'll do both here.
            Console.WriteLine("Deleting Snapshot Set.");
            oVSS.DeleteSnapshotSet(gSnapshotSet, true);

        }
        catch (Exception ex)
        {
            Console.WriteLine();
            Console.WriteLine(ex.Message);
            Console.WriteLine(ex.StackTrace);
            Console.WriteLine();

        }
        finally
        {
            oVSS.Dispose();
        }
    }

Короче говоря, я хотел бы взять системный диск в режиме реального времени, который обычно имеет разделы «System Reserved», «Main» и «Recovery», исделать живой клон на другой диск в системе.

Я бы позаботился о том, чтобы на новом диске было достаточно места, он уже разбит на разделы и отформатирован в 3 NTFS-раздела.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...