Thursday, July 29, 2010

Hint Paths and The System.Reflection.CustomAttributeFormatException

With in my organization we use multiple branches and a centralized bin directory within each branch. All of our references are file based and not version specific. There are arguments for why this works or why it should not be done but this implementation has worked for our current architecture.
Now lets say one day you come to work and start in a new branch and find the System.Reflection.CustomAttributeFormatException after comping a new. And you begin asking your self how did I get here and what have I done this is not my beautiful house this is not my large automobile. After answering those questions and more colleague and I found someone added a rouge reference to a DLL in another branch. Initially this involved some meticulous evaluation of each project and its references.

I offer you a magnet for your needle in the hay stack the code below can be pasted in to a visual studio macro to scan each project and make sure it is referencing the correct path. (Your paths may vary)
Imports System
Imports System.Diagnostics
Imports EnvDTE
Imports VSLangProj
Imports System.Collections

Public Module ReferenceScanner
    Private Path As String
    Private ExcludedPaths As ArrayList
    Private Sub Scan(ByVal project As Project)
        If Not project.ProjectItems Is Nothing Then
            If TypeOf (project.Object) Is VSProject Then
                Dim visualStudioProject As VSProject = DirectCast(project.Object, VSProject)
                For Each reference As Reference In visualStudioProject.References
                    Dim referencePath As String = reference.Path
                    Dim exclude As Boolean = False
                    For Each excludePath As String In ExcludedPaths
                        exclude = referencePath.StartsWith(excludePath)
                        If exclude Then Exit For
                    Next
                    If Not exclude And Not String.IsNullOrEmpty(reference.Path) Then
                        If Not reference.Path.StartsWith(Path) Then
                            Debug.Write(project.Name)
                            Debug.Write(" ")
                            Debug.WriteLine(reference.Path)
                        End If

                    End If
                Next
            End If
            For Each childProjectItem As ProjectItem In project.ProjectItems
                If Not childProjectItem.SubProject Is Nothing Then Scan(childProjectItem.SubProject)
            Next
        End If
    End Sub
    Public Sub CheckSolutionHintPaths()
        If ExcludedPaths Is Nothing Then
            ExcludedPaths = New ArrayList()
            ExcludedPaths.Add("C:\Windows\Microsoft.NET\Framework\")
            ExcludedPaths.Add("C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\")
            ExcludedPaths.Add("D:\Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies\")
        End If

        Path = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(DTE.Solution.FullName), "bin")
        For Each project As Project In DTE.Solution.Projects
            Scan(project)
        Next
    End Sub
End Module

*Dont forget to replace the referenced dll after you have corrected your references