1

.NET 3.5 ClickOnce アプリケーションがあります。サーバーに保存されている Word ドキュメントのリストを含む単純なグリッドがあります。ボタンをクリックすると、アプリケーションは選択したドキュメントをサーバーから (WCF 経由で) ダウンロードし、定義された一時フォルダーに配置します。その直後に、次の関数を使用してドキュメントのハッシュが計算されます。

Public Shared Function HashFile(ByVal file As String) As String
  Using reader As New System.IO.FileStream(file, IO.FileMode.Open, IO.FileAccess.Read)
    Using provider As New System.Security.Cryptography.MD5CryptoServiceProvider
      Dim hash() As Byte = provider.ComputeHash(reader)

      Dim sb As New System.Text.StringBuilder(hash.Length * 2)

      For i As Integer = 0 To hash.Length - 1
        sb.Append(hash(i).ToString("X2"))
      Next

      Return sb.ToString().ToLower
    End Using
  End Using
End Function

Word 文書が開かれます。

Private Shared Function OpenDocument(ByVal path As String) As Boolean
  Try
    Dim process As New Process
    process.StartInfo.FileName = path
    process.StartInfo.UseShellExecute = True
    process.StartInfo.ErrorDialog = True
    process.Start()
    Return True
  Catch ex As Exception
    Return False
  End Try
End Function

アプリケーションで開いているすべてのドキュメントのリストがあります。ドキュメントを開いた直後に、そのドキュメントに関する情報がこのリストに追加されます。これまでのところ、かなり単純です。アプリケーションには、1000 ミリ秒ごとにチェックするタイマーがあり、開いているドキュメントのいずれかが既に閉じられているかどうかを確認します。Word からそのような情報を取得する簡単な方法がないため、次のトリックが使用されます。

Public Shared Function IsLockedFile(ByVal path As String) As Boolean
  Dim isLocked As Boolean = True

  Try
    Using fs As FileStream = File.Open(path, FileMode.Open, FileAccess.Write)
      isLocked = False
    End Using
  Catch ex As Exception
  End Try

  Return isLocked
End Function

アプリケーションが書き込みアクセスでファイルを正常に開いた場合は、ドキュメントが閉じられたことを意味します (Word によってロックされなくなりました)。その直後に、上記と同じ関数を使用して、ファイルの MD5 ハッシュが再度計算されます。古いハッシュが新しいハッシュと等しい場合、ユーザーがドキュメントに変更を加えていないことを意味します。ハッシュが異なる場合、ドキュメントはサーバーにアップロードされます。これは、プロセス全体の簡略化された説明です。

それはかなりうまくいっています。ただし、顧客は、ドキュメントへの変更が時々失われると報告しました。長い間、私たちはその理由を発見しました。アプリケーションが (閉じた) ドキュメントのハッシュを計算するとき、古いハッシュを返すことがあります。ファイルの古いバージョンをまだ読んでいるようです。バグの発生は非常に不確定です。たいていはうまくいっています。たとえば、50回は正しい(異なる)ハッシュを取得しますが、3回続けて間違った(古い)ハッシュを取得します。

開発者環境 (VMware で仮想化された Windows Server 2008) ではバグをシミュレートできず、ホスト (Windows 7 64 ビット、ウイルス対策はオフ) でのみシミュレートできました。

すべてのディスク操作が確実にフラッシュされるように、ハッシュが再計算される前に遅延を入れようとさえしました。しかし、2秒経ってもまだ間違っていました。古いハッシュです。足りないかもしれませんが、どれくらい待てばいいですか?

私がグーグルで調べたところ、.NETアプリケーションで作成されたIO操作をフラッシュする可能性はあります.NETアプリケーションの外部ではありません。ハッシュを読み取るときに読み取り/書き込み用に排他的に開くことも役に立ちませんでした。これを解決する方法、または他に何が原因である可能性がありますか?

ありがとう。

4

1 に答える 1

0

代わりにFileSystemWatcherを使用すると、おそらくより多くの成功を収めることができます。

ドキュメントがいつ変更されたかを判断し、サーバーにアップロードします。

于 2013-10-09T19:58:32.853 に答える