7

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 の検索インデクサーがファイルをいじっているため、アプリケーションがファイルを作成して名前を変更できると期待できない場合、それは完全にクレイジーです。再試行し続ける必要がありますか?ユーザーに怒鳴ります (これは非常に望ましくありません)。何か他のことをしますか?

4

4 に答える 4

4

Process Monitor (編集: 以前は FileMon として知られていたアーティスト)を使用して、どのアプリケーションが正確に邪魔をしているかを確認することをお勧めします。マシンで行われたファイル システム呼び出しのトレース全体を表示できます。

(編集:アプリケーションの変更について@moochaに感謝します)

于 2008-09-30T15:21:01.573 に答える
1

ウイルス対策または Windows インデックス処理が同時にファイルをいじっていると思います。ウイルス対策なしで同じテストを実行できますか。次に、一時ファイルが Windows Search によってインデックス付けされていない場所に作成されていることを確認して、もう一度実行しますか?

于 2008-09-30T15:13:16.960 に答える
0

これは通常、別の何かが問題のファイルに対して開いているハンドルを持っていることを意味します。おそらく、アクティブなウイルス スキャナーが実行されていますか? Sysinternalsサイトから Process Monitor などを実行してみましたか? すべてのファイル操作をフィルタリングして、フードの下で何が起こっているかをよりよく把握する必要があります。

于 2008-09-30T15:18:09.473 に答える
0

Windows にはアプリケーション ファイルを保存するための特別な場所があり、インデックスは作成されていないと思います (少なくともデフォルトでは)。Vista では、パスは次のとおりです。

C:\Users\ユーザー名\AppData

アプリケーションに適している場合は、そこにファイルを配置することをお勧めします。

于 2008-10-01T20:56:48.467 に答える