views:

102

answers:

2

I wrote a MsBuild Task : MyTask. In my solution, I have the Task project and others projects. MyTask references a project (say ProjA) which references third assemblies, say (dep1 and dep2).

The projects all builds well and I have the outputs in one directory (Compil). In this directory i have all the dll's I want : MyTask.dll, ProjA.dll, dep1.dll, dep2.dll and others.

In my MsBuild file i include the custom task assembly with :

<UsingTask AssemblyFile="..\Compil\MyTask.dll" TaskName="CreateSitesCss" />

Then I call a task of the MyTask assembly. The call is well executed but MsBuild complains about not finding the dep1 and dep2 assemblies (although they are in the same directory) :

error : Could not load file or assembly 'dep1, Version=2.0.0.0, Culture=neutral,PublicKey Token=9109c11469ae1bc7' or one of its dependencies. The system cannot find the file specified.

I can solve this problem by copying dep1.dll and dep2.dll to c:\windows\microsoft .net\framework\v4.0\ but I don't want to do this because it triggers problems when building other projects (won't copy the dep1.dll and dep2.dll to the output directory...).

Has anybody the same problem, or better, a solution?


EDIT

Here is the output of Fusion Log Viewer

*** Assembly Binder Log Entry  (19/10/2010 @ 17:52:45) ***

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.

Assembly manager loaded from:  C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable  c:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
--- A detailed error log follows. 

=== Pre-bind state information ===
LOG: User = HEADOFFICE\bbaumann
LOG: DisplayName = ProjA
 (Partial)
WRN: Partial binding information was supplied for an assembly:
WRN: Assembly Name: ProjA | Domain ID: 1
WRN: A partial bind occurs when only part of the assembly display name is provided.
WRN: This might result in the binder loading an incorrect assembly.
WRN: It is recommended to provide a fully specified textual identity for the assembly,
WRN: that consists of the simple name, version, culture, and public key token.
WRN: See whitepaper http://go.microsoft.com/fwlink/?LinkId=109270 for more information and common solutions to this issue.
LOG: Appbase = file:///c:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MSBuild.exe
Calling assembly : System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: c:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
WRN: Not probing location file:///d:/svn/twilight/_build/ProjA.DLL, because the location falls outside of the appbase.
WRN: Not probing location file:///d:/svn/twilight/_build/ProjA/ProjA.DLL, because the location falls outside of the appbase.
WRN: Not probing location file:///d:/svn/twilight/_build/ProjA.EXE, because the location falls outside of the appbase.
WRN: Not probing location file:///d:/svn/twilight/_build/ProjA/ProjA.EXE, because the location falls outside of the appbase.
LOG: Attempting download of new URL file:///c:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/ProjA.DLL.
LOG: Attempting download of new URL file:///c:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/ProjA/ProjA.DLL.
LOG: Attempting download of new URL file:///c:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/ProjA.EXE.
LOG: Attempting download of new URL file:///c:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/ProjA/ProjA.EXE.
LOG: All probing URLs attempted and failed.

And If I copy MsBuild.exe in the directory where all my dll are, it works fine...
MsBuild does not seem to look for dep1.dll and dep2.dll in my Compil directory even if it finds ProjA.dll within...


EDIT

As to how my bindings are done : MyTask references the ProjA Project by :

<ProjectReference Include="..\ProjA\ProjA.csproj">
   <Project>{ED61DCC3-D759-4D44-B802-A6A46F328402}</Project>
   <Name>ProjA</Name>
</ProjectReference>

ProjA references the two dependencies by

<Reference Include="dep1, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>..\Dependencies\dep1\dep1.dll</HintPath>
</Reference>
<Reference Include="dep2, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>..\Dependencies\dep2\dep2.dll</HintPath>
</Reference>
+2  A: 

You might try the Fusion Log Viewer (fuslogvw.exe, installed with VisualStudio) to see which paths are being searched for the assemblies. You may find another folder that can be used instead.

If dep1 and dep2 are third-party assemblies or internal ones that won't change, you could always throw them in the GAC. This is something I generally avoid on a build server, but if you are only using them for build helpers and not production installs it shouldn't be an issue.

Edit: The partial bind might be the cause. Are you using Assembly.Load to use ProjA? From the logs you provided, it looks like it is failing to load ProjA - it is not getting far enough to even try loading dep1 or dep2.

Pedro
I will give a try to Fusion Log Viewer this will give a more concrete result than the comments from microsoft.csharp.targets. As for the GAC, dep1 and dep2 are Projects we are making, so the dlls change. That's why I prefer copying them by hand to msbuilddir and delete them afterwards...
Benjamin Baumann
Thanks for your help. I edited my post with my binding configurations. I don't Load assemblies by code but only by configuration. I think the log seems that it fails to FULLY load ProjA (in fact the dep1 and dep2 dependencies) which is consistent with MSBUild error message : "Could not load file or assembly 'dep1, Version=2.0.0.0, Culture=neutral,PublicKey Token=9109c11469ae1bc7'"
Benjamin Baumann
I give the reward to you Pedro because you helped me the most, but I still haven't my answer :'(. Thanks, Pedro.
Benjamin Baumann
Do you have a sample (with code) that shows this problem? If I can get a copy, I might be able to help debug.
Pedro
A: 

There are a couple of work arounds that I could sugest.

  1. ILMerge this will allow you merge several Assemblies together, into one assembly.

  2. You can add the secondary refence to your solution even though you are not using it, this would copy it to your bin folder.

  3. create another Target to run after the compile to copy the missing Assembly to the folder

Hope this helps.

Iain

Iain
I know ILMerge and it could solve the problem. But I will use it only in last option (I may even prefer copying MSBuild.exe to the directory). As for options 2 and 3 : the files are in the output folder, they are marked private (copylocal in VS) and everything is fine. I did this several times with C# dll projects with no harm. But with a MSBuild Custom Task, MSBuild doesnot seem to look for the second-level assemblies in the current directory...
Benjamin Baumann