2012-12-20 31 views
6

Gần đây tôi đã phải thay đổi từ việc sử dụng File.Copy() thành CopyFileEx và tôi đang cố gắng tìm cách sử dụng nó.Thông số trình bao bọc CopyFileEx

Sau rất nhiều googling tôi tìm thấy this wrapper đẹp để sử dụng nó, nhưng những gì tôi cần là để có được sự tiến bộ của byte được sao chép của tập tin hiện tại, và nếu có thể tính toán tiến trình sao chép tất cả các tập tin tôi vượt qua nó .

(Tôi biết có các dự án có thanh tiến trình được liên kết với CopyFileEx nhưng tôi không đủ kinh nghiệm để rút ra mã có liên quan và tôi muốn sử dụng trình bao bọc này).

Có lẽ chỉ bằng cách so sánh nó với tổng số byte của tệp cần sao chép, mà tôi sẽ tìm thấy trước đó và tính tỷ lệ phần trăm từ đó.

phương pháp hiện tại của tôi sao chép là

FileRoutines.CopyFile(new FileInfo("source.txt"), new FileInfo("dest.txt")); 

Những gì tôi đang bị mắc kẹt trên là làm thế nào để quá tải nó với các thông số của cần thiết để có được các thông tin tiến bộ.

public sealed class FileRoutines 
{ 
    public static void CopyFile(FileInfo source, FileInfo destination) 
    { 
     CopyFile(source, destination, CopyFileOptions.None); 
    } 

    public static void CopyFile(FileInfo source, FileInfo destination, 
     CopyFileOptions options) 
    { 
     CopyFile(source, destination, options, null); 
    } 

    public static void CopyFile(FileInfo source, FileInfo destination, 
     CopyFileOptions options, CopyFileCallback callback) 
    { 
     CopyFile(source, destination, options, callback, null); 
    } 

    public static void CopyFile(FileInfo source, FileInfo destination, 
     CopyFileOptions options, CopyFileCallback callback, object state) 
    { 
     if (source == null) throw new ArgumentNullException("source"); 
     if (destination == null) 
      throw new ArgumentNullException("destination"); 
     if ((options & ~CopyFileOptions.All) != 0) 
      throw new ArgumentOutOfRangeException("options"); 

     new FileIOPermission(
      FileIOPermissionAccess.Read, source.FullName).Demand(); 
     new FileIOPermission(
      FileIOPermissionAccess.Write, destination.FullName).Demand(); 

     CopyProgressRoutine cpr = callback == null ? 
      null : new CopyProgressRoutine(new CopyProgressData(
       source, destination, callback, state).CallbackHandler); 

     bool cancel = false; 
     if (!CopyFileEx(source.FullName, destination.FullName, cpr, 
      IntPtr.Zero, ref cancel, (int)options)) 
     { 
      throw new IOException(new Win32Exception().Message); 
     } 
    } 

    private class CopyProgressData 
    { 
     private FileInfo _source = null; 
     private FileInfo _destination = null; 
     private CopyFileCallback _callback = null; 
     private object _state = null; 

     public CopyProgressData(FileInfo source, FileInfo destination, 
      CopyFileCallback callback, object state) 
     { 
      _source = source; 
      _destination = destination; 
      _callback = callback; 
      _state = state; 
     } 

     public int CallbackHandler(
      long totalFileSize, long totalBytesTransferred, 
      long streamSize, long streamBytesTransferred, 
      int streamNumber, int callbackReason, 
      IntPtr sourceFile, IntPtr destinationFile, IntPtr data) 
     { 
      return (int)_callback(_source, _destination, _state, 
       totalFileSize, totalBytesTransferred); 
     } 
    } 

    private delegate int CopyProgressRoutine(
     long totalFileSize, long TotalBytesTransferred, long streamSize, 
     long streamBytesTransferred, int streamNumber, int callbackReason, 
     IntPtr sourceFile, IntPtr destinationFile, IntPtr data); 

    [SuppressUnmanagedCodeSecurity] 
    [DllImport("Kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)] 
    private static extern bool CopyFileEx(
     string lpExistingFileName, string lpNewFileName, 
     CopyProgressRoutine lpProgressRoutine, 
     IntPtr lpData, ref bool pbCancel, int dwCopyFlags); 
} 

public delegate CopyFileCallbackAction CopyFileCallback(
    FileInfo source, FileInfo destination, object state, 
    long totalFileSize, long totalBytesTransferred); 

public enum CopyFileCallbackAction 
{ 
    Continue = 0, 
    Cancel = 1, 
    Stop = 2, 
    Quiet = 3 
} 

[Flags] 
public enum CopyFileOptions 
{ 
    None = 0x0, 
    FailIfDestinationExists = 0x1, 
    Restartable = 0x2, 
    AllowDecryptedDestination = 0x8, 
    All = FailIfDestinationExists | Restartable | AllowDecryptedDestination 
} 

Mọi con trỏ thực sự được đánh giá cao.

+0

Mã này trông giống với mã của bài viết trên Tạp chí MSDN. Nếu vậy, bạn nên ghi có bản gốc. http://msdn.microsoft.com/en-us/magazine/cc163851.aspx –

+1

@ChrisDolan - liên kết chỉ trỏ tới kho lưu trữ tạp chí MSDN - xem chm cho tạp chí MSDN tháng 2 năm 2005 .Net Matters Hình 1 FileRoutines.CopyFile Using Win32 CopyFileEx –

+1

@ TheLonelyCoder - Hmm, bạn nói đúng. Tôi đã tìm thấy nó ở đây: https://web.archive.org/web/20130304214632/http://msdn.microsoft.com/en-us/magazine/cc163851.aspx nhưng không có CSS ​​nên rất khó để đọc –

Trả lời

8

Trình bao bọc đã có đường ống dẫn nước cần thiết để xử lý tiến trình. Chỉ cần thực hiện mã để cập nhật thanh tiến trình của bạn trong CallbackHandler trước khi trở về. Giá trị progressBar1.Maximum mặc định là 100, vì vậy mã bên dưới sẽ tính phần trăm.

Thay thế gọi CopyFile hiện tại của bạn với điều này:

CopyFileCallbackAction myCallback(FileInfo source, FileInfo destination, object state, long totalFileSize, long totalBytesTransferred) 
{ 
    double dProgress = (totalBytesTransferred/(double)totalFileSize) * 100.0; 
    progressBar1.Value = (int)dProgress; 
    return CopyFileCallbackAction.Continue; 
} 

FileRoutines.CopyFile(new FileInfo("source.txt"), new FileInfo("dest.txt"), myCallback); 
+0

Cảm ơn câu trả lời của bạn. Tôi biết mã đã có, tôi chỉ không biết làm thế nào để sử dụng nó :) Bạn có thể cho tôi một ví dụ mã? –

+0

@BaliC - Mã được thêm theo yêu cầu. :) –

+0

Cảm ơn rất nhiều, tôi sẽ kiểm tra tối nay và sẽ cho bạn biết nếu nó hoạt động :) –

0

Nếu bạn chỉ muốn hiển thị một thanh tiến trình cho một bản sao tập tin, bạn có thể làm this. Nó sử dụng hộp thoại tiêu chuẩn Windows cho thấy một thanh tiến trình và thời gian còn lại, và nó có một nút Cancel. Đó chỉ là những gì tôi cần về cơ bản một dòng mã.

// The following using directive requires a project reference to Microsoft.VisualBasic. 
using Microsoft.VisualBasic.FileIO; 

class FileProgress 
{ 
    static void Main() 
    { 
     // Specify the path to a folder that you want to copy. If the folder is small, 
     // you won't have time to see the progress dialog box. 
     string sourcePath = @"C:\Windows\symbols\"; 
     // Choose a destination for the copied files. 
     string destinationPath = @"C:\TestFolder"; 

     FileSystem.CopyDirectory(sourcePath, destinationPath, 
      UIOption.AllDialogs); 
    } 
} 
Các vấn đề liên quan