2012-04-27 155 views
2

我正在寫一個(相當)簡單的C#應用​​程序,使用.NET 4在運行可執行文件之前檢查更新。如果網絡共享上存在更新版本的exe,只需將其複製到本地文件夾並啓動即可。除了在瞭解File.Copy()的侷限性時,這一切都工作得很完美,我意識到當我這樣做時我不能顯示進度條,而且我看到的所有內容都表示使用CopyFileEx,米試圖做到這一點。CopyFileEx「參數無效」錯誤

我使用的樣例代碼中發現here,它編譯罰款(雖然我仍然BackgroundWorker的究竟是如何發揮作用的有點不確定),除了當我真正去運行應用程序時,CopyFilEx()方法返回錯誤,錯誤是「參數不正確」。

我的代碼(有關章節而已,我會添加更多的如果需要的話)

調用函數:

XCopy.Copy(strServerAppPath + strExeName, strLocalAppPath + strExeName, true, true, (o, pce) => 
{ 
worker.ReportProgress(pce.ProgressPercentage, strServerAppPath + strExeName); 
}); 

(源路徑的計算結果爲 「C:\ test.txt的」 和的目標路徑 「C:\測試\ test.txt的」)

凡在上面的代碼鏈接錯誤發生:

bool result = CopyFileEx(Source, Destination, new CopyProgressRoutine(CopyProgressHandler), IntPtr.Zero, ref IsCancelled, copyFileFlags); 
      if (!result) 
       throw new Win32Exception(Marshal.GetLastWin32Error()); 

在此先感謝您的幫助,我一直在爲此奮鬥了幾個小時...

回答

3

與其處理所有的編組問題,只是「滾動您自己的」複印機塊:

private static void CopyFile(string source, string destination, int bytesPerChunk) 
{ 
    int bytesRead = 0; 

    using (FileStream fs = new FileStream(source, FileMode.Open, FileAccess.Read)) 
    { 
     using (BinaryReader br = new BinaryReader(fs)) 
     { 
      using (FileStream fsDest = new FileStream(destination, FileMode.Create)) 
      { 
       BinaryWriter bw = new BinaryWriter(fsDest); 
       byte[] buffer; 

       for (int i = 0; i < fs.Length; i += bytesPerChunk) 
       { 
        buffer = br.ReadBytes(bytesPerChunk); 
        bw.Write(buffer); 
        bytesRead += bytesPerChunk; 
        ReportProgress(bytesRead, fs.Length); //report the progress 
       } 
      } 
     } 
    } 
} 
+0

看起來很有意思......我以前見過類似的答案,但一般認爲似乎是copyfileex更好(如果真的可以讓它工作)。不管怎麼說,我都會試一試:) – Mansfield 2012-04-27 16:53:33

+0

它很有效,所以我會去用它。非常感謝! – Mansfield 2012-04-27 17:32:03

+2

使用'ReadBytes(byte [],int,int)'方法可能會更好,它可以重用相同的緩衝區,而不是爲每個讀操作創建一個新的數組。 (http://msdn.microsoft.com/en-us/library/ms143295.aspx) – 2012-04-27 20:34:58

3

與其說ReadBytes(),其上的每個呼叫分配一個新的byte[]緩衝器陣列的,分配單個緩衝液(,比方說在大小64KB)和呼叫Read(buf, 0, buf.Length),這將讀取多達buf.Length字節進數組,然後返回讀取的實際字節數。然後在每次讀取時重新使用相同的緩衝區陣列(將其內容寫入目標流之後)。這節省了爲每個讀/寫操作重新分配新的緩衝區。

例如,流複製方法的內環將看起來像這樣:

byte[] buf; 

// Allocate an I/O data buffer 
buf = new byte[64*1024]; 

// Copy the contents of the input stream to the output stream 
for (;;) 
{ 
    int  len; 

    // Read a block of data from the input stream 
    len = inp.ReadBytes(buf, 0, buf.Length); 
    if (len <= 0) 
     break; 

    // Write the data to the output stream 
    outp.Write(buf, 0, len); 
} 

的循環讀取到64KB從輸入流的字節到緩衝,然後寫出讀取到輸出流的實際字節數。每個讀/寫操作使用相同的緩衝區,所以我們不做不必要的分配和釋放緩衝區。當讀取操作失敗時,我們已經到達輸入流的末尾,所以我們退出循環。

+0

感謝您的提示! – Mansfield 2014-06-04 12:09:02

+0

@David R Tribble Pls。提供'ReportProgress(bytesRead,fs.Length)'的實現,還是應該使用與CopyFileEx中相同的後臺工作器? – Khan 2015-02-09 09:37:57