处理CopyFileEx中的Marshall错误

时间:2017-01-09 10:26:30

标签: c# exception task marshalling

对于备份我们的用户数据多达10000个用户我计划使用这个包装但是因为它在丢失用户数据方面有点危险我真的需要捕获所有复制错误(文件存在,自动化等等)。

这里是包装器

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace PROBTP_BACKUP2.Model
{

    public static class FileEx
    {
        public static Task CopyAsync(string sourceFileName, string destFileName)
        {
            return CopyAsync(sourceFileName, destFileName, CancellationToken.None);
        }

        public static Task CopyAsync(string sourceFileName, string destFileName, CancellationToken token)
        {
            return CopyAsync(sourceFileName, destFileName, token, null);
        }

        public static Task CopyAsync(string sourceFileName, string destFileName, IProgress<double> progress)
        {

            return CopyAsync(sourceFileName, destFileName, CancellationToken.None, progress);

        }

        public static Task CopyAsync(string sourceFileName, string destFileName, CancellationToken token, IProgress<double> progress)
        {
            int pbCancel = 0;
            CopyProgressRoutine copyProgressHandler;
            bool bSuccess = true;
            if (progress != null)
            {
                copyProgressHandler = (total, transferred, streamSize, streamByteTrans, dwStreamNumber, reason, hSourceFile, hDestinationFile, lpData) =>
                {
                    progress.Report((double)transferred / total * 100);
                  Console.WriteLine((double)transferred );
                    return CopyProgressResult.PROGRESS_CONTINUE;
                };
            }
            else
            {
                copyProgressHandler = EmptyCopyProgressHandler;
            }
            token.ThrowIfCancellationRequested();
            var ctr = token.Register(() => pbCancel = 1);
            var copyTask = Task.Run(() =>
            {
                try
                {
                 bSuccess = CopyFileEx(sourceFileName, destFileName, copyProgressHandler, IntPtr.Zero, ref pbCancel, CopyFileFlags.COPY_FILE_FAIL_IF_EXISTS);
                 token.ThrowIfCancellationRequested();


                }

                finally
                {

                    ctr.Dispose();

                }
                if (!bSuccess)
                {
                    Console.WriteLine(bSuccess);
                    string errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
                    Console.WriteLine(errorMessage);

                }
            }, token);

            return copyTask;
        }

        private static CopyProgressResult EmptyCopyProgressHandler(long total, long transferred, long streamSize, long streamByteTrans, uint dwStreamNumber, CopyProgressCallbackReason reason, IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData)
        {
            return CopyProgressResult.PROGRESS_CONTINUE;
        }

        #region DLL Import

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CopyFileEx(string lpExistingFileName, string lpNewFileName,
           CopyProgressRoutine lpProgressRoutine, IntPtr lpData, ref Int32 pbCancel,
           CopyFileFlags dwCopyFlags);

        delegate CopyProgressResult CopyProgressRoutine(
            long totalFileSize,
            long totalBytesTransferred,
            long streamSize,
            long streamBytesTransferred,
            uint dwStreamNumber,
            CopyProgressCallbackReason dwCallbackReason,
            IntPtr hSourceFile,
            IntPtr hDestinationFile,
            IntPtr lpData);

        enum CopyProgressResult : uint
        {
            PROGRESS_CONTINUE = 0,
            PROGRESS_CANCEL = 1,
            PROGRESS_STOP = 2,
            PROGRESS_QUIET = 3
        }

        enum CopyProgressCallbackReason : uint
        {
            CALLBACK_CHUNK_FINISHED = 0x00000000,
            CALLBACK_STREAM_SWITCH = 0x00000001
        }

        [Flags]
        enum CopyFileFlags : uint
        {
            COPY_FILE_FAIL_IF_EXISTS = 0x00000001,
            COPY_FILE_RESTARTABLE = 0x00000002,
            COPY_FILE_OPEN_SOURCE_FOR_WRITE = 0x00000004,
            COPY_FILE_ALLOW_DECRYPTED_DESTINATION = 0x00000008
        }

        #endregion
    }
}

这里是点击按钮上的启动器

public async void StartProcessing(string test)
        {
            var progressIndicator = new Progress<double>(ReportProgress =>
            {
                fileName = ReportProgress.ToString();
                totalPercent = (int)ReportProgress;
            });
            CancellationToken cts = new CancellationToken();
            await Task.Run(() => FileEx.CopyAsync(@"input.rar","C:\cop\output.rar", progressIndicator));

        }

让我说我在这里clik 3次输出(文件已经存在以供测试)

-false -Descripteur non valide -假 -Le fichier existe -假 -Le fichier existe

我翻译 - 无效的描述符 文件存在 -file存在

嗯,你得到它我不知道为什么我起初得到“无效的描述符” 在第二次,我不确定我会以这种方式发现任何错误。

所以,如果有人可以帮助添加严重的错误处理代码,我很高兴

ps:我知道有人会问它,为什么我不使用copyTo或robocopy等。 因为我们需要进步或者用户将在loooooooooooong文件复制思维应用程序崩溃的情况下大量杀死进程。(如果我不熟悉我的计划copyTo(),那就太难了。

0 个答案:

没有答案