A few times over the last several months, the question has come up regarding how to determine whether a file on disk that is being edited is different that what is checked into TFS version control.  Folks looking at the PendingChange object have asked about the difference between the two hash value properties.

If you query for the pending changes in the workspace using GetPendingChanges() (or QueryPendingSets() if you don't want all of the pending changes for the workspace), you'll get an array of PendingChange objects.  The PendingChange object has quite a few properties.  Two of those properties are HashValue and UploadHashValue.  Unfortunately, the documentation on MSDN doesn't really do them justice.

The HashValue property is the right one to use if you want to determine whether a file with a pending edit has been modified.  HashValue is the MD5 hash of the content of the version against which the change was pended.  This value will be different from the MD5 hash of the file on disk, which you will need to compute yourself using MD5CryptoServiceProvider, if the file has been edited and actually changed.

I would recommend not using the UploadHashValue.  The UploadHashValue is the hash for the content last uploaded during a shelve or failed checkin operation.  This is used internally for the optimization to avoid uploading the same content repeatedly.  For example, a checkin may fail due to a conflict after all of the file contents have been uploaded.   To make subsequent attempts faster, the server keeps the content that was uploaded and the client checks to see if it needs to send the content when the checkin is attempted again.  The UploadHashValue is only really useful for this process.

Note that the GetHashCode() method is the standard .NET Object’s GetHashCode(), so it’s not relevant to the discussion of content hash values.

One caveat to computing hash values is that on systems where FIPS enforcement has been enabled, the MD5CryptoServiceProvider class cannot be used (it throws an exception), and TFS itself does not compute hashes when that is the case (the hash values are just used for upload optimization, so upload optimization is disabled).  You can learn more about FIPS enforcement at http://blogs.msdn.com/shawnfa/archive/2005/05/16/417975.aspx.  The summary of the issue is that FIPS standard only allows the SHA family of hash algorithms.

This post applies to TFS 2005 and newer.