0

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

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

在继续代码示例之前,我对 VSS(.Net 接口使用可通过 NuGet 包管理器获得的 AlphaVSS)有点犹豫,因为两个使用 VSS(Shadow Copy 和另一个工具)的实用程序没有正确复制驱动器. 并非所有文件都被复制,尤其是根目录中的 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 分区。

4

0 回答 0