web-dev-qa-db-ja.com

別のプロセスで使用されているファイルをコピーする方法

別のプロセスが使用しているファイルを同時にコピーすることはできますか?

次のコードを使用してファイルをコピーしようとすると例外が発生するため、私は尋ねます:

 System.IO.File.Copy(s, destFile, true);

発生する例外は次のとおりです。

プロセスは別のプロセスで使用されているため、ファイル 'D:\ temp\1000000045.Zip'にアクセスできません。

新しいファイルを作成するのではなく、コピーまたは削除するだけです。これは可能ですか?

30
Vir

例(注:2つのGoogleの結果を組み合わせただけです。小さなエラーを修正する必要があるかもしれません;))

重要な部分はFileShare.ReadWrite FileStreamを開くとき。

Excelが開いたままファイルをブロックしている間に、同様のコードを使用してExcelドキュメントを開いて読み取ります。

using (var inputFile = new FileStream(
    "oldFile.txt",
    FileMode.Open,
    FileAccess.Read,
    FileShare.ReadWrite))
{
    using (var outputFile = new FileStream("newFile.txt", FileMode.Create))
    {
        var buffer = new byte[0x10000];
        int bytes;

        while ((bytes = inputFile.Read(buffer, 0, buffer.Length)) > 0)
        {
            outputFile.Write(buffer, 0, bytes);
        }
    }
}
34
Zebi

Windows上の別のプロセスによって読み取り/書き込みロックされたファイルのコピーを作成するための最も簡単な(そしておそらく唯一の)ソリューションは、ボリュームシャドウコピーサービス(VSS)を使用することです。

ボリュームシャドウコピーサービスは複雑で、マネージコードから呼び出すのは困難です。幸いなことに、いくつかのすばらしいチャップがこれを行うための.NETクラスライブラリを作成しました。 CodePlexのAlpha VSSプロジェクトを確認してください: http://alphavss.codeplex.com

[〜#〜] edit [〜#〜]

CodePlexの多くのプロジェクトと同様に、Alpha VSSはGitHubに移行しました。プロジェクトはここにあります: https://github.com/alphaleonis/AlphaVSS

9
STLDev

ファイルをブロックしているプロセスを調べて見つける必要があります。このプロセスがあなたのものでない場合、問題を解決する方法はありません。もちろん、いくつかのハッキングを適用し、手動でファイルロックを解除することもできますが、このアプローチは疑いのない結果につながる可能性が高いです。プロセスが自分のものである場合は、ファイルのロックを解除するか、共有読み取りアクセスでロックしてください。

[編集]
ブロッカープロセスを見つける最も簡単な方法は、 Process Explorer 。Launchを使用して起動し、Find->Find Handle or DLL... ダイアログボックス。検索結果では、ファイルをブロックしているプロセスを確認できます。 C#でこのジョブを実行することもできます: どのプロセスがファイルをロックしますか? 。また

3
Anton Semenov

いいえ、できません。一部のプログラムは読み取り用にファイルをロックしませんが、ロックすると、他のプログラムを強制終了せずにファイルにアクセスできなくなります。

0
GolezTrol

別のオプションは、Processクラスを使用してロックされたファイルをどこかにコピーし、CMDを呼び出して "copy"コマンドを使用することです。ほとんどの場合、「コピー」コマンドは、ファイルが別のプロセスで使用されている場合でも、C#File.Copyの問題を回避してファイルのコピーを作成できます。

例:

try
{
File.Copy(somefile)
}
catch (IOException e)
{
 if (e.Message.Contains("in use"))
                        {

                            Process.StartInfo.UseShellExecute = false;
                            Process.StartInfo.RedirectStandardOutput = true;                           
                            Process.StartInfo.FileName = "cmd.exe";
                            Process.StartInfo.Arguments = "/C copy \"" + yourlockedfile + "\" \"" + destination + "\"";
                            Process.Start();                            
                            Console.WriteLine(Process.StandardOutput.ReadToEnd());
                            Proess.WaitForExit();
                            Process.Close();                          
                        }
}

the try/catch should be added on top of your current try/catch to handle the file in use exception to allow your code to continue... 
0
MickeyM