I have a script that searches through a release branch of our software, and detects the difference from the branch to the common dev dir (diff on all files)
so i get the file... try to figure out the pinned version to diff it with the one in the other directory. There the problem starts. I cant figure out the pinned version. There is a MSDN KB article, but they say that the Action of the version starts with "Pinned" or "Unpinned".. this does not fit to our situation here. Those texts never appear in the Version.Action .
Can someone help
VSS 6.0d (Build 31222)

Get pinned version of VSS through automation
Timdog68
You can find if an item is pinned and the version to which is pinned at like this:
Dim db As New SourceSafeTypeLib.VSSDatabase
db.Open("\\server\vss_database_share\", "alinc")
Dim x As SourceSafeTypeLib.VSSItem
x = db.VSSItem("$/item.txt")
MsgBox("IsPinned = " + x.IsPinned.ToString)
If (x.IsPinned) Then
For Each x1 As SourceSafeTypeLib.VSSItem In x.Links
If (x1.Parent.Spec = x.Parent.Spec) Then
MsgBox("Pinned in " + x.Parent.Spec + " at version " + x1.VersionNumber.ToString)
End If
Next
End If
With VSS 6.0d where you don't have the IsPinned property, you can still use the Links collection to find out the version number to which an item is pinned, but you won't be able to distinguish between an item that's unpinned and an item that's pinned at a last databse version.
Alin
Barry Lewis
This is a marvelous hack of VSS data files, but is WRONG.
Please do not use such code!
The function's intent is to scan the files in data folder, starting from the root, like this
$/Folder1
$/Folder1/Folder2
$/Folder1/Folder2/Folder3/Item
until it locates the physical file for the item ($/Folder1/Folder2/Folder3/Item in this case).
Then, it gets 2 bytes of this file which it ANDs between them, and conclude that is the pinned version
Here are a couple of issues with the function I can see at a first look:
a) The test "InStr(1, Mid(line, 15, Len(spath(i))), spath(i), vbTextCompare)" will incorrectly match longer entryies that have same beginning characters as the searched folder. For instance it will match "$/Folder12" with the searched "Folder1"
b) Folder with long file names (longer than 32 charactes) have the names stored in names.dat, not in the data files.The attempt to locate the physical file of a folder named "$/A very long name for this folder that have more than 31 characters/" will incorrectly match the folder with "$/A very long name for this folder too/", producing incorrect results.
c) When a file or folder is deleted in a database, it is not actually deleted from the parent file, so you may actually have 2 entries in $/Folder1's physical file for 2 children named 'Folder2' (one of them deleted and one not). The function is incorrectly picking the deleted entry, giving incorrect results.
d) The function may gives incorrect results on a database with orphanes files. It may be possible that both physical.a and physical.b files exists on disk (one orphan) and your function may pick the wrong one.
e) The function concludes (lPinnedVersion = byte53 & byte54), which can only have max. 256 values. You surely can pin versions of files bigger than 256! What you probably wanted there was (256 * byte54 + byte53)...
I'd strongly advise against using hack code like this, as it's likely you don't have a full understanding of proprietary VSS database structures, and will likely write code that apparently works but will eventually yield incorrect results. And, if the database structure will change in the future, your code will break again.
Btw, to identify the physical file name of an item you could have used easier the "ss.exe physical" command line (in VSS 6.0), or the VssItem.Physical property in VSS2005.
Alin
Jerry West
someone was sleeping from the ms vss team
Danny Yoder
Stoober
Public Function PinnedVersionNumber(oVSSItem As VSSItem) As Long
Dim fso As FileSystemObject
Dim ts As TextStream
Dim line As String
Dim sDataFileNameA As String
Dim sDataFileNameB As String
Dim spath() As String
Dim i As Long
Dim sletter As String
Dim sKey As String
Dim sLogFileName As String
Dim lPinnedVersion As Long
Dim ch1 As Byte
Dim ch2 As Byte
Dim fFound As Boolean
Dim lRecordOffset As Long
On Error GoTo Error_Handler
' set Pinned Version = -99 as default;
lPinnedVersion = -99
'Set the default start of the tree. This is the "$" file;
sletter = "a"
sKey = "aaaaaaaa"
'set the path for our VSSItem;
spath = Split(Replace(oVSSItem.Spec, " ", "_", , , vbTextCompare),"/")
'Parse through each data file to move through the VSS Tree;
For i = 1 To UBound(spath)
'Data files may end in .a or .b;
'Make sure we are pointing to the current VSSDatabase;
sDataFileNameA = "SouceSafe_Database\Data\" & sletter & "\" & sKey & ".a"
sDataFileNameB = "SouceSafe_Database\Data\" & sletter & "\" & sKey & ".b"
Set fso = New FileSystemObject
'Find out if our data file ends in .a or .b;
If fso.FileExists(sDataFileNameA) Then
Set ts = fso.OpenTextFile(sDataFileNameA, ForReading)
sLogFileName = sDataFileNameA
Else
Set ts = fso.OpenTextFile(sDataFileNameB, ForReading)
sLogFileName = sDataFileNameB
End If
fFound = False
lRecordOffset = -1 'Reset the number of records so we have a count of the "last" file
Do While Not ts.AtEndOfStream
line = ts.Read(64) 'Each record is 64 bytes
lRecordOffset = lRecordOffset + 1 'Count the number of records
' Debug.Print Mid(line, 15, Len(spath(i)));
If InStr(1, Mid(line, 15, Len(spath(i))), spath(i), vbTextCompare) Then 'Look at the the "Child" record;
' Debug.Print line;
'Set the keys for the next file;
sKey = Mid(line, 55, 8)
sletter = Mid(line, 55, 1)
fFound = True
Exit Do
End If
Loop
ts.Close
'Check to see if our parsing worked;
If Not fFound Then
' MsgBox "Parsing Failed";
GoTo Exit_Routine
End If
Next
'Open the Data file and look at specific bytes;
'We wants bytes 54 and 53 for our record.;
If fso.FileExists(sLogFileName) Then
Open sLogFileName For Binary Access Read Lock Read As #1
Get 1, (lRecordOffset * 64) + 54, ch1 'We wants bytes 54 and 53 for our record.;
Get 1, (lRecordOffset * 64) + 53, ch2
Close #1
lPinnedVersion = ch1 & ch2
End If
Exit_Routine:
PinnedVersionNumber = lPinnedVersion
Exit Function
Error_Handler:
Call Err.Raise(Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext)
End Function
You may have to modify this code. Another great ref to all of this is
http://www.ezds.com/html/ssi_log_data_files.html That is where I got some of the information that helped me write the above. Also thanks goes to Dave Goodall. Hope this will help everyone
nigeldude
Public Function PinnedVersionNumber(oVSSItem As VSSItem) As Long
Dim oVSSTestItem As VSSItem
Dim oVSSVersion As VSSVersion
On Error GoTo Error_Handler
PinnedVersionNumber = -99
Set oVSSTestItem = PinnedItem(oVSSItem)
Call oVSSTestItem.Checkout(, , VSSFlags.VSSFLAG_GETNO)
Call oVSSTestItem.UndoCheckout(, VSSFlags.VSSFLAG_DELNOREPLACE)
Exit_Routine:
Exit Function
Error_Handler:
Select Case Err.Number
Case PineedToSpecificVersionError '<file> is pinned to a specific version
Err.Clear
PinnedVersionNumber = oVSSTestItem.VersionNumber
Exit Function
Case FileCheckedOutError '< > is currently checked out by < >
Err.Clear
Exit Function
Case Else
Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext
End Select
End Function
As you can see and I'm sure you've found there is no "pinned" property that is documented in the Object Model. However if you try to check a file out that is pinned you should recieve an error that "You may not check out a file that is pinned to a specific version". The wording might not be the exact same. But based on the error you recieve you may be able to tell if the file is pinned. If you get the pinned file error then when you try to get the VersionNumber on that file it should be the pinned version. However if you are able to check the file out then you will have to undo a checkout and you will know that the file is not pinned.
If anyone finds a better way to find out if a file is pinned or what version it is pinned at please let me know.
Steve H
mbothmer
It would also be nice if this functionality was built into VSS 6. Then we wouldn’t need to write “HACK” code to find out simple information. < xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />