Vista で、ファイルへの書き込み、ファイルのクローズ、目的の場所への移動がランダムに失敗することに気付きました。ERROR_ACCESS_DENIED
具体的には、明確な理由もなくMoveFileEx() が返されます。これは、少なくとも Vista SP1 (32 ビット) で発生します。XP SP3 では発生しません。
まったく同じ問題についてインターネットでこのスレッドを見つけましたが、実際の解決策はありません。これまでのところ、エラーは Vista の検索インデクサーが原因のようです。以下を参照してください。
そこに示されているコード例は、問題を再現するのに十分です。ここにも貼り付けています:
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
bool test() {
unsigned char buf[] = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99
};
HANDLE h;
DWORD nbytes;
LPCTSTR fn_tmp = "aaa";
LPCTSTR fn = "bbb";
h = CreateFile(fn_tmp, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_ALWAYS, 0, 0);
if (h == INVALID_HANDLE_VALUE) return 0;
if (!WriteFile(h, buf, sizeof buf, &nbytes, 0)) goto error;
if (!FlushFileBuffers(h)) goto error;
if (!CloseHandle(h)) goto error;
if (!MoveFileEx(fn_tmp, fn, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH)) {
printf("error=%d\n", GetLastError());
return 0;
}
return 1;
error:
CloseHandle(h);
return 0;
}
int main(int argc, char** argv) {
unsigned int i;
for (i = 0;; ++i) {
printf("*%u\n", i);
if (!test()) return 1;
}
return 0;
}
これを Visual Studio でコンソール アプリとしてビルドします。正しい動作は、テスト番号を出力する無限ループです。Vista SP1 では、プログラムは乱数の繰り返しの後 (通常は 100 回の繰り返しが行われる前) に終了します。
これは、Windows XP SP2 では発生しません。ウイルス対策はまったく実行されていません。その他の奇妙なバックグラウンド プロセスはありません (マシンはほとんどバニラ OS インストール + Visual Studio です)。
編集:Process Monitor(@sixlettervariablesに感謝)を介してさらに掘り下げると、特に悪いことは何もわかりません。テストの繰り返しごとに 176 のディスク操作が行われ、その大部分は SearchProtocolHost.exe (検索インデクサー) からのものです。検索インデックス サービスが停止している場合、エラーは発生しないので、原因のようです。
失敗時 (アプリが を取得したときERROR_ACCESS_DENIED
)、SearchProtocolHost.exe は、読み取り/書き込み/削除共有モードで開いている detin ファイル (bbb) への 2 つの CreateFile を持っているので、問題ないはずです。オープンの 1 つに日和見ロック ( ) が続いていますFSCTL_REQUEST_FILTER_OPLOCK
。それが原因でしょうか?
FILE_ATTRIBUTE_TEMPORARY
とにかく、ファイルにFILE_ATTRIBUTE_NOT_CONTENT_INDEXED
フラグを設定することで問題を回避できることがわかりました。それだけで十分に見えFILE_ATTRIBUTE_NOT_CONTENT_INDEXED
ますが、ファイルを一時としてマークすると、検索インデクサーによるディスク操作も大幅に削減されます。
しかし、これは本当の解決策ではありません。つまり、一部の Vista の検索インデクサーがファイルをいじっているため、アプリケーションがファイルを作成して名前を変更できると期待できない場合、それは完全にクレイジーです。再試行し続ける必要がありますか?ユーザーに怒鳴ります (これは非常に望ましくありません)。何か他のことをしますか?