How do I create an application.extension.config file using MSBuild?

Hi,
I'm using MSBuild to build an executable program (exe) from VB.net source code. How do I get MSBuild to output an ApplicationName.exe.config file?
Thanks,
Damian
[219 byte] By [DMorrissey] at [2007-12-17]
# 1
MSBuild does not generate .CONFIG files on its own. The only thing it can do for you is copy an existing .CONFIG file from your project to the final bin directory. So, if you have a file in your project called "APP.CONFIG", then MSBuild will copy this file to the bin directory as "AssemblyName.EXE.CONFIG".
RajeevGoelmsft at 2007-9-9 > top of Msdn Tech,Visual Studio,Visual Studio MSBuild...
# 2
Thanks for that Rajeev. I do have a file called APP.CONFIG in my project. However, this isn't being copied to the bin directory as "AssemblyName.EXE.CONFIG" when I run MSBuild. Should MSBuild do this automatically or do I have to do this manually?
Regards,
Damian
DMorrissey at 2007-9-9 > top of Msdn Tech,Visual Studio,Visual Studio MSBuild...
# 3
Hmm, MSBuild really should have copied that file automatically for you. Would you mind pasting in the contents of your project file (.CSPROJ or .VBPROJ), so we can take a closer look?

--Rajeev

RajeevGoelmsft at 2007-9-9 > top of Msdn Tech,Visual Studio,Visual Studio MSBuild...
# 4
Hi Rajeev,
Here's the project file as requested:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SchemaVersion>C:\Windows\Microsoft.NET\Framework\v2.0.50215</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\GlobalAssemblyInfo.vb" />
<Compile Include="AssemblyInfo.vb" />
<Compile Include="modMain.vb" />
<Compile Include="My Project\MyApplication1.vb" />
<Compile Include="My Project\MyResources.vb" />
<Compile Include="My Project\Settings.Designer.vb" />
<Compile Include="PerformanceTest.Designer.vb" />
<Compile Include="PerformanceTest.vb" />
<Compile Include="PRSCL00002WindowManager.vb" />
<Compile Include="PulseSpalsh.vb" />
<Compile Include="FormObjectStack.vb" />
</ItemGroup>
<ItemGroup>
<Reference Include="$(SchemaVersion)\Microsoft.VisualBasic.Compatibility.dll" />
<Reference Include="..\PULSEConstants\bin\PULSE.Constants.dll " />
<Reference Include="..\PULSEFormObjects\bin\PULSE.FormObjects.dll " />
<Reference Include="..\PULSETAClient\bin\PULSE.TA.Client.dll " />
<Reference Include="..\PULSETACommon\bin\PULSE.TA.Common.dll" />
<Reference Include="$(SchemaVersion)\System.dll" />
<Reference Include="$(SchemaVersion)\System.Data.dll" />
<Reference Include="$(SchemaVersion)\System.Drawing.dll" />
<Reference Include="$(SchemaVersion)\System.EnterpriseServices.dll" />
<Reference Include="$(SchemaVersion)\System.Windows.Forms.dll" />
<Reference Include="$(SchemaVersion)\System.Xml.dll" />
</ItemGroup>
<ItemGroup>
<Import Include="Microsoft.VisualBasic" />
<Import Include="PULSE.Constants" />
<Import Include="PULSE.FormObjects" />
<Import Include="PULSE.TA.Client" />
<Import Include="PULSE.TA.Common" />
<Import Include="System" />
<Import Include="System.Collections" />
<Import Include="System.Data" />
<Import Include="System.Diagnostics" />
<Import Include="System.Drawing" />
<Import Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="My Project\MyResources.resources" />
<EmbeddedResource Include="PerformanceTest.resources" />
<EmbeddedResource Include="PulseSpalsh.resources" />
</ItemGroup>
<Target Name="Compile">
<ResGen References="@(Reference)" Sources="@(EmbeddedResource)" UseSourcePath="true" />
</Target>
<Target Name="Build" Outputs="bin\PULSEApplication.exe" DependsOnTargets="Compile">
<Vbc MainEntryPoint="Sub Main" NoConfig="true" ContinueOnError="true" Optimize="false" DefineConstants="NOCOMPLUS=0" RemoveIntegerChecks="false" NoWarnings="true" Resources="@(EmbeddedResource)" Sources="@(Compile)" DebugType="full" OutputAssembly="bin\PULSEApplication.exe" BaseAddress="11000000" Verbosity="quiet" References="@(Reference)" Imports="@(Import)" OptionCompare="binary" OptionExplicit="true" OptionStrict="false" RootNamespace="PULSE.Application" TargetType="winexe" Win32Icon="PulseNetIcon.ico" />
</Target>
</Project>

DMorrissey at 2007-9-9 > top of Msdn Tech,Visual Studio,Visual Studio MSBuild...
# 5

Okay, I admit I had made some false assumptions about your project. The project you are showing has a completely custom build process. You've implemented your own "Build" and "Compile" target, and you didn't code in the step to copy APP.CONFIG to the bin directory as AssemblyName.exe.config. When I said that this should happen automatically, what I really should have said was that this happens automatically if you are using the build process defined in Microsoft.VisualBasic.targets and Microsoft.Common.targets. This is the default VB build process that gets run for all VB projects that you just create from Visual Studio, because those .VBPROJ files will have an <Import Project="... ... Microsoft.VisualBasic.targets"/>. But since you're using your own build process, you'll have to add the step to copy APP.CONFIG yourself.

Couple other notes and questions:

1. Just out of curiosity, why did you implement your own build process rather than just importing Microsoft.VisualBasic.targets? There's nothing wrong with what you did; I'm just curious.

2. You actually don't have APP.CONFIG listed as an item in your project anywhere, or at least not that I can see. In one of the ItemGroups you need to add:
<None Include="app.config" />

3. The <ResGen> task doesn't exist anymore. Which version of MSBuild are you using? The replacement for this is the <GenerateResource> task.

4. When you pass in the "Sources" parameter to <ResGen>, it's actually expecting a bunch of .RESX files, but it looks like you're passing in .RESOURCES files which are already compiled.

--Rajeev

RajeevGoelmsft at 2007-9-9 > top of Msdn Tech,Visual Studio,Visual Studio MSBuild...
# 6
Thanks for that Rajeev. I've added a step to copy the App.config file which is now working.
To answer your questions:
1. We implemented our own build process because we needed as much flexibility as possible. Each .proj is generated as part of the build process. If you could outline how I could do the same thing by importing Microsoft.VisualBasic.targets that would be great.
2. I added <none include="app.config" /> as suggested.
3. My original build process used the beta 1 version of VS 2005 .Net framework. I recently upgraded to beta 2 which entailed making changes to the .proj files for MSBuild. I was unaware that ResGen no longer exists. Thanks for pointing this out.
4. I am passing in resX files. The version of the .proj file I pasted in was incorrect.
On another issue when I attempt to run the resultant .exe
file (built by MSBuild) I get an unhandled exception error. This doesn't happen when I build the .exe in VS 2005. Am I missing something in the .proj file?
Thanks.

DMorrissey at 2007-9-9 > top of Msdn Tech,Visual Studio,Visual Studio MSBuild...
# 7
Damian,

1. You don't need to implement your own build process in order to have flexibility. I would suggest that you remove the <Target> nodes from your generated project file, and instead just add this line:

<Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.targets" />

That will take care of everything so that you don't have to figure out the whole build process yourself. If you do need to customize portions of the build, you can still do so by overriding specific targets or inserting your own build steps into the chain where appropriate. If you have a specific customization you're trying to achieve, and need help with it, post another question to this forum and somebody will try to help.

Also, something you said is making me wonder if you currently have two different project files ... one .PROJ file which you're generating yourself and using with MSBuild.exe from the command-line, and a separate .VBPROJ file which you are creating with Visual Studio for builds inside the IDE. Is this true? If this is the case, it is absolutely not necessary to do this. You can use a single project file for both. You can just run MSBuild.exe on the .VBPROJ that Visual Studio created. Also, you can open the .VBPROJ and customize portions of the build process as necessary, and it will still work both on the command-line and inside Visual Studio.

3. You may also consider upgrading to the final release version of VS 2005 and .NET Framework 2.0, which just shipped.

Regarding the error you're getting when running the project as built by MSBuild but not when built by VisualStudio ... this again makes me wonder if you have two different project files with different build processes ... one for MSBuild and one for VisualStudio. If you use the exact same project file for both, then the build process should produce identical binaries, and they should run the same way. By the way, what exception were you getting when you ran your app after building it with MSBuild?

--Rajeev

RajeevGoelmsft at 2007-9-9 > top of Msdn Tech,Visual Studio,Visual Studio MSBuild...
# 8
Hi Rajeev,
As you suggested I removed my <Target> nodes and replaced them with <Import Project ...> and after a bit of customisation I got it to work. The resultant exe is also running without the previous exception error.

I don't have two project files. I only run MSBuild against .proj files. I was using the output from a Visual Studio build to compare my MSBuild output with.
Thank you for your help, it was much appreciated.
Damian
DMorrissey at 2007-9-9 > top of Msdn Tech,Visual Studio,Visual Studio MSBuild...

Visual Studio

Site Classified