2012-12-20 124 views
6

我最近不得不改變使用File.Copy()CopyFileEx,我正在努力尋找如何使用它。CopyFileEx包裝參數

經過大量的谷歌搜索後,我發現this不錯的包裝使用它,但我需要的是獲取當前文件的複製字節的進度,並且如果可能的話計算複製所有文件的進度, 。我知道有一些項目的進度條鏈接到CopyFileEx,但我沒有足夠的經驗去推出相關的代碼,並且我想使用這個包裝器)。

大概只是將它與要預先複製的文件的總字節數進行比較,然後從中找出百分比。

我複製當前的方法是

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

我被困在什麼是如何與參數的獲取進度信息需要重載它。

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 
} 

任何指針真的很感激。

+0

此代碼看起來與MSDN Magazine文章的代碼完全相同。如果是這樣,你應該相信原來的。 http://msdn.microsoft.com/en-us/magazine/cc163851.aspx –

+1

@ChrisDolan - 鏈接只是指向MSDN雜誌存檔 - 請參閱MSDN雜誌chm 2005年2月.Net Matters圖1 FileRoutines.CopyFile使用Win32 CopyFileEx –

+1

@TheLonelyCoder - 嗯,你是對的。我在這裏重新找到它:https://web.archive.org/web/20130304214632/http://msdn.microsoft.com/en-us/magazine/cc163851.aspx但沒有CSS,所以它很難閱讀 –

回答

8

包裝已經有處理進度所需的管道。在返回之前,只需實現代碼以在CallbackHandler中更新進度條。 progressBar1.Maximum默認爲100,所以下面的代碼將計算百分比。

這個替換您當前的CopyFile電話:

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

感謝您的回答。我知道代碼已經存在,我只是不知道如何使用它:)你能給我一個代碼示例嗎? –

+0

@BaliC - 按要求添加的代碼。 :) –

+0

非常感謝,今晚我會測試,並會告訴你它是否有效:) –

0

如果你只是想顯示文件複製進度條,你可以做this。它使用顯示進度條和剩餘時間的Windows標準對話框,並且它有一個取消按鈕。這正是我基本上需要的一行代碼。

// 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); 
    } 
}