2008-10-09 13 views
28

मैंने सी # (.NET 2.0 फ्रेमवर्क) में प्रतिलिपि उपयोगिता बनाई है जो फ़ाइलों, निर्देशिकाओं और रिकर्सिव उप निर्देशिका आदि की प्रतिलिपि बनाता है। प्रोग्राम में एक जीयूआई है जो वर्तमान फ़ाइल की प्रतिलिपि बनाई गई है, वर्तमान फ़ाइल संख्या (अनुक्रम), प्रतिलिपि बनाने के लिए फाइलों की कुल संख्या और कॉपी ऑपरेशन के लिए प्रतिशत पूरा किया गया। एक प्रगति पट्टी भी है, जो वर्तमान फ़ाइल/कुल फाइलों पर आधारित है।क्या मैं .NET में FileInfo.CopyTo() का उपयोग कर फ़ाइल कॉपी प्रगति दिखा सकता हूं?

मेरी समस्या बड़ी फ़ाइलों की प्रतिलिपि बनाने से संबंधित है। मैं एक बड़ी फ़ाइल की कुल प्रति प्रगति को इंगित करने का कोई तरीका नहीं ढूंढ पाया (मेरी वर्तमान क्लास संरचना का उपयोग करके जो FileInfo.CopyTo विधि का उपयोग करता है)। एक कामकाज के रूप में मैंने फाइल कॉपी ऑपरेशंस और जीयूआई डिस्प्ले को अपने स्वयं के थ्रेड में अलग कर दिया है और यह दिखाने के लिए एक दृश्य क्यू सेट किया है कि काम किया जा रहा है। कम से कम उपयोगकर्ता को पता है कि कार्यक्रम जमे हुए नहीं है और अभी भी फाइलों की प्रतिलिपि बना रहा है।

यह बाइट्स की कुल संख्या के आधार पर प्रगति दिखाने में सक्षम होना चाहिए या फ़ाइलइन्फो.कोपीटो विधि से आग लगने वाली कुछ प्रकार की घटना है जो वर्तमान फ़ाइल से कॉपी की गई बाइट्स की कुल संख्या इंगित करती है।

मुझे FileInfo.Length संपत्ति के बारे में पता है, इसलिए मुझे यकीन है कि मैकगुइवर मेरा स्वयं का कार्यक्रम है जो इस पर आधारित है और अपडेट पढ़ने वाले चीजों के जीयूआई पक्ष पर हैंडलर है (शायद किसी प्रकार के टाइमर का उपयोग कर गंतव्य ऑब्जेक्ट की FileInfo.Length संपत्ति की जांच करना?)।

क्या कोई ऐसा करने का तरीका जानता है जिसे मैं देख रहा हूं। अगर मैं इससे बच सकता हूं, तो मैं अपनी कक्षा को एक स्ट्रीम के माध्यम से बाइट्स कॉपी करने के लिए फिर से लिखना नहीं चाहूंगा और इसे इस तरह ट्रैक करूँगा (हालांकि मुझे लगता है कि मैं उस मार्ग पर जाकर फंस सकता हूं)।

अग्रिम धन्यवाद

पुनश्च - मैं अब के लिए .NET 2.0 ढांचे के साथ अटक कर रहा हूँ, इसलिए किसी भी समाधान है कि> = 3.0 में उपलब्ध सुविधाओं की आवश्यकता है सिर्फ मेरे लिए एक विकल्प नहीं हैं।

पीपीएस - मैं किसी भी .NET भाषा विविधता में समाधान के लिए खुला हूं, न केवल सी #।

+0

कोई पूर्ण नमूना स्रोत कोड? – Kiquenet

उत्तर

33

FileInfo.CopyTo मूल रूप से kernel32.dll में Win32 API कॉल "CopyFile" के चारों ओर एक रैपर है। यह विधि प्रगति कॉलबैक का समर्थन नहीं करती है।

हालांकि, CopyFileEx विधि करता है, और आप की तरह इसे यहाँ वर्णन किया गया है, कुछ ही मिनटों में इसके चारों ओर अपने स्वयं के नेट आवरण लिख सकते हैं: http://www.pinvoke.net/default.aspx/kernel32.CopyFileEx

+0

धन्यवाद गैस्पर। यह विकल्प इस मुद्दे से निपटने के लिए एक संभावित तरीका जैसा दिखता है। मैं इसे थोड़ा और देख लूंगा। –

+1

इसके लायक होने के लिए मैंने सफलतापूर्वक इस दृष्टिकोण का उपयोग किया है। असल में मुझे पूरा यकीन है कि मैंने सचमुच पिनवोक.net से बहुत कोड कॉपी किया है। एजेंटिडल आप सभी पैरामीटर से निपटने के बजाय इसे लपेटने के लिए एक अच्छी छोटी कक्षा बना सकते हैं। –

6

ईश्वर के प्रेम अपनी खुद की फ़ाइल को लागू नहीं करते के लिए धाराओं का उपयोग कर कॉपी करें! Win32 CopyFile API कॉल का उल्लेख है कि गैस्पर का उल्लेख उदाहरण का लाभ लेने में सक्षम है डीएमए, जबकि मैं डोनट्स के लिए डॉलर शर्त लगाता हूं कि कोड लिखा जाएगा "ऐसा करने के लिए पर्याप्त" स्मार्ट नहीं होगा।

CopyFileEx आपको सही तरीके से इलाज करेगा, या आप एक पृष्ठभूमिवर्कर को कार्यान्वित कर सकते हैं जो लक्ष्य फ़ाइल के बढ़ते आकार को देखता है और उस जानकारी का उपयोग करके प्रगति पट्टी को अद्यतन करता है। बाद की विधि आपको एक PInvoke बचाती है, लेकिन पूर्व लंबे समय तक शायद थोड़ा क्लीनर है।

+0

फ़ाइलइन्फो ऑब्जेक्ट का उपयोग करके लक्ष्य फ़ाइल को देखना और लंबाई की जांच करना एक और विकल्प है जिसे मैंने माना है। मैं मानता हूं कि CopyFileEx दृष्टिकोण का उपयोग शायद जाने का सबसे अच्छा तरीका है। –

5

इस तरह की चीजों के लिए मैं शेल 32 पर वापस आ गया हूं (या यह शेलूई है? मुझे अब और नहीं पता)। यह आपको एक मूल विंडोज संवाद देता है जिसे उपयोगकर्ताओं को प्रतिलिपि बनाने के लिए उपयोग करने के लिए उपयोग किया जाता है। मुझे लगता है कि यह आपके पहले से मौजूद संवाद को प्रतिस्थापित करेगा, इसलिए यह आपके लिए सही जवाब नहीं हो सकता है, लेकिन उन लोगों के लिए याद रखना उपयोगी है जो "चुटकी" परिदृश्य में हैं।

Microsoft.VisualBasic.FileIO.FileSystem.CopyFile(
    srcPath, 
    dstPath, 
    Microsoft.VisualBasic.FileIO.UIOption.AllDialogs,  
    Microsoft.VisualBasic.FileIO.UICancelOption.ThrowException 
); 

हां, आपको माइक्रोसॉफ्ट का संदर्भ देना होगा। विज़ुअल बेसिक असेंबली। मैं इस असेंबली में love तक बढ़ गया हूं।

+0

एकमात्र कारण मैंने इस मार्ग को नहीं लिया है कि मुझे यह सुनिश्चित करने की ज़रूरत है कि उपयोगकर्ता कॉपी ऑपरेशन रद्द नहीं कर सका। –

23

मैंने marked answer में दिए गए कार्यान्वयन का भी उपयोग किया। हालांकि मैंने .NET से उपयोग करने के लिए एक nicer ™ API प्रदान करने के लिए एक रैपर बनाया।

उपयोग:

XCopy.Copy(networkFile.FullPath, temporaryFilename, true, true, (o, pce) => 
{ 
    worker.ReportProgress(pce.ProgressPercentage, networkFile); 
}); 

कार्यान्वयन CopyFileEx विधि ओर इशारा करते हुए के लिए @Gasper और @Dennis को

/// <summary> 
/// PInvoke wrapper for CopyEx 
/// http://msdn.microsoft.com/en-us/library/windows/desktop/aa363852.aspx 
/// </summary> 
public class XCopy 
{ 
    public static void Copy(string source, string destination, bool overwrite, bool nobuffering) 
    { 
     new XCopy().CopyInternal(source, destination, overwrite, nobuffering, null);    
    } 

    public static void Copy(string source, string destination, bool overwrite, bool nobuffering, EventHandler<ProgressChangedEventArgs> handler) 
    {    
     new XCopy().CopyInternal(source, destination, overwrite, nobuffering, handler);    
    } 

    private event EventHandler Completed; 
    private event EventHandler<ProgressChangedEventArgs> ProgressChanged; 

    private int IsCancelled; 
    private int FilePercentCompleted; 
    private string Source; 
    private string Destination;   

    private XCopy() 
    { 
     IsCancelled = 0; 
    } 

    private void CopyInternal(string source, string destination, bool overwrite, bool nobuffering, EventHandler<ProgressChangedEventArgs> handler) 
    { 
     try 
     { 
      CopyFileFlags copyFileFlags = CopyFileFlags.COPY_FILE_RESTARTABLE; 
      if (!overwrite) 
       copyFileFlags |= CopyFileFlags.COPY_FILE_FAIL_IF_EXISTS; 

      if (nobuffering) 
       copyFileFlags |= CopyFileFlags.COPY_FILE_NO_BUFFERING; 

      Source = source; 
      Destination = destination; 

      if (handler != null) 
       ProgressChanged += handler; 

      bool result = CopyFileEx(Source, Destination, new CopyProgressRoutine(CopyProgressHandler), IntPtr.Zero, ref IsCancelled, copyFileFlags); 
      if (!result) 
       throw new Win32Exception(Marshal.GetLastWin32Error()); 
     } 
     catch (Exception) 
     { 
      if (handler != null) 
       ProgressChanged -= handler; 

      throw; 
     } 
    } 

    private void OnProgressChanged(double percent) 
    { 
     // only raise an event when progress has changed 
     if ((int)percent > FilePercentCompleted) 
     { 
      FilePercentCompleted = (int)percent; 

      var handler = ProgressChanged; 
      if (handler != null) 
       handler(this, new ProgressChangedEventArgs((int)FilePercentCompleted, null)); 
     } 
    } 

    private void OnCompleted() 
    { 
     var handler = Completed; 
     if (handler != null) 
      handler(this, EventArgs.Empty); 
    } 

    #region PInvoke 

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

    private delegate CopyProgressResult CopyProgressRoutine(long TotalFileSize, long TotalBytesTransferred, long StreamSize, long StreamBytesTransferred, uint dwStreamNumber, CopyProgressCallbackReason dwCallbackReason, 
                IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData); 

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

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

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

    private CopyProgressResult CopyProgressHandler(long total, long transferred, long streamSize, long streamByteTrans, uint dwStreamNumber, 
                CopyProgressCallbackReason reason, IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData) 
    { 
     if (reason == CopyProgressCallbackReason.CALLBACK_CHUNK_FINISHED) 
      OnProgressChanged((transferred/(double)total) * 100.0); 

     if (transferred >= total) 
      OnCompleted(); 

     return CopyProgressResult.PROGRESS_CONTINUE; 
    } 

    #endregion 

} 
+0

वास्तव में यह बहुत प्यारा है ... –

+0

यह अच्छा है। मैं वास्तव में इसका उपयोग समाप्त नहीं कर पाया क्योंकि मुझे फ़ाइल async डाउनलोड करने के लिए 'WebClient' का उपयोग करके x100 बेहतर प्रदर्शन मिला। – Dennis

+0

@ डेनिस यहां मेरी पोस्ट देखें यदि आपके पास कुछ समय है (इस कोड का उपयोग करके) http://stackoverflow.com/questions/10354610/copyfileex-the-parameter-is-invalid-error – Mansfield

3

धन्यवाद। मैं बीच में बंद करें प्रतिलिपि

/// <summary> 
    /// Type indicates how the copy gets completed. 
    /// </summary> 
    internal enum CopyCompletedType 
    { 
     Succeeded, 
     Aborted, 
     Exception 
    } 

/// <summary> 
/// Event arguments for file copy 
/// </summary> 
internal class FileCopyEventArgs : EventArgs 
{ 
    /// <summary> 
    /// Constructor 
    /// </summary> 
    /// <param name="type">type of the copy completed type enum</param> 
    /// <param name="exception">exception if any</param> 
    public FileCopyEventArgs(CopyCompletedType type, Exception exception) 
    { 
     Type = type; 
     Exception = exception; 
    } 

    /// <summary> 
    /// Type of the copy completed type 
    /// </summary> 
    public CopyCompletedType Type 
    { 
     get; 
     private set; 

    } 

    /// <summary> 
    /// Exception if any happend during copy. 
    /// </summary> 
    public Exception Exception 
    { 
     get; 
     private set; 
    } 

} 

/// <summary> 
/// PInvoke wrapper for CopyEx 
/// http://msdn.microsoft.com/en-us/library/windows/desktop/aa363852.aspx 
/// </summary> 
internal class XCopy 
{ 

    private int IsCancelled; 
    private int FilePercentCompleted; 

    public XCopy() 
    { 
     IsCancelled = 0; 
    } 

    /// <summary> 
    /// Copies the file asynchronously 
    /// </summary> 
    /// <param name="source">the source path</param> 
    /// <param name="destination">the destination path</param> 
    /// <param name="nobuffering">Bufferig status</param> 
    /// <param name="handler">Event handler to do file copy.</param> 
    public void CopyAsync(string source, string destination, bool nobuffering) 
    { 
     try 
     { 
      //since we needed an async copy .. 
      Action action = new Action(
       () => CopyInternal(source, destination, nobuffering) 
        ); 
      Task task = new Task(action); 
      task.Start(); 
     } 
     catch (AggregateException ex) 
     { 
      //handle the inner exception since exception thrown from task are wrapped in 
      //aggreate exception. 
      OnCompleted(CopyCompletedType.Exception, ex.InnerException); 
     } 
     catch (Exception ex) 
     { 
      OnCompleted(CopyCompletedType.Exception, ex); 
     } 
    } 

    /// <summary> 
    /// Event which will notify the subscribers if the copy gets completed 
    /// There are three scenarios in which completed event will be thrown when 
    /// 1.Copy succeeded 
    /// 2.Copy aborted. 
    /// 3.Any exception occured. 
    /// These information can be obtained from the Event args. 
    /// </summary> 
    public event EventHandler<FileCopyEventArgs> Completed; 
    /// <summary> 
    /// Event which will notify the subscribers if there is any progress change while copying. 
    /// This will indicate the progress percentage in its event args. 
    /// </summary> 
    public event EventHandler<ProgressChangedEventArgs> ProgressChanged; 

    /// <summary> 
    /// Aborts the copy asynchronously and throws Completed event when done. 
    /// User may not want to wait for completed event in case of Abort since 
    /// the event will tell that copy has been aborted. 
    /// </summary> 
    public void AbortCopyAsync() 
    { 
     Trace.WriteLine("Aborting the copy"); 
     //setting this will cancel an operation since we pass the 
     //reference to copyfileex and it will periodically check for this. 
     //otherwise also We can check for iscancelled on onprogresschanged and return 
     //Progress_cancelled . 
     IsCancelled = 1; 

     Action completedEvent = new Action(() => 
      { 
       //wait for some time because we ll not know when IsCancelled is set , at what time windows stops copying. 
       //so after sometime this may become valid . 
       Thread.Sleep(500); 
       //do we need to wait for some time and send completed event. 
       OnCompleted(CopyCompletedType.Aborted); 
       //reset the value , otherwise if we try to copy again since value is 1 , 
       //it thinks that its aborted and wont allow to copy. 
       IsCancelled = 0; 
      }); 

     Task completedTask = new Task(completedEvent); 
     completedTask.Start(); 
    } 


    /// <summary> 
    /// Copies the file using asynchronos task 
    /// </summary> 
    /// <param name="source">the source path</param> 
    /// <param name="destination">the destination path</param> 
    /// <param name="nobuffering">Buffering status</param> 
    /// <param name="handler">Delegate to handle Progress changed</param> 
    private void CopyInternal(string source, string destination, bool nobuffering) 
    { 
     CopyFileFlags copyFileFlags = CopyFileFlags.COPY_FILE_RESTARTABLE; 

     if (nobuffering) 
     { 
      copyFileFlags |= CopyFileFlags.COPY_FILE_NO_BUFFERING; 
     } 

     try 
     { 
      Trace.WriteLine("File copy started with Source: " + source + " and destination: " + destination); 
      //call win32 api. 
      bool result = CopyFileEx(source, destination, new CopyProgressRoutine(CopyProgressHandler), IntPtr.Zero, ref IsCancelled, copyFileFlags); 
      if (!result) 
      { 
       //when ever we get the result as false it means some error occured so get the last win 32 error. 
       throw new Win32Exception(Marshal.GetLastWin32Error()); 
      } 
     } 
     catch (Exception ex) 
     { 
      //the mesage will contain the requested operation was aborted when the file copy 
      //was cancelled. so we explicitly check for that and do a graceful exit 
      if (ex.Message.Contains("aborted")) 
      { 
       Trace.WriteLine("Copy aborted."); 
      } 
      else 
      { 
       OnCompleted(CopyCompletedType.Exception, ex.InnerException); 
      } 
     } 
    } 

    private void OnProgressChanged(double percent) 
    { 
     // only raise an event when progress has changed 
     if ((int)percent > FilePercentCompleted) 
     { 
      FilePercentCompleted = (int)percent; 

      var handler = ProgressChanged; 
      if (handler != null) 
      { 
       handler(this, new ProgressChangedEventArgs((int)FilePercentCompleted, null)); 
      } 
     } 
    } 

    private void OnCompleted(CopyCompletedType type, Exception exception = null) 
    { 
     var handler = Completed; 
     if (handler != null) 
     { 
      handler(this, new FileCopyEventArgs(type, exception)); 
     } 
    } 

    #region PInvoke 

    /// <summary> 
    /// Delegate which will be called by Win32 API for progress change 
    /// </summary> 
    /// <param name="total">the total size</param> 
    /// <param name="transferred">the transferrred size</param> 
    /// <param name="streamSize">size of the stream</param> 
    /// <param name="streamByteTrans"></param> 
    /// <param name="dwStreamNumber">stream number</param> 
    /// <param name="reason">reason for callback</param> 
    /// <param name="hSourceFile">the source file handle</param> 
    /// <param name="hDestinationFile">the destination file handle</param> 
    /// <param name="lpData">data passed by users</param> 
    /// <returns>indicating whether to continue or do somthing else.</returns> 
    private CopyProgressResult CopyProgressHandler(long total, long transferred, long streamSize, long streamByteTrans, uint dwStreamNumber, 
                CopyProgressCallbackReason reason, IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData) 
    { 
     //when a chunk is finished call the progress changed. 
     if (reason == CopyProgressCallbackReason.CALLBACK_CHUNK_FINISHED) 
     { 
      OnProgressChanged((transferred/(double)total) * 100.0); 
     } 

     //transfer completed 
     if (transferred >= total) 
     { 
      if (CloseHandle(hDestinationFile)) 
      { 
       OnCompleted(CopyCompletedType.Succeeded, null); 
      } 
      else 
      { 
       OnCompleted(CopyCompletedType.Exception, 
        new System.IO.IOException("Unable to close the file handle")); 
      } 
     } 

     return CopyProgressResult.PROGRESS_CONTINUE; 
    } 
    [System.Runtime.InteropServices.DllImport("Kernel32")] 
    private extern static Boolean CloseHandle(IntPtr handle); 

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

    private delegate CopyProgressResult CopyProgressRoutine(long TotalFileSize, long TotalBytesTransferred, long StreamSize, long StreamBytesTransferred, uint dwStreamNumber, CopyProgressCallbackReason dwCallbackReason, 
                IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData); 

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

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

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

    #endregion 

} 

साथ डेनिस जवाब विस्तार किया है ग्राहकों/XCopy वर्ग और कॉल प्रतिलिपि की एक वस्तु बना सकते हैं विधि गर्भपात।

+0

CloseHandle (hDestinationFile) को निष्पादित नहीं किया जाना चाहिए क्योंकि ओएस भी हैंडल को बंद करने का प्रयास करेगा और विफल होने पर अपवाद लौटाएगा। ऑनकॉम्प्लेटेड (CopyCompleteType.Succeeded ... को CopyInternal() – Mike

9

मैं जानता हूँ कि मैं पार्टी के लिए देर से एक सा हूँ, लेकिन मुझे लगता है कि एक Task वापस आती है और एक CancellationToken और IProgress<double> स्वीकार करता CopyFileEx के लिए एक आवरण बना दिया। दुर्भाग्य से यह .NET 2.0 ढांचे में काम नहीं करेगा, लेकिन 4.5 का उपयोग करने वाले किसी के लिए, यह आपको await कीवर्ड का उपयोग करने की अनुमति देता है।

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; 
     if (progress != null) 
     { 
      copyProgressHandler = (total, transferred, streamSize, streamByteTrans, dwStreamNumber, reason, hSourceFile, hDestinationFile, lpData) => 
      { 
       progress.Report((double)transferred/total * 100); 
       return CopyProgressResult.PROGRESS_CONTINUE; 
      }; 
     } 
     else 
     { 
      copyProgressHandler = EmptyCopyProgressHandler; 
     } 
     token.ThrowIfCancellationRequested(); 
     var ctr = token.Register(() => pbCancel = 1); 
     var copyTask = Task.Run(() => 
     { 
      try 
      { 
       CopyFileEx(sourceFileName, destFileName, copyProgressHandler, IntPtr.Zero, ref pbCancel, CopyFileFlags.COPY_FILE_RESTARTABLE); 
       token.ThrowIfCancellationRequested(); 
      } 
      finally 
      { 
       ctr.Dispose(); 
      } 
     }, 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 
} 
+0

द्वारा निष्पादित करना चाहिए, मैंने 6 साल पहले प्रश्न पूछा था, इसलिए समय के लिए प्रासंगिक एक अद्यतन उत्तर निश्चित रूप से स्वागत है। –

संबंधित मुद्दे

 संबंधित मुद्दे