32726


ファイル操作のテストを行うプログラムを書いています。作業用のディレクトリが既に存在する場合は削除してから作り直そうと思い、次のように書きました。

[code]

    if (Directory.Exists("foo"))
        Directory.Delete("foo", true);
    Directory.CreateDirectory("foo");
    
[/code]

ところがディレクトリ foo
が既に存在している状態でこれを実行すると、ディレクトリが削除されるだけで再作成が行われません。この時も例外は出ていないようです。

同じようなコードがファイルに対しては問題なく動くのですが・・・。

[code]

    if(File.Exists("bar"))
        File.Delete("bar");
    File.WriteAllText("bar", "");
    
[/code]

ディレクトリの再作成を行うにはどうすればよいでしょうか？  
上記のような挙動になる理由も教えていただけると助かります。


CC BY-SA 3.0
2017-02-16T11:33:57.020
32725
2017-02-18T01:39:15.310
20681
question
c# windows
Directory.Deleteした直後のDirectory.CreateDirectoryがうまく動かない


[`Directory.Delete`](https://msdn.microsoft.com/ja-
jp/library/62t64db3\(v=vs.100\).aspx)のリファレンスに触れられていますが、対象のディレクトリを「エクスプローラーで開いている」と削除がすぐに行われない場合があります。

> 場合によっては、指定したディレクトリを Windows エクスプローラーで開いていると、Delete メソッドで削除できないことがあります。

[内部的](https://referencesource.microsoft.com/#mscorlib/system/io/directory.cs,1486)に使用している[`RemoveDirectory`](https://msdn.microsoft.com/en-
us/library/aa365488.aspx)関数によるとこれはエクスプローラーに限った問題ではないようです。

> The RemoveDirectory function marks a directory for deletion on close.
> Therefore, the directory is not removed until the last handle to the
> directory is closed.

ですので`while`などを使用して実際に削除されるまで待機するのが良いかと思います。


CC BY-SA 3.0
2017-02-16T12:32:30.647
32726
2017-02-16T12:32:30.647
5750
32725
answer


`Directory.Exists("foo")`でファイルの存在確認を行うとウィルス対策ソフトがスキャンを開始する場合があります。その場合、`Directory.Delete("foo",
true)`はpgrhoさんが指摘されているように削除マークが付けられるだけで、実際の削除が遅延させられる可能性があります。  
また`Directory.CreateDirectory("foo")`は[ドキュメント](https://msdn.microsoft.com/ja-
jp/library/54a0at6s\(v=vs.100\).aspx)にあるように

> 既存のディレクトリがある場合は、このメソッドは何も実行しません。

その上で、ウィルス対策ソフトのスキャンが完了すると削除マークに従い、ディレクトリが削除されます。

* * *
[code]

    try {
        Directory.Delete("foo", true);
    }
    catch (DirectoryNotFoundException) {}
    Directory.CreateDirectory("foo");
    
[/code]

と直接削除しにいった方がいいかもしれません。もしくはディレクトリ内のファイルを削除した方がいいです。


CC BY-SA 3.0
2017-02-16T13:03:26.147
32727
2017-02-16T13:03:26.147
4236
32725
answer


最終手段として

IFileOperation::Deleteitems() API  
<https://msdn.microsoft.com/en-us/library/bb775767(v=vs.85).aspx>

使うという手もあると思います。

試していませんが、↑は Win32 よりも上位の、Windows Shell (≒
Explorer.exe）の機能呼び出しを行うもの（のはず）なので、期待した動作を得られるのではないでしょうか。


CC BY-SA 3.0
2017-02-18T01:39:15.310
32760
2017-02-18T01:39:15.310
3033
32725
answer