2012-04-27 9 views
2

.NET(実行可能ファイルを実行する前に、アップデートを確認するために.NET 4を使用している(かなり)単純なC#アプリケーションを作成しています。新しいバージョンのexeがネットワーク共有に存在する場合は、それをローカルフォルダにコピーして起動するだけです。 File.Copy()の限界を読んでいる間を除いて、すべて完璧に動作しています。私はこれを行っている間にプログレスバーを表示できないことに気付きました。私が見たすべてのものはCopyFileExを使用すると言いました。それをやろうとしている。CopyFileEx "パラメータが無効です"エラー

私はサンプルコードhereを使用していましたが、実際にアプリケーションを実行するときを除いて、CopyFilEx()メソッドが返す以外は細かい部分をコンパイルすることができます。 falseで、「パラメータが正しくありません」というエラーが表示されます。

私のコード(必要であれば、関連するセクションのみ、私はより多くを追加します)

関数を呼び出す:

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

マーシャルのすべてを扱うのではなく、ちょうど "自分の"チャンク:すべての呼び出しで新しいbyte[]バッファ配列を割り当て、その代わりReadBytes()を呼び出すの

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

+0

それは働いたので、私はそれに行くでしょう。どうもありがとう! – Mansfield

+2

'ReadBytes(byte []、int、int)'メソッドを使うほうが良いかもしれません。これは、読み込み操作ごとに新しい配列を作成するのではなく、同じバッファを再利用できます。 (http://msdn.microsoft.com/en-us/library/ms143295.aspx) –

3

、へbuf.Lengthバイトまで読まれる、(サイズが64キロバイトを言うの)単一のバッファを割り当て、Read(buf, 0, 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); 
} 

をループがバッファに入力ストリームからバイトの64キロバイトまで読み出し次に、読み取られた実際のバイト数を出力ストリームに書き出します。同じバッファが各読み込み/書き込み操作に使用されるため、バッファの不要な割り当てや割り当て解除は行われません。読み込み操作が失敗すると、入力ストリームの最後に到達したので、ループを終了します。

+0

チップをありがとう! – Mansfield

+0

@David R Tribble Pls。 'ReportProgress(bytesRead、fs.Length)'の実装を提供するか、CopyFileExの場合と同じバックグラウンドワーカーを使用する必要がありますか? – Khan

関連する問題