【问题标题】:Still getting old file content in .NET仍然在 .NET 中获取旧文件内容
【发布时间】:2013-10-17 08:34:09
【问题描述】:

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

谢谢。

【问题讨论】:

  • 对不起.. 我不认为你会得到很多答案。 SO 是精打细算的,因此提出这样的难题需要人们付出太多努力才能尝试和帮助。我尝试了一些,最后不得不自己回答。
  • 正在尝试重新创建WebDAV
  • Mithlon 非常适合点磨。通常有帮助的一件事是,如果您获得足够的声望,您可以设置赏金(牺牲自己的代表作为赏金),这会引起关注。
  • 我根本不买“旧文件内容”的解释。用户用另一个名称保存文档太简单了。在 Word 中很容易做到,您永远不会看到它,并且用户不知道为什么该更改没有被采纳。

标签: .net file io


【解决方案1】:

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

判断文档何时发生变化,然后上传到服务器。

【讨论】:

  • 我看不到 FileSystemWatcher 将如何帮助您解决锁定问题等。如果文件被写入由一个奇怪的驱动程序/操作系统管理的驱动器上,而该驱动器没有正确报告锁定您'仍然会有同样的问题。 FSW 将帮助您避免轮询,尽管当有数千个文件被监视时,它确实会丢失事件,这通常会迫使您将其与较慢的轮询相结合。
  • 也许我错过了一些东西。我设想这个应用程序可以跟踪用户本地 PC 上的文档何时发生变化。如果检测到更改,则将其发送回服务器。您不能使用观察程序来确定哪些文件被更改了吗?我认为锁定不是问题,因为文件在修改/保存后不应再被锁定。
  • 您可能正在做某事。然而,我读他的方式是他知道文件已经改变,所以我认为从 FSW 获得额外的确认不会让它变得更加真实,它确实已经改变了。尝试你的建议当然不会有什么坏处。 PS:不确定文件是本地的。
  • 谢谢大家。是的,我知道文件何时更改,或者至少我很确定当 IsLockedFile 返回 false 时,文件将从 Word 中释放(并保存)。正如我所写,我什至在此之后延迟了一些时间,以确保将更改刷新到磁盘。我可以尝试使用 FSW,但我现在不确定,如果它通知我更改也意味着文件是从 Word 中“发布”的(它是专门打开的)。是的,文件是本地的。
猜你喜欢
  • 2011-02-14
  • 2016-02-19
  • 2020-12-01
  • 2011-01-23
  • 2016-05-19
  • 2015-10-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-14
相关资源
最近更新 更多