NAnt resource linking / building

Go To StackoverFlow.com

0

I have almost cracked this NAnt thing, and all I can say is Visual Studio has certainly "hidden" a lot of things behind the covers when it comes to compiling.

I have my VB.NET app compiling successfully now via NAnt, however it does not run, it comes up with the error:

Could not find any resources appropriate for the specified culture or the neutral culture.
Make sure "APP3.Resource.resources" was correctly embedded or linked into assembly "APP3" at compile time, or that all the satellite assemblies required are loadable and fully signed.

When I compile and run in Visual Studio it all works fine.

The build file includes all the .resx files for all projects being compiled, and I do not get any errors during the NAnt build process.

Any ideas would be appreciated :-)

Oh, and I notice that my EXE is 6kb smaller, so something is obviously missing, and the NAnt process does not seem to create a manifest file either, or all the XML files, I assume that is normal?

<?xml version="1.0"?>
<project name="APP3" default="build" basedir="..\">
<description>APP3 build</description>
<property name="nant.settings.currentframework" value="net-3.5" />
<property name="projectversion" value="3.8.0" />
<property name="project.config" value="debug" />

<target name="init">
    <call target="${project.config}" />
</target>

<target name="debug">
    <property name="project.config" value="debug" />
    <property name="build.debug" value="true" />
    <property name="basedir.suffix" value="-debug" />
</target>

<target name="release">
    <property name="project.config" value="release" />
    <property name="build.debug" value="false" />
    <property name="basedir.suffix" value="-release" />
</target>

<target name="clean">
    <delete file="${project::get-base-directory()}${project::get-name()}_${projectversion}${basedir.suffix}\APP3_DataClasses.dll" failonerror="false" />
    <delete file="${project::get-base-directory()}${project::get-name()}_${projectversion}${basedir.suffix}\classUtilities.dll" failonerror="false" />
    <delete file="${project::get-base-directory()}${project::get-name()}_${projectversion}${basedir.suffix}\APP3.exe" failonerror="false" />
</target>

<target name="build-classutilities" depends="init, clean" description="compiles the     APP3 utilities class">
    <property name="build.dir" value="${project::get-base-directory()}/${project::get-name()}_${projectversion}${basedir.suffix}"/>
    <mkdir dir="${build.dir}" />
    <vbc target="library" output="${build.dir}/classUtilities.dll" debug="${build.debug}" rootnamespace="classUtilities">
        <imports>
            <import namespace="Microsoft.VisualBasic" />
            <import namespace="System" />
            <import namespace="System.Collections" />
            <import namespace="System.Collections.Generic" />
            <import namespace="System.Data" />
            <import namespace="System.Diagnostics" />
            <import namespace="System.Linq" />
            <import namespace="System.Xml.Linq" />
        </imports>
        <sources>
            <include name="${project::get-base-directory()}/classUtilities/Utilities.vb" />
        </sources>
        <resources>
            <include name="${project::get-base-directory()}/classUtilities/*.resx" />
            <include name="${project::get-base-directory()}/classUtilities/My Project/*.resx" />
        </resources>
        <references>
            <include name="System.dll" />
            <include name="System.Data.dll" />
            <include name="System.Core.dll" />
            <include name="System.Xml.dll" />
            <include name="System.Xml.Linq.dll" />
        </references>
    </vbc>
</target>

<target name="build-dataclasses" depends="build-classutilities" description="compiles the APP3 data classes">
    <property name="build.dir" value="${project::get-base-directory()}/${project::get-name()}_${projectversion}${basedir.suffix}"/>
    <mkdir dir="${build.dir}" />
    <vbc target="library" output="${build.dir}/APP3_DataClasses.dll" debug="${build.debug}" rootnamespace="APP3_DataClasses">
        <imports>
            <import namespace="Microsoft.VisualBasic" />
            <import namespace="System" />
            <import namespace="System.Collections" />
            <import namespace="System.Collections.Generic" />
            <import namespace="System.Configuration" />
            <import namespace="System.Data" />
            <import namespace="System.Diagnostics" />
            <import namespace="System.Xml" />
            <import namespace="System.Xml.Linq" />
            <import namespace="Iesi.Collections" />
        </imports>
        <sources>
            <include name="${project::get-base-directory()}/APP3_DataClasses/**/*.vb" />
        </sources>
        <resources prefix="APP3_DataClasses">
            <include name="${project::get-base-directory()}/APP3_DataClasses/*.resx" />
            <include name="${project::get-base-directory()}/APP3_DataClasses/My Project/*.resx" />
            <include name="${project::get-base-directory()}/APP3_DataClasses/*.hbm.xml" />
        </resources>
        <references>
            <include name="System.dll" />
            <include name="System.Core.dll" />
            <include name="System.Xml.dll" />
            <include name="System.Xml.Linq.dll" />
            <include name="C:\Dev\NHibernate-2.1.2\Required_Bins\Iesi.Collections.dll" />
        </references>
    </vbc>
</target>

<target name="build" description="compiles the source code" depends="build-dataclasses">
    <property name="build.dir" value="${project::get-base-directory()}/${project::get-name()}_${projectversion}${basedir.suffix}"/>
    <mkdir dir="${build.dir}" />
    <copy file="C:\Dev\NHibernate-2.1.2\Required_Bins\NHibernate.dll" tofile="${build.dir}/NHibernate.dll" />
    <copy file="C:\Dev\NHibernate-2.1.2\Required_Bins\Iesi.Collections.dll" tofile="${build.dir}/Iesi.Collections.dll" />
    <copy file="C:\Dev\NHibernate-2.1.2\Required_Bins\log4net.dll" tofile="${build.dir}/log4net.dll" />
    <copy file="${project::get-base-directory()}/APP3/hibernate.cfg.xml" tofile="${build.dir}/hibernate.cfg.xml" />
    <copy file="C:\Dev\LumenWorks.Framework\LumenWorks.Framework.3.8.0\LumenWorks.Framework.IO.dll" tofile="${build.dir}/LumenWorks.Framework.IO.dll" />
    <copy file="C:\Program Files (x86)\Microsoft Visual Studio 9.0\Visual Studio Tools for Office\PIA\Office11\Microsoft.Office.Interop.Word.dll" tofile="${build.dir}/Microsoft.Office.Interop.Word.dll" />
    <copy file="C:\Program Files (x86)\Microsoft Visual Studio 9.0\Visual Studio Tools for Office\PIA\Office11\office.dll" tofile="${build.dir}/office.dll" />
    <copy file="C:\Program Files (x86)\Microsoft Visual Studio 9.0\Visual Studio Tools for Office\PIA\Office11\Microsoft.Vbe.Interop.dll" tofile="${build.dir}/Microsoft.Vbe.Interop.dll" />
    <copy file="${project::get-base-directory()}/APP3/app.config" tofile="${build.dir}/APP3.exe.config" />
    <copy todir="${build.dir}">
        <fileset basedir="C:\Dev\NHibernate-2.1.2\Required_For_LazyLoading\Castle\">
            <include name="*.dll" />
        </fileset>
    </copy>
    <vbc target="winexe" output="${build.dir}/APP3.exe" debug="${build.debug}" rootnamespace="APP3">
        <imports>
            <import namespace="Microsoft.VisualBasic" />
            <import namespace="System" />
            <import namespace="System.Collections" />
            <import namespace="System.Collections.Generic" />
            <import namespace="System.Configuration" />
            <import namespace="System.Data" />
            <import namespace="System.Data.SqlClient" />
            <import namespace="System.Diagnostics" />
            <import namespace="System.Drawing" />
            <import namespace="System.Windows.Forms" />
            <import namespace="System.IO" />
            <import namespace="System.Xml" />
        </imports>
        <sources>
            <include name="${project::get-base-directory()}/${project::get-name()}/*.vb" />
            <include name="${project::get-base-directory()}/${project::get-name()}/classes/*.vb" />
            <include name="${project::get-base-directory()}/${project::get-name()}/historical/*.vb" />
            <include name="${project::get-base-directory()}/${project::get-name()}/Modules/*.vb" />
            <include name="${project::get-base-directory()}/${project::get-name()}/My Project/*.vb" />
        </sources>
        <resources prefix="APP3" dynamicprefix="true">
            <include name="${project::get-base-directory()}/${project::get-name()}/*.resx" />
            <include name="${project::get-base-directory()}/${project::get-name()}/My Project/*.resx" />
        </resources>
        <references>
            <include name="Microsoft.VisualBasic.dll" />
            <include name="System.dll" />
            <include name="System.Data.dll" />
            <include name="System.Windows.Forms.dll" />
            <include name="System.configuration.dll" />
            <include name="System.Drawing.dll" />
            <include name="${build.dir}/APP3_DataClasses.dll" />
            <include name="${build.dir}/classUtilities.dll" />
            <include name="System.Xml.dll" />
            <include name="C:\Dev\NHibernate-2.1.2\Required_Bins\Iesi.Collections.dll" />
            <include name="C:\Dev\NHibernate-2.1.2\Required_Bins\NHibernate.dll" />
            <include name="C:\Dev\NHibernate-2.1.2\Required_Bins\log4net.dll" />
            <include name="C:\Dev\LumenWorks.Framework\LumenWorks.Framework.3.8.0\LumenWorks.Framework.IO.dll" />
            <include name="C:\Program Files (x86)\Microsoft Visual Studio 9.0\Visual Studio Tools for Office\PIA\Office11\Microsoft.Office.Interop.Word.dll" />
        </references>
    </vbc>
</target>

2012-04-04 07:22
by Dominik
Out of curiosity, and for a better context: why do you need to build with NAnt? Nowadays everything you would customise with NAnt is doable with MSbuild as well, which gets you a build that can be performed straight from the VS in addition to the command line tool - skolima 2012-04-04 07:29
Good question, and to be honest I just need something that will compile on our new CI server (Atlassian Bamboo), which I see does both NAnt and MSBuild. If MSBuild is easier to get working in that scenario, where the CI server does not have VS of any type installed, just the .NET frameworks. We have had problems in the past with .NET 2.0 msbuild, in terms of not picking up reference paths to DLLs (it will only pick up 1), but if that can be overcome, no problem - Dominik 2012-04-04 07:34
MSBuild got much improved in 3.5 and 4.0 releases, 4.0 has finally feature-parity with NAnt. And it's installed together with a normal .Net Framework installation - skolima 2012-04-04 10:07
OK, my only concern is previously it was difficult to tell msbuild all the paths (3 or 4) where to check for DLLs during the build process. Do you have any details on how this can be achieved so that I have a different build file used by the CI server, where the DLLs are in different locations to my dev PC - Dominik 2012-04-04 22:50
Generally, you should use relative paths and have the same project layout on all machines. However, with HintPath or AssemblySearchPaths, you can tell MSBuild where to search for references. You can include a variable in there, with a default value so that it works in VS, and set it to different value when building in CI. More information: http://msdn.microsoft.com/en-us/magazine/dd483291.aspx#id010004 - skolima 2012-04-06 07:44


0

I faced the same problem, and then tested each of the assemblies with the program .NET Reflector I've discovered that when a program is compiled from the VS, a resource file Properties\Resources.resx in the assembly has a name appName.Properties.Resources.resources. When you use nAnt

<resources>
    <include name="${proj_dir}/Properties/Resources.resx"/>
</ resources>

in the assembly resource file has name Resources.resources .

I solved this problem as follows.

<target name="example">
    <copy file="${proj_dir}/Properties/Resources.resx" tofile="${proj_dir}/Properties/appName.Properties.Resources.resx"/>
    <csc target="winexe" output="${bin_dir}/appName.exe">
        <sources>
            <include name="${proj_dir}/*.cs"/>
            <include name="${proj_dir}/Properties/*.cs"/>                           
        </sources>
            <resources>
            <include name="${proj_dir}/Properties/appName.Properties.Resources.resx"/>
        </resources>
    </csc>
    <delete file="${proj_dir}/Properties/appName.Properties.Resources.resx"/>
</target>
2012-05-13 17:45
by Gambit
Great answer! For anyone looking, I also found this at https://support.microsoft.com/en-us/kb/839861 "When you run Resgen.exe, if you do not specify the file name of the output file while you convert an XML-based resource format (.resx) file to a .resources file, Resgen.exe creates a .resources file that has the same file name as the input file. If the file name of your XML-based resource format file does not start with the namespace name of your application, the file name of the .resources file will not contain this namespace name either. - clairestreb 2016-10-13 16:38
Ads