views:

439

answers:

3

How can we make our build process (Dev Studio 2005) for a .NET project completely independent of what is installed on the GAC on the particular machine that it is running on.

Here's the problem we're trying to solve: Depending on what assemblies happen to have been installed into the GAC, our build process generates different .NET assemblies in the output directory that we then use to build a .MSI

Presumably this is because dev studio is assuming that, because it's installed in the GAC, it should not be installed as part of our product.

We want to disable this behaviour so that all .NET assemblies that are referenced, directly or indirectly by our project, get copied into the output directory of the project (excepting the .NET 2.0 runtime standard assemblies).

For direct assembly references, I am aware that setting "Copy Local=True" makes this work.

However, this isn't working for indirect assembly references.

i.e. One of our projects references an assembly called "A.dll", which depends on another assembly called "B.dll" which is in the same directory as "A.dll". On machines in which "B.dll" is not installed in the GAC, both A.dll and B.dll are copied to the output directory in the Dev studio build process. This is what we want.

But on machines on which B.dll is installed into the GAC, even if "Copy Local = True" for A.dll, B.dll does not get copied into the output directory.

A: 

The simplest answer is to be explicit: add a reference to B.dll and set it how you want it.

Marc Gravell
+1  A: 

I think you probably should not be relying on the Visual Studio build process to do this for you automatically, particularly when the results can vary depending on the building machine.

What I would do in this case (this applies whether you are building with Visual Studio or using an automated build script) is to have some post-build script (I usually use batch files for simplicity) copy all of the assemblies your project needs into the appropriate directory immediately after the build (I normally keep any assemblies that are not part of my project in a directory in my source control so that it's all in one place). Then when you build your installer, everything is exactly where it needs to be.

DannySmurf
+3  A: 

Like Marc suggested, the only way to do it was to add the dependent references and setting CopyLocal=True.

But I'm coming to agree with Danny's answer - don't use Dev Studio for your deployment, because you can't get sufficient control over the build process.

Why? There's some "defaulting" logic going on with the Dev Studio in which if it has computed the value of a property, then it won't save it to the .CSPROJ file, leaving a Dev Studio instance on another machine the task of "defaulting" the property to something else!

The only error-free way to do it is to explicitly edit the .csproj xml file directly and ensure that you've added True to the Reference element:

<ItemGroup>
    <Reference Include="ConfigManagerClient, Version=1.0.0.0, Culture=neutral, PublicKeyToken=20fc1ffb797ec904, processorArchitecture=MSIL">
    <SpecificVersion>False</SpecificVersion>
    <HintPath>..\..\thirdparty\CM\ConfigManagerClient.dll</HintPath>
    <!-- If DevStudio inferred this to be true, then it won't explicitly save it.
         When the project is loaded on another machine on which the assembly is
         installed in the GAC,
         Dev Studio on _that_ machine will infer that CopyLocal should be False!!
     -->
    <Private>True</Private>
</Reference>

This sort of behaviour appears to make it next to impossible to know what your .CSPROJ file is going to do when run on a different machine.

In the long run you're much better off not entrusting your build and packaging process to Dev Studio and instead just using, say, Nant and explicit command lines.

Paul Hollingsworth