Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I'm convinced that this is a new bug/feature in VS 2010 because I have an add-in that started showing similar behaviour a couple of days ago after I migrated it from VS 2008... Basically, if you add a reference to anything within VS's assembly search path, it will be added without the path hint.</p> <p>I managed to find other VS add-ins that solved this problem (Power Tools, NuGet among others), and they all seem to use MsBuild. I don't know if MsBuild raises resource usage much - I myself haven't seen too big a slowdown, possibly because References.Add() is very slow to start with. But note that to get an instance of MsBuild project, a method called "GetLoadedProjects" is used, which may mean that it works on data already present in memory.</p> <p>Below is the code I used to fix my add-in, it's a simplified version of what I found on the net... Essentially, the idea is to add the reference as usual, then use MsBuild to set the path hint. Setting the hint is a trivial operation, but finding the instance of the MsBuild project item to add the hint to is incredibly complicated. I tried to hack an alternative using MsBuild only, but ran into other problems... This one seems to work. </p> <p>One other thing that may be of interest here: the code contains a sort of optimization - it doesn't add the hint to the new reference if the reference's path is equal to the path we wanted to add. This is good enough for the case in question, and detects correctly when VS decides to use the dll from the output folder instead of what we told it. But when I tried to add a reference to the dll already in the output folder (I use a single output folder for many related projects), the add-in didn't set the hint path and project seemed to switch to using some other dll in the path (in my case the one from its PublicAssemblies folder)... So it may be useful to remove that "if (!newRef.Path.Equals(..." line altogether and add the hint always. I'm still investigating this case, so any additional - uhm, hints or improvements of the code are welcome.</p> <pre><code>string newFileName = "the path to your.dll"; VSLangProj.VSProject containingProject = yourProject; VSLangProj.Reference newRef; newRef = containingProject.References.Add(newFileName); if (!newRef.Path.Equals(newFileName, StringComparison.OrdinalIgnoreCase)) { Microsoft.Build.Evaluation.Project msBuildProj = Microsoft.Build.Evaluation.ProjectCollection.GlobalProjectCollection.GetLoadedProjects(containingProject.Project.FullName).First(); Microsoft.Build.Evaluation.ProjectItem msBuildRef = null; AssemblyName newFileAssemblyName = AssemblyName.GetAssemblyName(newFileName); foreach(var item in msBuildProj.GetItems("Reference")) { AssemblyName refAssemblyName = null; try { refAssemblyName = new AssemblyName(item.EvaluatedInclude); } catch {} if (refAssemblyName != null) { var refToken = refAssemblyName.GetPublicKeyToken(); var newToken = newFileAssemblyName.GetPublicKeyToken(); if ( refAssemblyName.Name.Equals(newFileAssemblyName.Name, StringComparison.OrdinalIgnoreCase) &amp;&amp; ((refAssemblyName.Version != null &amp;&amp; refAssemblyName.Version.Equals(newFileAssemblyName.Version)) || (refAssemblyName.Version == null &amp;&amp; newFileAssemblyName.Version == null)) &amp;&amp; (refAssemblyName.CultureInfo != null &amp;&amp; (refAssemblyName.CultureInfo.Equals(newFileAssemblyName.CultureInfo)) || (refAssemblyName.CultureInfo == null &amp;&amp; newFileAssemblyName.CultureInfo == null)) &amp;&amp; ((refToken != null &amp;&amp; newToken != null &amp;&amp; Enumerable.SequenceEqual(refToken, newToken)) || (refToken == null &amp;&amp; newToken == null)) ) { msBuildRef = item; break; } } } if (msBuildRef != null) { Uri newFileUri = new Uri(newFileName); Uri projectUri = new Uri(Path.GetDirectoryName(containingProject.Project.FullName).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar); Uri relativeUri = projectUri.MakeRelativeUri(newFileUri); msBuildRef.SetMetadataValue("HintPath", relativeUri.ToString()); } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload