系统驱动器进行磁盘克隆

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

我正在尝试找到一种方法将活动的 Windows 系统磁盘克隆到另一个磁盘,而不强制用户使磁盘脱机,就像 Clonezilla 所要求的那样。

我正在考虑使用 Microsoft 卷影复制服务 (VSS) 来至少解决部分问题。 (我完全愿意接受更好的想法/解决方案。)

在继续代码示例之前,我对 VSS 有点犹豫(.Net 接口使用可通过 NuGet Package Manager 获得的 AlphaVSS),因为使用 VSS(影子复制和另一个工具)的两个实用程序没有复制驱动器适当地。并非所有文件都被正确复制,尤其是根目录中的 sys 文件,并且完全权限也没有复制。简单的 Araxis 磁盘比较显示了副本的不准确性。此外,我无法启动克隆的驱动器。我看到一个屏幕,显示驱动器无法启动,必须修复。

该示例有点难以理解。我期待看到包含开关(子目录与非子目录、权限等)

我确实看过dotNetDiskImager,但那是USB到图像文件和图像文件到USB磁盘。修改代码,让人们开车去潜水是完全失败的。人们不能只是愚蠢地复制扇区。人们必须知道您正在复制什么并进行修改。仅仅复制扇区并不是一个简单的任务,因此回到 VSS。

还有更好的想法吗?

这里是更新的 AlphaVSS 代码,它修复了由于 AlphaVSS 同步而非异步而导致的编译器错误。我还将代码从 VB 翻译为 C#。

    [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();
        }
    }

简而言之,我想拿一个实时系统磁盘,通常有“系统保留”、“主”和恢复分区,并实时克隆到系统中的另一个磁盘。

我会确保新磁盘有足够的空间,已经分区并格式化为3个NTFS分区。

c# disk volume-shadow-service shadow-copy
1个回答
0
投票

要在 Windows 10 上免费克隆磁盘 - 任何大小到任何大小 - 您需要 2 个分区!您的主操作系统分区:

避免灾难并删除旧驱动器并仅安装新的完全空白的 SDD(将在 DISKPART 中显示为磁盘 0):

使用 USB 恢复(见上文)或 Windows 10 安装盘启动 -> 修复 Windows 安装 -> 命令提示符

磁盘部分

选择磁盘0

CREATE PART EFI SIZE=260(可以是 100)

选择第 1 部分

快速格式化 FS=FAT32

分配字母=F

选择磁盘0

CREATE PART MSR SIZE=100(顺便说一句,MSR 是一些微软的胡言乱语,甚至没有被使用)

选择磁盘0

CREATE PART PRIMARY(如果您不想使用整个磁盘,请使用 SIZE=N)

选择第 3 部分

快速格式化 FS=NTFS 标签=“操作系统”

分配字母=C

列出音量(记下列表中的音量)

退出

引导 /nt60 F:

---------- 现在通过 USB 电缆连接您的旧磁盘 - 当您在 Windows 中运行时,它应该即插即用

磁盘部分

列表卷(注意添加到列表中的新卷 - 我的旧主驱动器现在安装为 e:)

退出(与过去不同,操作系统驱动器上没有特殊的引导内容 - 您只需要文件的副本)

ROBOCOPY e:\ c:\ /s /copyall /r:0 /b(可能需要几个小时才能完成)

---------- 重新启动 -- 工作完成 --

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