VBC + NAnt. Error compiling WinForm - build-process

It should first be noted that I am trying to avoid rewriting all my scripts to use msbuild.
I have noticed that there are several problems when using NAnt with the VBC task and compiling a WinForms application. The main problem seems to be that VBC can't find Sub Main. This is odd, since from within VS, there is no indication that there is any sort of difference between my call to vbc and msbuild's call to vbc.
Does anyone have any insight into a solution to this problem or a way to force the creation of the rest of the partial classes that might/might not be being produced by MSBuild/VS?
Sample Build Script:
<?xml version="1.0" encoding="utf-8" ?>
<project xmlns="http://nant.sf.net/release/0.85/nant.xsd" name="Test" default="build">
<target name="build">
<vbc target="winexe" output="C:\Test.exe" main="WindowAppNantTest.My.MyApplication" verbose="true" rootnamespace="WindowAppNantTest">
<imports>
<import namespace="Microsoft.VisualBasic"/>
<import namespace="System.Windows.Forms"/>
</imports>
<sources>
<include name="**/**/*.vb"/>
</sources>
</vbc>
</target>
</project>
Error(s):
[vbc] vbc : error BC30420: 'Sub Main' was not found in 'WindowAppNantTest.My.MyApplication'.

It appears like the problem is coming from the main and rootnamespace attributes. What happens when you switch them to be something like the following:
<vbc target="winexe" output="C:\Test.exe" main="MyApplication" verbose="true" rootnamespace="WindowAppNantTest.My">
<imports>
<import namespace="Microsoft.VisualBasic"/>
<import namespace="System.Windows.Forms"/>
</imports>
<sources>
<include name="**/**/*.vb"/>
</sources>
</vbc>
or something like the following:
<vbc target="winexe" output="C:\Test.exe" main="My.MyApplication" verbose="true" rootnamespace="WindowAppNantTest">
<imports>
<import namespace="Microsoft.VisualBasic"/>
<import namespace="System.Windows.Forms"/>
</imports>
<sources>
<include name="**/**/*.vb"/>
</sources>
</vbc>

I'm not sure if you mean you don't want to use msbuild within NAnt or if you don't want to switch to msbuild scripting wholesale.
If it is the latter, then my reply on your other post on the same topic is valid here as well.
You can use NAnt contrib (http://nantcontrib.sourceforge.net/) and use msbuild within your NAnt script.
The reference on the msbuild task is:
http://nantcontrib.sourceforge.net/release/latest/help/tasks/msbuild.html
And the pertinent snippet:
<target name="build" depends="clean">
<msbuild project="ProjectName.vbproj" />
</target>

What you need to do is set the following into your VBC command:
<references>
<include name="System.Windows.Forms.dll"/>
<indlude name="Microsoft.VisualBasic.dll"/>
</references>
This should fix your problem. (I guessed on the second dll as I'm a CS guy) however the syntax for compiling is pretty much the same.
In all the projects I've worked on you always need to set the references to include any DLL's whether they are from .Net, 3rd party or your own (ie Project references) otherwise they won't link in properly.
Give that a go and see what happens.

Related

Publish not transforming Web.config for Website project [duplicate]

It doesn't seem to be possible to change the Build Configuration of Visual Studio 2010 Website Projects (as opposed to Visual Studio Web Applications), and changing the Build Configuration is a key part of enabling Web.config transformations (it's not possible to change the configuration to anything except Debug).
How do I get Web.config transformations to work with Visual Studio 2010 Website projects if it's not possible to change the Build Configuration?
I'd prefer not to use entire an Web Application Project solution out of box.
My solution is to use the XmlTransform task defined in Microsoft.Web.Publishing.Tasks.dll directly (this task is the core of WebConfigTransformation)
This way it is flexible enough and does exactly what you expect it to do.
For example here is the WebSiteTransformator.csproj I'm using for transforming web.config.
Here also is an example of flexibility that is impossible to reach with original WebConfigTransformation: it takes web.Template.config, applies web.$(Configuration).config over it and writes web.config. This allows us to add web.config itself into ignore list in source control. It is still valid csproj to be referenced by website:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<OutputType>Library</OutputType>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<OutputPath>$(TEMP)\TransformWebConfig\bin</OutputPath>
<BaseIntermediateOutputPath>$(TEMP)\TransformWebConfig\obj\</BaseIntermediateOutputPath>
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
<WebFolderName>$(SolutionDir)\MyWebSite\</WebFolderName>
</PropertyGroup>
<ItemGroup>
<Compile Include="Dummy.cs" />
</ItemGroup>
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll"/>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="BeforeBuild">
<TransformXml Source="$(WebFolderName)Web.Template.config"
Transform="$(WebFolderName)Web.$(Configuration).config"
Destination="$(WebFolderName)Web.config" />
</Target>
</Project>
I found a pretty good blog post describing a solution to this here:
http://andrewtwest.com/2010/02/25/using-web-config-transformations-in-web-site-projects/
In short: create an empty project (as long as it is not another website project) in your solution that contains the website. The empty project will give you access to msbuild through its project file, which will allow you to perform transforms on your website web.config.
I used a slightly alternative approach. Still a bit of a hack, but I think a lot more straightforward. This worked for me, but obviously there are a lot of different configurations available so I can't guarantee it'll work for everyone. This revolves around the way that a website is first packaged up in to your AppData folder before being published...
Manually add a Web.Release.config file to the website and add the necessary transforms - obviously there's no 'Add Config Transform' option for websites, hence having to do this manually. Example Web.Release.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="MySetting" value="NewValue" xdt:Transform="Replace" xdt:Locator="Match(key)" />
</appSettings>
<system.web>
<compilation xdt:Transform="RemoveAttributes(debug)" />
</system.web>
</configuration>
Inside the website.publishproj file, ensure the configuration is set to Release:
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
Add the following to the very bottom of website.publishproj (just before </Project>):
<Target Name="AfterBuild">
<MakeDir Directories="$(PackageArchiveRootDir)\..\CSAutoParameterize\original" />
<TransformXml Source="Web.config" Transform="Web.$(ConfigurationName).config" Destination="$(PackageArchiveRootDir)\..\CSAutoParameterize\original\Web.config" StackTrace="false" />
</Target>
Create a publish profile in VS 2017 and then right click on the .pubxml profile in App_Data\PublishProfiles and select Add Config Transform.
See https://social.msdn.microsoft.com/Forums/vstudio/en-US/31f41991-abb2-41de-ad0b-c1379cc7c806/vs-2013-express-for-web-webconfig-transforms?forum=visualstudiogeneral&prof=required
As mentioned in Andriy's comment above, Solution wide build events definitely seems like a cleaner way to do this.
I am adding this as a separate answer, as it gets a little lost in the comment, but IMHO is the best answer. Props to Andriy K and Sayed Ibrahim.
If you would prefer not to need a Web.Template.config, I used this:
<PropertyGroup>
<_tempSourceFile>$([System.IO.Path]::GetTempFileName())</_tempSourceFile>
<_tempTransformFile>$([System.IO.Path]::GetTempFileName())</_tempTransformFile>
</PropertyGroup>
<Copy SourceFiles="$(ProjectDir)Web.config" DestinationFiles="$(_tempSourceFile)"/>
<Copy SourceFiles="$(ProjectDir)Web.$(Configuration).config" DestinationFiles="$(_tempTransformFile)"/>
<TransformXml Source="$(_tempSourceFile)"
Transform="$(_tempTransformFile)"
Destination="$(ProjectDir)Web.config"
StackTrace="false" />
Adapted from an answer here.

Is there a basic, standard .build file for NAnt?

Basically, I'm trying to integrate CruiseControl.NET with NAnt. I've got CC.NET set up, but I'm getting an exception when it tries to build with NAnt.
BUILD FAILED - Could not find a '*.build' file in 'C:\inetpub\MyProject\'
Okay, no big deal, I just have to create a build file. Not sure what that is, but I found one in the HelloWorld example that came with NAnt, it looks like this:
<project name="Hello World" default="run">
<property name="basename" value="HelloWorld"/>
<property name="debug" value="true"/>
<target name="clean">
<delete>
<fileset>
<include name="bin/${basename}-??.exe"/>
<include name="bin/${basename}-??.pdb"/>
</fileset>
</delete>
</target>
<target name="build">
<mkdir dir="bin" />
<csc target="exe" output="bin/${basename}-cs.exe" debug="${debug}">
<sources>
<include name="${basename}.cs"/>
</sources>
</csc>
<jsc target="exe" output="bin/${basename}-js.exe" debug="${debug}">
<sources>
<include name="${basename}.js"/>
</sources>
</jsc>
<vbc target="exe" output="bin/${basename}-vb.exe" debug="${debug}">
<sources>
<include name="${basename}.vb"/>
</sources>
</vbc>
</target>
<target name="run" depends="build">
<exec program="bin/${basename}-cs.exe" basedir="."/>
<exec program="bin/${basename}-js.exe" basedir="."/>
<exec program="bin/${basename}-vb.exe" basedir="."/>
</target>
</project>
There's a lot more content in this file than I was expecting. I tried searching around to find out what everything meant, what was required, etc. But I couldn't find anything.
Is there just a basic and standard file that I could use? All I want to do is simply build my entire application, nothing crazy.
Nant's tasks and attributes are described here: NAnt Help
Task Reference
Also,
A Brief Introduction to NAnt
NAnt Starter Series
This article has a template:
The Anatomy of a NAnt Build File
Plus, previous SO question:
Simple HelloWorld build script

Applying Web.Config transformations outside of Web Deployment

Is there a way to apply VS 2010 Web.Config transformations outside of web deployment, say during debugging? It would give me a great boost to be able to freely switch between different environments.
Yes, you can perform a Web.config transformation explicitly by invoking the TransformXml MSBuild task during the AfterBuild step in your project file.
Here's an example:
<UsingTask
TaskName="TransformXml"
AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterBuild" Condition="exists('Web.$(Configuration).config')">
<!-- Generates the transformed Web.config in the intermediate directory -->
<TransformXml
Source="Web.config"
Destination="$(IntermediateOutputPath)Web.config"
Transform="Web.$(Configuration).config" />
<!-- Overwrites the original Web.config with the transformed configuration file -->
<Copy
SourceFiles="$(IntermediateOutputPath)Web.config"
DestinationFolder="$(ProjectDir)" />
</Target>
Related resources:
Web.config transformations for App.config files
Can I specify that a package should be created every time I build a solution?
The solution above made a great starting point for me, but I ended up with the following which doesn't need a copy task and doesn't have any issues with file in use errors.
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterBuild">
<TransformXml Condition="exists('$(TempBuildDir)\Web.$(Configuration).config')" Source="$(TempBuildDir)\Web.config" Destination="$(OutputPath)Web.config" Transform="$(TempBuildDir)\Web.$(Configuration).config" />
<ItemGroup>
<DeleteAfterBuild Include="$(OutputPath)Web.*.config" />
</ItemGroup>
<Delete Files="#(DeleteAfterBuild)">
<Output TaskParameter="DeletedFiles" PropertyName="deleted" />
</Delete>
<Message Text="DELETED FILES: $(deleted)" Importance="high" />
</Target>

Could not load definitions from resource flexTasks.tasks. It could not be found

I'm attempting to compile a Flex application from an ANT script, inside of Eclipse (CFBuilder, based on Eclipse), and I've run into this error:
Could not load definitions from resource flexTasks.tasks. It could not be found.
I haven't been able to find anything that gives directions on where this file (flexTasks.tasks) should be copied to, if it's needed at all. Some places indicate that it should be part of the flexTasks.jar file. I've tried two different things:
Copy the jar file into the ant/plugins/lib folder (and restart my CF Builder instance)
Specify the path to the jar in the classpath attribute, as suggested by the comment on this page
Neither helps me get past this error.
Here's my build script, for reference:
<project name="Tagging" default="compile-tagging" basedir=".">
<!-- setup flex compilation capability -->
<taskdef resource="flexTasks.tasks" />
<property name="flex.src" value="./src" />
<property name="flex.bin" value="./bin"/>
<target name="compile-tagging">
<mxmlc
file="${flex.src}/main.mxml"
output="${flex.bin}/main.swf"
keep-generated-actionscript="true">
<source-path path-element="${FLEX_HOME}/frameworks" />
</mxmlc>
</target>
</project>
Adam, I believe you need to tell taskdef where to look for the file. try keeping flextasks.jar in the same directory as your ant file (for now... you can move it later after you get it working).
then, you can do something like this:
<taskdef name="mxmlc" classname="WhateverTheTaskIsNamed" classpath="flexTAsks.jar" />
While not ideal, this code is working for me at the moment:
<project name="IOLTagging" default="go" basedir=".">
<!-- setup flex compilation capability -->
<property name="FLEX_HOME" value="C:/program files (x86)/Adobe/Adobe Flash Builder Beta 2/sdks/3.4.1/" />
<taskdef name="mxmlc" classname="flex.ant.MxmlcTask" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" />
<taskdef name="html-wrapper" classname="flex.ant.HtmlWrapperTask" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" />
<property name="flex.src" value="./src" />
<property name="flex.bin" value="./bin"/>
<property name="swf.name" value="main" />
<target name="go" depends="compile-flex" />
<target name="compile-flex">
<mxmlc
file="${flex.src}/main.mxml"
output="${flex.bin}/${swf.name}.swf"
debug="false"
keep-generated-actionscript="false">
<source-path path-element="${FLEX_HOME}/frameworks" />
<compiler.library-path dir="${basedir}/libs" append="true">
<include name="*.swc" />
</compiler.library-path>
</mxmlc>
</target>
</project>
I had the same problem, and the reason was in lack of permissions to acces $FLEX_HOME/ant.
You can also put the flexTasks.jar in ~/.ant/lib directory
If you run ant -diagnostics you should see the jar in USER_HOME/.ant/lib jar listing
I think you should have solved this problem. just trying flexmonkey today and also got the same problem.
"Could not load definitions from resource flexTasks.tasks. It could not be found."
solution is to make sure the flexTasks.jar is included in the dir lib of your project workplace.
when I copied flexTasks.jar from flashbuild folder \ant\lib and built it again. the problem is fixed.

How do I compile an ASP.Net MVC project using MSBuild

How do I compile an ASP.Net MVC project using MSBuild? We use a Continuous Integration server to compile and deploy our applications. To keep things simple I created an MVC 1.0 project in VS2008. I immediately created an MSBuild script file to compile it. I did not change any code in the project. The MSBuild script contained the following target.
<AspNetCompiler
VirtualPath="/"
PhysicalPath="C:\Development\mvc1\"
TargetPath="c:\publish\xxx"
Force="true"
Debug="false"
Updateable="true"
The MVC project sln file is contained in the c:\development\mvc1\ directory. I am running XP/Pro.
I am receiving an error ASPCONFIG: it is an error to use a section registered as allowDefintion='MachineToApplication' beyond application level.. I removed the authenication mode, membership provider, etc. from the web config file until I finally saw a different error message. I am now receiving an error message saying that the file '/views/shared/site.master' does not exist.
What is going on? Thanks in advance for your help!
Am I using the wrong MSBuild command?
If you compile your sln-file (msbuild mysolution.sln) or
<MSBuild Projects="msbuild mysolution.sln" Targets="Rebuild" ContinueOnError="false"
StopOnFirstFailure="false" /><!-- -d -errorstack -->
and the sln-file has the ASP.NET MVC-project .csproj-file then the .csproj-file does have everything you need. Open the .csproj with notepad and look for:
1) This should be true:
<MvcBuildViews>false</MvcBuildViews>
2) Target Name="AfterBuildCompiler":
<Target Name="AfterBuildCompiler" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="SomeVirtualDir" PhysicalPath="C:\Development\mvc1\" TargetPath="c:\publish\xxx\" />
</Target>
I didn't do anything else and it worked. I actually made my config so that only release build deploy the application (by moving MvcBuildViews-property under PropertyGroups. Then I can use the same .csproj in the development (debug) and deployment (release).
This build script compiles an asp.net MVC 3 application. Since the entire internet appears to have forgotten the concept of "Build Script" this one does not require you to have Visual Studio installed on the target Machine or to "lol, you just have to edit your csproj file to get msbuild!!"
Moving on.
Make sure you have .NET 4 and MVC3 installed. By the way, my build scripts only work with msbuild 4, so make sure you're using the proper one.
The general process is as follows (thanks to many hints and answers I got here!)
1) Build the dependencies (you DLL's)
2) Build the DLL for your web application.
3) Call the asp.net compiler task.
4) Check the scripts for additional comments.
Note that this is called from an outside script that compiles other DLL's (Business, data access, etc.)
<Project ToolsVersion="4.0" DefaultTargets="build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildDir>..\..\dist</BuildDir>
<Optimize>true</Optimize>
</PropertyGroup>
<ItemGroup >
<Reference Include="System.dll" />
<Reference Include="System.Core.dll" />
<Reference Include="System.Web.Abstractions.dll" />
<!-- add the remaining DLL's required. Check your References folder inside VS2010 and add the relevant entries here. It's a lot of references. I ommited them to make the post more compact.
For reasons that are beyond me, I only managed to get some DLL's referenced by full path. Go figure... -->
<Reference Include="C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Web.Helpers\v4.0_1.0.0.0__31bf3856ad364e35\System.Web.Helpers.dll" />
<Reference Include="C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Web.Mvc\v4.0_3.0.0.0__31bf3856ad364e35\System.Web.Mvc.dll" />
<Reference Include="C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Web.WebPages\v4.0_1.0.0.0__31bf3856ad364e35\System.Web.WebPages.dll" />
<!-- The "main build script" compiles the other DLL's from the project and places them on the BuildDir folder. Just reference it here-->
<Reference Include="$(BuildDir)\*.dll"></Reference>
</ItemGroup>
<!-- Build a DLL for the code file inside your web project (controllers, models, the lot...) place it together with the other DLL's
WARNING: Simple build command. Resource files are not included in this.
-->
<Target Name="BuildWebDll">
<ItemGroup>
<CodeFiles Include=".\**\*.cs" />
</ItemGroup>
<CSC Sources="#(CodeFiles)" TargetType="Library" References="#(Reference)" OutputAssembly="$(BuildDir)\cth.web.dll" >
</CSC>
</Target>
<!-- For reasons also unkown, but covered in a number os posts in this forum, the asp.net compiler requires the necessary DLL's to be placed on the BIN/ folder of your web project. That's why we're copying every DLL we need to said folder. For debugging, check the Bin folder on Visual Studio after you compile the project. You need to replicate that in your BIN/
-->
<Target Name="CopyDLLs">
<ItemGroup>
<DllFiles Include="$(BuildDir)/*.dll"/>
</ItemGroup>
<Copy SourceFiles="#(DllFiles)" DestinationFolder="Bin\"></Copy>
</Target>
<Target Name="build">
<CallTarget Targets="BuildWebDll"></CallTarget>
<CallTarget Targets="CopyDLLs"></CallTarget>
<!-- Call this from the webproject directory. PhysicalPath references ".". TargetPath can be everything you want -->
<AspNetCompiler Updateable="true" VirtualPath="/CTH.Web" PhysicalPath="./" TargetPath="$(BuildDir)/CTH.Web" Force="true" Debug="false" />
</Target>
Remember that you have to include resource files, do any web.config replacements, etc. I really hope this helps.
The easiest way I found was to add a WebDeployment project to your solution.
http://www.microsoft.com/DOWNLOADS/details.aspx?FamilyID=0aa30ae8-c73b-4bdd-bb1b-fe697256c459&displaylang=en
You set the properties for the build in the WebDeployment project (like precompile ) . The Buildserver builds the wdprj.
In my environment I have to start by building the web first. After that I can start the wdprj.
Here is my nant - script. It should be easy to write the same in msbuild. It actually runs in TeamCity.
xml version="1.0"?>
<project name="GreatProjectWeb"
default="build" basedir="."
xmlns="http://nant.sf.net/release/0.85/nant.xsd">
<description>Build Script</description>
<!-- builds only the csproj, not the entire solution-->
<target name="build" description="Compile the project using Debug configuration for more verbose error descriptions">
<echo message="Building..."> </echo>
<exec program="C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe" >
<arg value="GreatProjectWeb\GreatProjectWeb.csproj" />
<arg value="/t:Build" />
<arg value="/p:Configuration=Release" />
</exec>
<echo message="Building Projektfile finished. Starting WDP Project..."> </echo>
<exec program="C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe" >
<arg value="GreatProjectWeb_Build\GreatProjectWeb_Build.wdproj" />
<arg value="/t:Build" />
<arg value="/p:Configuration=Release" />
</exec>
<exec program="7z" >
<arg value="a" />
<arg value="GreatProjectWeb_Deploy\web_GreatProject.zip" />
<arg value="GreatProjectWeb_Deploy\*" />
</exec>
</target>
</project>
You could use NAnt which has a "msbuild" task in it that will just do it for you. NAnt is a great way to go for CI builds.
The NAnt home page
The NAnt Contrib home page
The MSBuild task reference from NAnt Contrib
...the contrib library adds some great functionality that the vanilla NAnt doesn't have. It is very simple. I've included a snippet of my .build file here so you can see how I've used it:
<property name="DeployDestination" value="\\MyTestServerName\DestinationFolder"/>
<property name="Solution.Configuration" value="Debug" overwrite="True" />
<property name="nant.settings.currentframework" value="net-3.5" />
<if test="${WebContentDestination=='Production'}">
<property name="DeployDestination" value="\\MyProductionServer\DestinationFolder"/>
</if>
...<snip>
<target name="Build">
<msbuild project="SolutionFileName.sln">
<arg value="/p:Configuration=${Solution.Configuration}" />
</msbuild>
</target>
<target name="Deploy">
<copy todir="${DeployDestination}" flatten="true" >
<fileset>All files to copy</fileset>
</copy>
</target>

Resources