How to find wrong assembly dependencies via PowerShell

Sometimes when you work with .NET assemblies, you can see a message telling you something about dependencies and referencies. Something like this:

Error when binding assemblies

It probably means that some assemblies reference an assembly that is not contained in the /bin folder. How can it happen? Have project A, B, C. A is basic project, B depends on A, C depends on A,B. Compile A, then compile B. Recompile A and compile C. C will reference fresh assemblies from A, but it will reference old assemblies from A through the B project as well. You can either go for Reflector and check manually the references or take PowerShell and do it in a much funier way.

The PowerShell approach

I won't waste your time, here is the script:

$references=Get-ChildItem c:\temp\bin -rec | % {
    $loaded  = [reflection.assembly]::LoadFile($_.FullName)
    $name    =$loaded.ManifestModule
    $loaded.GetReferencedAssemblies() | % {
        $toAdd='' | select Who,FullName,Name,Version
        $toAdd.Who,$toAdd.FullName,$toAdd.Name,$toAdd.Version = `
            $loaded,$_.FullName,$_.Name,$_.Version
        $toAdd
    }
}

$references | 
    Group-Object FullName,Version | 
    Select-Object -expand Name | 
    Sort-Object

Just change the directory name with the assemblies and run it. After I did it, I saw this output:

antlr.runtime, Version=2.7.6.2, Culture=neutral, P...
Common.Logging, Version=1.2.0.0, Culture=neutral, ...
...
Gmc.System, Version=0.2.3491.12201, Culture=neutra...
Gmc.System, Version=0.2.3491.12554, Culture=neutra...
...
System.Xml, Version=1.0.3300.0, Culture=neutral, P...
System.Xml, Version=1.0.5000.0, Culture=neutral, P...
System.Xml, Version=2.0.0.0, Culture=neutral, Publ...
System.Xml.Linq, Version=3.5.0.0, Culture=neutral,...

The key problem are the two rows about Gmc.System – two different versions are used. Now, just go and look for the referencing assemblies (some names were 'obfuscated'):

[3] $references | Where-Object { $_.Name -eq 'Gmc.System' } | Select-Object Who,Version

Who                                                Version
---                                                -------
Gmc.Dam.D.Api, Version=1.0.0.0, Culture=neutral,.. 0.2.3491.12554
Gmc.Dam.D.Fcd, Version=1.0.0.0, Culture=neutral... 0.2.3491.12554
Gmc.Dam.Z, Version=1.0.0.0, Culture=neutral, Pu... 0.2.3491.12554
Gmc.Dam.Web, Version=1.0.0.0, Culture=neutral, ... 0.2.3491.12554
Gmc.Dam.Web, Version=1.0.0.0, Culture=neutral, ... 0.2.3491.12201
Gmc.Ginger.A, Version=0.1.3491.12219, Culture=n... 0.2.3491.12201
Gmc.Ginger.D.Api, Version=0.1.3491.12222, Cultu... 0.2.3491.12201
Gmc.Ginger.D.Facade, Version=0.1.3491.12223, Cu... 0.2.3491.12201
Gmc.Ginger.Z, Version=0.1.3491.12217, Culture=n... 0.2.3491.12201
Gmc.Ginger.Web.Mvc, Version=0.1.3491.12232, Cul... 0.2.3491.12201

It's quite obvious that assemblies beginning with Gmc.Ginger use the old version. Problem solved.

Meta: 2009-07-23, Pepa