Visual Source Safe (VSS) と Visual Studio のバインドを解除する

VSS 管理下にあるプロジェクトをVSSに接続できない環境に持っていく、自動ビルドやバッチでの静的解析の際にバインド情報が残存しているとバッチ処理に失敗するなど、VSSのバインド情報を削除する必要があります。今回は、VSSのバインド情報が、どのように構成され、どれを削除すれば良いか確認をしていきたいと思います。

  • VSSのバインド情報を確認する

VSSのバインド情報を確認するために、作成したプロジェクトをVSSで管理する前と後でDIFFを取って差異を把握します。

.slnに以下のエントリが追加されています。

GlobalSection(SourceCodeControl)

.csproj/.vbprojに以下のエントリが追加されています。

SccProjectName
SccLocalPath
SccAuxPath
SccProvider

ファイルが追加されています。

.scc
.vspscc
.vssscc

上記を削除すると、VSSからのバインドを削除できると説明できます。

■手動での削除
手動で VSS のバインドを解除するには、IDE-ツール-ソース管理からバインドの解除を実行する。

■自動での削除
関連するファイルと、ソリューションとプロジェクトの内容を修正するプログラムが以下となっています。使い方は、コマンドライン引数で、ソリューションファイルが入っているフォルダを指定して実行するとVSSのバインドが完全に解除されます。


Imports System.Text
Imports System.Xml

Public Class StartUp

Public Shared Sub Main()

Dim arg() As String = Environment.GetCommandLineArgs

If arg.Length > 1 Then

Dim targetPath As String = arg(1)

Call RemoveBind(targetPath)

End If

End Sub

Public Shared Sub RemoveBind(ByVal targetPath As String)

Dim files() As String = Nothing

files = System.IO.Directory.GetFiles(targetPath, "*.scc", IO.SearchOption.AllDirectories)

For i As Integer = 0 To files.Length - 1
System.IO.File.SetAttributes(files(i), IO.FileAttributes.Normal)
System.IO.File.Delete(files(i))
Next

files = System.IO.Directory.GetFiles(targetPath, "*.vspscc", IO.SearchOption.AllDirectories)

For i As Integer = 0 To files.Length - 1
System.IO.File.SetAttributes(files(i), IO.FileAttributes.Normal)
System.IO.File.Delete(files(i))
Next

files = System.IO.Directory.GetFiles(targetPath, "*.vssscc", IO.SearchOption.AllDirectories)

For i As Integer = 0 To files.Length - 1
System.IO.File.SetAttributes(files(i), IO.FileAttributes.Normal)
System.IO.File.Delete(files(i))
Next

files = System.IO.Directory.GetFiles(targetPath, "*.sln", IO.SearchOption.AllDirectories)

For i As Integer = 0 To files.Length - 1
RemoveSolutionBind(files(i))
Next

files = System.IO.Directory.GetFiles(targetPath, "*.csproj", IO.SearchOption.AllDirectories)

For i As Integer = 0 To files.Length - 1
RemoveProjectBind(files(i))
Next

files = System.IO.Directory.GetFiles(targetPath, "*.vbproj", IO.SearchOption.AllDirectories)

For i As Integer = 0 To files.Length - 1
RemoveProjectBind(files(i))
Next

End Sub

Public Shared Sub RemoveSolutionBind(ByVal filePath As String)

Dim lines() As String = System.IO.File.ReadAllLines(filePath)

Dim startRow As Integer = -1
Dim finishRow As Integer = -1

For i As Integer = 0 To lines.Length - 1

If lines(i).IndexOf("GlobalSection(SourceCodeControl)", StringComparison.CurrentCultureIgnoreCase) > 0 Then
startRow = i
Exit For
End If

Next

If startRow <> -1 Then

For i As Integer = startRow To lines.Length - 1

If lines(i).IndexOf("EndGlobalSection", StringComparison.CurrentCultureIgnoreCase) > 0 Then
finishRow = i
Exit For
End If

Next

End If

If (startRow <> -1) AndAlso (finishRow <> 1) Then

Dim sb As New StringBuilder

For i As Integer = 0 To lines.Length - 1

If (startRow <= i) AndAlso (i <= finishRow) Then
Continue For
End If

sb.AppendLine(lines(i))

Next

System.IO.File.SetAttributes(filePath, IO.FileAttributes.Normal)
System.IO.File.Delete(filePath)
System.IO.File.WriteAllText(filePath, sb.ToString, Encoding.UTF8)

End If

End Sub

Public Shared Sub RemoveProjectBind(ByVal filePath As String)

Dim xmlDoc As XDocument = XDocument.Load(filePath)

RecursiveSearch(xmlDoc.Root, "SccProjectName")
RecursiveSearch(xmlDoc.Root, "SccLocalPath")
RecursiveSearch(xmlDoc.Root, "SccAuxPath")
RecursiveSearch(xmlDoc.Root, "SccProvider")

System.IO.File.SetAttributes(filePath, IO.FileAttributes.Normal)
System.IO.File.Delete(filePath)
xmlDoc.Save(filePath)

End Sub

Public Shared Sub RecursiveSearch(ByVal xmlElement As XElement, ByVal targetTag As String)

If String.Compare(xmlElement.Name.LocalName, targetTag, True) = 0 Then
xmlElement.Value = String.Empty
End If

For Each item As XElement In xmlElement.Elements
RecursiveSearch(item, targetTag)
Next

End Sub

End Class

TFSの場合はこちら。
Team Foundation Server (TFS) と Visual Studio のバインドを解除する