NASへの保存

Category: visual studio vc_ja

Question

Brillia on Wed, 10 Sep 2014 07:42:12


お世話になります。

MFC(VS2008)で開発したアプリケーションで、
ドキュメントをファイル保存するのにシリアライズを使用しています。
保存先が、NASの場合、たまにですが、保存に失敗するようです。
※ファイルサイズが3MBを超えると起こるそうですが、それもたまにらしいです。

ただ再現性がないため、原因が突き止められません。

NASの問題のような気がしますが、NAS側も問題ないようなこといわれました。

なにか原因を突き止める方法があれば教えてください。

Replies

とっちゃん on Wed, 10 Sep 2014 08:50:49


再現性はなくてもエラーは発生するのでしょうか?

そうであれば、エラーの詳細を表示する方法を検討してみてはいかがでしょう?

MFCのデフォルト実装に従っているのであれば、ファイルの読み込みや保存の時にエラーが発生すれば CDocument::ReportSaveLoadException() が呼ばれます。

こちらは、仮想関数ですので、自身のドキュメントクラスでオーバーライドして、詳細エラーを表示するなどで原因を絞り込むことができるかもしれません。

Brillia on Wed, 10 Sep 2014 10:06:37


ご返事ありがとうございます。

ちょっと状況が変わってきました。

初めは、エラーは発生せずに保存処理が終了して、次の日にファイルを開こうとしたら
ファイルがなくなっていたといわれていたのですが、

実際は、「xxxxファイルへのアクセスは拒否されました。」とメッセージが表示されていたようです。

めったにこのようなメッセージが表示が出るわけでもないし、
警告ダイアログには、OKボタンしかないので、保存はされているはずだと思っていたようです。

現在把握した状況ですが、

・NASを使用してファイルを保存している
・NASへの保存に、ネットワークドライブを使用している
・VISTAを使用している
・NASからファイルが消失するときは、上記の警告メッセージが表示されていた

ここから推測すると、

ネットワークドライブが切断されていたのではないのかと疑っているのですが、
※一定時間アクセスしなかったら、切断されるという話を聞いたことが。。。

アプリケーションの保存処理の仕様は、

1.上書き対象ファイルを、ローカルPCにバックアップ
2.上書き対象ファイルを削除
3.シリアライズ開始
4.保存に失敗したとき、バックアップしたファイルを、上書き対象ファイルがあった場所にリストア

としています。

ファイルが削除された原因は、「2」だと思うのですが、保存に失敗した場合でも、
リストア処理されるはずなのですが。。。

ネットワークドライブが切断されていたとしたら、「2」も実行に失敗されるはずだし。。。

再現性がないので、
CDocument::ReportSaveLoadException() を実装考えるべきなのでしょうが、
※実装は行う予定です。ありがとうございます。

上記の状況から、なにか推測できる原因があれば、教えてください。

とっちゃん on Thu, 11 Sep 2014 02:24:32


「アクセスが拒否されました」なので、おそらく AFX_IDP_FILE_ACCESS_DENIED の文字列をセットしていると思われます。

手元にVS2008がないので2013のリソースを見ているので確実ではありませんが、この値をセットしているとすると、例外は CFileException::accessDenied だと思われます。

ファイルがNAS側のファイルなのであれば、保存処理の時に別のマシンなどからのアクセスが入っていなかったかなどもチェックしたほうがいいかもしれません。

複数のユーザーで同じファイルを操作する場合、一方の操作が原因でアクセス違反が出ることはよくあるエラーの一つです。

Brillia on Fri, 12 Sep 2014 06:07:08


ご返事ありがとうございます。

1.上書き対象ファイルを、ローカルPCにバックアップ
2.上書き対象ファイルを削除
3.保存処理開始(ファイルオープン、シリアライズ
4.保存に失敗したとき、バックアップしたファイルを、上書き対象ファイルがあった場所にリストア

上記はアプリケーションの保存処理の仕様なのですが、

「2」の処理が、実は終わっていなくて、「3」の処理が開始され、
「アクセスが拒否されました」ということが、ありえますか?

いろんなパターンを試したのですが、MFCランタイムは、「AFX_IDP_FILE_ACCESS_DENIED
以外のエラーは返してくれるのですが、AFX_IDP_FILE_ACCESS_DENIED」が使用されるパターンに
遭遇しません。

NAS情報として、「Windows Storage Server 2003」を使用しているようです。

とっちゃん on Fri, 12 Sep 2014 06:57:22


MFCの例外クラスの中で、AFX_IDP_FILE_ACCESS_DENIED が使われる例外は、CFileException::accessDenied が該当します。

ただ、この例外が発生する可能性はありすぎて、ソースコードレビューしても判断できるかどうかは分かりません。

「2」の処理が、実は終わっていなくて、「3」の処理が開始され、
>「アクセスが拒否されました」ということが、ありえますか?

可能性としてないとは言えません。

このエラーに遭遇しないとありますが、遭遇しないのは、再現性がないからではありませんか?

再現性はないものの、時折発生するのですよね?

その時折発生するときに「ユーザーが何をしていたか?」がおそらく原因究明のために調査すべき内容だと思います。

例えば、

同じ時間帯に別のマシンで同じプログラムを動かしていたとか。。。

エクスプローラで該当フォルダを参照していたとか。。。

エクスプローラじゃなくても該当フォルダを参照するプログラムがあればそれが影響している可能性もあります。

他に発生個所の可能性としては、3の処理で失敗した場合に4に行くとありますが、3でエラーメッセージを表示せず、4を行っているなどはありませんか?

その4で該当エラーが発生という可能性も考えられます。

もちろんもっと手前の1でエラーが出ているという可能性もありますが。。。

Jitta on Sat, 13 Sep 2014 23:37:28


 これって、コード上の発生場所は特定されているんですか?すでに指摘がありますが、「共有不可」で開いているファイルを開こうとすると、Access Denied になります。「いろんなパターン」とは、実際にどのようなパターンなのでしょうか。ここで「いろんなパターン」は、あなたが想像できるパターンですよね。想像できないことをやるのがユーザーなので、あなたがやったパターンは列挙する方が、「こんなパターンもあるよ」という情報を受けやすいでしょう。

 それと、どのように実現しているのか分かりませんが、どうも open-close を繰り返しているように見えます。たとえば、CreateFile で dwDesiredAccess を GENERIC_READ | GENERIC_WRITE、dwShareMode を 0 にして開き、もう一つファイルを開いてコピー、SetFilePointer でファイル ポインターを先頭に戻して SetEndOfFile で実質削除、そして保存、というようにやれば、途中でファイルを手放すことで発生するであろう問題は避けられると思うのですけど。