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 操作,而不是在它之外。读取哈希时的读/写独占打开也无济于事。任何想法如何解决这个问题或其他可能导致它的原因?

谢谢。

4

1 回答 1

0

如果您改用FileSystemWatcher ,您可能会取得更大的成功。

让它确定文档何时更改,然后将其上传到服务器。

于 2013-10-09T19:58:32.853 回答