none
ResolveAssemblyReference task

    Question

  • I believe I originally posted this question in the wrong forum (I had posted in team system but it seems to be related to msbuild - as I can duplicate the behaviour in VS)

     

    If a dependency of a referenced assembly can be found in a local folder why does MSBuild/ResolveAssemblyReference still check the GAC and then force the copylocal to false if also found there?? If copylocal is true on the referenced assembly and it's dependency file(s) are found (in a non gac location) msbuild should abide by the copylocal setting of the reference.

     

    To clarify - in the log slice below, BaseForms.dll is a file reference in the project with CopyLocal set to true and Infragistics2.Win.UltraWinTabControl.v8.1 is a dependency of BaseForms.dll. Both files are available (and according to the log, are resolved) - but since UltraWinTabControl is registered in the GAC it is not output. We depend on the built in output mechanism to get all the required files in place.

     

    What I end up with is BaseForms.dll getting output properly but not it's dependencies (if those dependencies are registered in the GAC of the machine this is built on). If those dependencies are not registered in the GAC they are ouptut along with BaseForms.dll.

     

    Is there anyway for me to change this behaviour? Has this behaviour changed in 3.5?

    Thanks for any help...

    -Mitch

     

    ------- (slice of the verbose log below - from output of the ResolveAssemblyReference task) -------

    Dependency "Infragistics2.Win.UltraWinTabControl.v8.1, Version=8.1.20081.1000, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb".
    Resolved file path is "F:\Build\TeamProjectNameRemoved\Main_Build_Test\Binaries\Debug\Infragistics2.Win.UltraWinTabControl.v8.1.dll".
    Reference found at search path location "F:\Build\TeamProjectNameRemoved\Main_Build_Test\Binaries\Debug".
    For SearchPath "F:\Build\TeamProjectNameRemoved\Main_Build_Test\Binaries\Debug".
    Considered "F:\Build\TeamProjectNameRemoved\Main_Build_Test\Binaries\Debug\Infragistics2.Win.UltraWinTabControl.v8.1.exe", but it didn't exist.
    Required by "BaseForms".
    This reference is not "CopyLocal" because it's registered in the GAC.

    -------

     

     

     

     

    Friday, March 28, 2008 3:11 PM

Answers

  • This behaior will be the same for  msbuild, vs, and team build and under the covers they all use msbuild's ResolveAssemblyReference task.

     

    If a dependency is in the gac, no matter where we resolve it from, we will set copy local to false.  This is part of a heuristic we apply to try and determine if the assembly should be copy local or not.  We are assuming that because it was installed in the gac that it will also be in the gac of any target machines and therefore copy local is not required. There are instructions at the top of the msbuild forum on how to open a bug.

     

    There is no way to change this behavior and it has not changed in .net 3.5. The only work around i can think of is to not have the assembly in the gac. 

     

    A related thread is http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3059058&SiteID=1 which i see came to the same conclusion.

    Friday, March 28, 2008 11:51 PM
    Moderator

All replies

  • This behaior will be the same for  msbuild, vs, and team build and under the covers they all use msbuild's ResolveAssemblyReference task.

     

    If a dependency is in the gac, no matter where we resolve it from, we will set copy local to false.  This is part of a heuristic we apply to try and determine if the assembly should be copy local or not.  We are assuming that because it was installed in the gac that it will also be in the gac of any target machines and therefore copy local is not required. There are instructions at the top of the msbuild forum on how to open a bug.

     

    There is no way to change this behavior and it has not changed in .net 3.5. The only work around i can think of is to not have the assembly in the gac. 

     

    A related thread is http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3059058&SiteID=1 which i see came to the same conclusion.

    Friday, March 28, 2008 11:51 PM
    Moderator
  • I ran into this exact same issue but after looking into it a bit more i seem to have found a better workaround. I can't say i understand entirely whats going on, but here goes.

    I'll start with the actual target in Microsoft.Common.Targets that calls the ResolveAssemblyReference task mentioned:

    <!--

    ============================================================

    ResolveAssemblyReferences

    Given the list of assemblies, find the closure of all assemblies that they depend on. These are

    what we need to copy to the output directory.

    [IN]

    @(Reference) - List of assembly references as fusion names.

    @(_ResolvedProjectReferencePaths) - List of project references produced by projects that this project depends on.

    The 'Private' attribute on the reference corresponds to the Copy Local flag in IDE.

    The 'Private' flag can have three possible values:

    - 'True' means the reference should be Copied Local

    - 'False' means the reference should not be Copied Local

    - [Missing] means this task will decide whether to treat this reference as CopyLocal or not.

    [OUT]

    @(ReferencePath) - Paths to resolved primary files.

    @(ReferenceDependencyPaths) - Paths to resolved dependency files.

    @(_ReferenceRelatedPaths) - Paths to .xmls and .pdbs.

    @(ReferenceSatellitePaths) - Paths to satellites.

    @(_ReferenceSerializationAssemblyPaths) - Paths to XML serialization assemblies created by sgen.

    @(_ReferenceScatterPaths) - Paths to scatter files.

    @(ReferenceCopyLocalPaths) - Paths to files that should be copied to the local directory.

    ============================================================

    -->


    based on those comments, the "There is no way to change this behavior" answer seemed incorrect to me. after testing a bit, what i have found is that when you add a reference to a project in visual studio it seems to somehow run the same heuristic that the msbuild task runs and so the property grid displays the default value for Copy Local but nothing is explicitely added to the project file. For instance, if i add a reference to a dll that is in a local lib folder and is not GAC'ed on my machine, the default value for Copy Local is true, which works great on my workstation, but after checking in and waiting for a build to run on the build server (where the same assembly is GAC'ed) the dll is not copied. This causes all kinds of deployment headaches if you do not keep your build server and your production servers GAC's matched up (which i dont want to do)

    What has happened is the "Default" or unspecified value for the two machines is different because the GAC is different. However, if i change the value of copy local from true on my machine to false, save the project file, then change back to true, and save again it adds an explicit value for copy local (<Private>):

    <Reference Include="MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=blahblahblahblah">

    <SpecificVersion>False</SpecificVersion>

    <HintPath>lib\MyAssembly.dll</HintPath>

    <Private>True</Private>

    </Reference>


    after this the build on the build server will successfully copy the assembly locally and treat it as a private reference.

    Hope this helps some people out, I know I didn't like your answer Chris (No offense to you :) and was glad to find an easier workaround.
    • Edited by steve_baker Wednesday, August 20, 2008 7:19 PM clarification
    • Proposed as answer by sved Monday, August 25, 2008 1:29 PM
    Wednesday, August 20, 2008 7:16 PM