Ask Learn
Preview
Ask Learn is an AI assistant that can answer questions, clarify concepts, and define terms using trusted Microsoft documentation.
Please sign in to use Ask Learn.
Sign inThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
こんにちは。Windows SDK のサポートをしています masanish です。 今回は、ファイルの削除についてしばしばお問い合わせいただく話題をご紹介します。
ファイルが消せない
いらなくなったファイルを ”完全に" 削除するには、コマンドプロンプトの Del コマンドや エクスプローラー で [Shift] + [Del] を利用しますね。ところが、ファイルを削除しようとしても、消せない、消えてくれないという経験はないでしょうか。この理由として2つのパターンがあります。
1つは、そもそもそのファイルを削除する権限を持っていない場合です。同じコンピュータを利用している別のユーザが作成したファイルとか、もともと Windows を動かすために必要なファイルだったりすると、消されると都合が悪いですね。Windowsでは、それぞれのファイルについて、誰がファイルを消す権限をもっているかどうか決められているので、許可されていない場合にはファイルを消すことができません。
もう1つは、そのファイルが使用中の場合です。使用中というのは、プログラマ的な表現にすると、別のプログラム(プロセス)そのファイルを開いている場合です。だれかが、ほかで使っているいるのに、そのファイルが突然消されてしまうとやっぱり具合が悪いですね。この場合もファイルを消そうとしても失敗します。いずれも、ファイルを消せない理由があるのです。
(消せない...使っているのはだれかぁ)
「ファイルは消せた」 はずだが、まだ残っている...
さて、今回紹介するのは、もうちょっと変わった現象です。というのは、
これは、ファイルの削除を行った際に、そのファイルの削除が直ちに行われず保留されている状態です。で、どのようなときにファイルの削除が「保留」されるかというと、別のプログラム(プロセス)でまだオープンされている場合です。
「えっと、ちょっと待った。別のファイルでオープンしていると、そのファイルって消せないのじゃないの?ちょっと前にそう書いてありますよね。」 はい、そうです。別のプログラムが使用中の場合に、ファイルを削除できるかどうかは、そのファイルの開き方によるのです。
ちょっと実験
では、このようなファイルの削除が遅延される現象をみてみましょう。
1.ここでは、C++ でのプログラムを用意します。以下のプログラムを コンパイルしてopenfile.exe という名前で作成します。
----
// openfile.c
// cl /Zi openfile.c
#include <windows.h>
#include <stdio.h>
void main( int argc, char** argv )
{
HANDLE hFile ;
if( argc != 2 ){
printf( "%s <file>\n", argv[ 0 ] ) ;
return ;
}
hFile = CreateFile( argv[ 1 ], GENERIC_READ , FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL ,NULL ) ;
if( hFile == (HANDLE)-1 ){
printf( "CreateFile Error %d\n", GetLastError()) ;
return ;
}
printf( "... Hit [Enter] Key to exit ...\n" ) ;
getchar() ;
CloseHandle( hFile ) ;
}
----
2. 消すファイルを 1 つ用意しておきます。a.txt という名前をつけました。
3.このファイルを先程作成したプログラム(openfile.exe )でオープンします。これで準備完了です。
4.次にこのファイルを、別のコマンドプロンプトから削除してみましょう。
エラーメッセージも表示されず削除成功。ほんとに無くなったから確かめてみるとまだ存在しています。
5.この状態がまさに、削除が保留されている状態です。
6. では、openfile.exe を実行したコマンドプロンプトで [Enter] を押してプログラムを終了しましょう。その後で、もう一度 dir を行うと、たしかに消えていますね。ファイルを開いていたプログラムが、そのファイルを閉じる(CloseHandle)することで、保留されいたファイルが削除されることになります。
FILE_SHARE_DELETE フラグ
プログラマの方には常識かもしれないですが、ファイルを開く場合には共有モードというフラグがあります。この共有モードのなかに、実は、削除共有というのがあります。これを指定しておくと、自分がファイルを開いて使用中のときに、別のプログラムがそのファイルを削除することを許可します。あるプログラムがそのファイルを削除しても、ほんとに削除されるのは、ファイルを閉じてからです。
この 2 ~3 がファイル削除が保留されている状態です。
FILE_SHARE_DELETEなんてどのような時に利用するか、ちょっとイメージできない方もいらっしゃるかもしれません。自分のアプリで作成する重要なデータファイルを、FILE_SHARE_DELETEを 開くことはしませんよね。
ファイルのインデックスを作成するインデックスサービスや、ウィルススキャンソフトが FILE_SHARE_DELETE を利用することがあるようです。すなわち、対象のファイルにはアクセスしたいのですが、利用者がそのファイルを削除することを邪魔しない。逆にこのようなソフトウェアが、削除共有を指定しないとファイルを消そうとしもたまたまこれらのソフトウェアがファイルのチェックしていたため、消せないということが発生しますね。
Delete Pending という状態
ファイルの削除が保留されている状態と書いてきましたが、Delete Pending とちょっと短く表現します。Delete Pending の状態の特徴を書いてみます。
一旦 Delete Pendingになると、あとはファイルが閉じれらてクローズされるのみです。この時点で削除されることが確定しているので、そのファイルを新たに開く(オープン)ことはできません。オープンしようとすると、アクセス拒否というエラーで失敗します。
実は、Delete Pending になっている状態のファイルを再度 Del コマンドで削除しようとすると今度は アクセス拒否 で失敗します。このときの厳密なエラーコードを参照すると STATUS_DELETE_PENDINGになります。process explorerで見てみるとその内容がわかりますね。
一方で、Dir コマンドなどそのフォルダのディレクトリエントリの情報を参照するとまだ存在していることになります。(保留状態なので、まだ見えるということですね)さらに、Delete Pending のファイルが存在しているフォルダを削除しようとしても、まだ保留の状態なので、ファイルが存在するということになります。このため、ファイルの削除が成功したけれども、そのフォルダが削除できないとう場合も発生します。
まとめ
ファイルを削除した場合に、そのファイルの削除が直ちに行われず保留される場合があります。これは他のプログラムが、削除共有という指定ですでにそのファイルをオープンしている場合があります。この状態を Delete Pending といいます。通常別のプログラムがファイルを閉じた場合に、そのファイルが削除されます。
Delete Pending 状態のファイルをオープンすると、アクセス拒否のエラーとなります。そのファイルが完全に削除されるタイミングは、オープンしている別のプログラムに依存します。このため、ファイルの削除後、ファイルの作成に失敗するということが発生した場合には、たとえば一定期間再試行をするという考慮が必要です。
Ask Learn is an AI assistant that can answer questions, clarify concepts, and define terms using trusted Microsoft documentation.
Please sign in to use Ask Learn.
Sign in