Command Line Compiling Settings.settings using VBC - vb.net

To an earlier question of mine, invovling VBC and NAnt with WinForms, I have since come up with a better way of stating this.
Within vbproj file, you have the following:
<ItemGroup>
<None Include="My Project\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<CustomToolNamespace>My</CustomToolNamespace>
<LastGenOutput>Settings.Designer.vb</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<Content Include="My Project\Application.myapp">
<Generator>MyApplicationCodeGenerator</Generator>
<LastGenOutput>Application.Designer.vb</LastGenOutput>
</Content>
</ItemGroup>
When one runs build from within Visual Studio (Debug Verbosity set to Normal), one of the lines produces is:
Target CoreCompile:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Vbc.exe ...
Which includes all of the settings required for vbc.exe to run. However, taking that string from Visual Studio, and running it directly on the command line yields:
... My Project\Settings.Designer.vb(67) : error BC30002: Type 'My.MySettings' is not defined.
Friend ReadOnly Property Settings() As Global.My.MySettings
...\My Project\Settings.Designer.vb(69) : error BC30456: 'My' is not a member of '<Default>'.
Return Global.My.MySettings.Default
How does one get the above Generators to run from a command line, or is there a call somewhere that will generate the correct temp files that are needed for vbc.exe to run the command string correctly?

The problem with looking at the build string within visual studio is that it's not actually calling vbc.exe to build from visual studio. All builds in visual studio happen with the in-memory compiler instead of the command line compiler (true for C# as well).
The command that looks like vbc.exe ... is a generated string that isn't actually executed. If you want to find out the correct string to build your project run the following code from a visual studio command prompt.
msbuild /v:diag myproject.vbproj
This will produce an msbuild log file (it will be quite long so I suggest piping to a file). Once the build is completed search for vbc.exe within that file. It will have the actual command line needed to build your project.

I spent a while working on this today. I'd like to know a proper answer as to how to get the vbc compiler to work properly in regard to the "My" namespace, but I managed to get my NAnt script working using NAnt contrib (http://nantcontrib.sourceforge.net/).
NAnt contrib allows you to build using the .NET msbuild, which at least allowed me to set up automated builds, notifications, etc. It does not give quite the granular control I would like, but it serves its purpose.
The reference on this task is:
http://nantcontrib.sourceforge.net/release/latest/help/tasks/msbuild.html
And the pertinent snippet from my build script:
<target name="build" depends="clean">
<msbuild project="ProjectName.vbproj" />
</target>
I've used NAnt quite a bit for CS applications, but this is the first for a VB.NET application.

Related

MSBuild - Execute Custom Targets w/o modifying individual projects

I have custom MSBuild Tasks to execute after the : AfterBuild event for each project in a solution.
I don't want to modify each Project file as:
Visual Studio wipes out all the Custom Changes done to the project file once i modify the project in Visual Studio (VS 2012 Ultimate), say add or remove a file/reference.
I don't want to use "CustomAfterMicrosoftCommonTargets" as mentioned here as there is no way to pass this command line argument while building from Visual Studio :
msbuild.exe app.proj /property:CustomAfterMicrosoftCommonTargets=custom.target
I found a solution here, but I didn't quite get it.
Can anybody please elaborate on it or help me figure out a better solution?
Update 5/12/2014:
I figured out that Visual Studio doesn't wipe out the custom changes if I am running the Visual Studio in the Administrator mode.
I can now think of having a Custom import file that has got the required overrides, but still I have to do this for each project in the solution. If somebody adds a new project, they have to remember to add this customization. I don't like this, but probably I can live with for now.
I tried to use the "CustomAfterMicrosoftCommonTargets" approach, but I was not able to set this property from the Pre-build event of Visual Studio, even running as Administrator didn't help.
I was trying to set an environment variable with same name from the Pre-Build event, but I never got the new value while MSBuild executes.
Thanks!
Finally I found an option where in I don't have to edit the individual project file.
The idea is to invoke your custom common targets file in the "AfterBuild" event that Visual Studio exposes.
IF "$(BuildingInsideVisualStudio)"=="true" (
$(MSBuildBinPath)\msbuild.exe "$(ProjectDir)CustomMSBuild.targets" /p:Configuration="$(Configuration)"/property:"ProjectUnderCompilation=$(MSBuildThisFileDirectory)$(MSBuildThisFile)"
)
So I am passing the project under compilation as a property and import that project file.
If I throw an exception in the custom task, it appears as as Compilation error on the parent project.
This worked amazingly and I am able to perform any validations on the project that was passed.
The only downside I see is that I am spawning another MSBuild.exe and I don't see any impact of that in the compilation time as of now.
Please let me know your thoughts on this implementation.
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="MyTarget">
<UsingTask AssemblyFile="$(ProjectDir)\bin\TaskLibrary.dll" TaskName="CheckProjectReferences" />
<PropertyGroup>
<ProjectUnderCompilation></ProjectUnderCompilation>
</PropertyGroup>
<Target Name="MyTarget">
<Message Text="Inside MyTarget" Importance="High" />
<CheckProjectReferences/>
</Target>
<Import Project="$(ProjectUnderCompilation)" />
</Project>

In MSBUILD, how can you specify a condition that check whether command line or VS launched it?

I have a csproj that I would like to have trigger the opening of a particular file in Visual Studio, only if the target was executed from within Visual Studio, but not from the MSBUILD command line. How do I do this?
Quote from MSDN page:
When building inside Visual Studio, the property $(BuildingInsideVisualStudio) is set to true. This can be used in your project or .targets files to cause the build to behave differently.
Example how it could be used in your .*proj or .targets file:
<PropertyGroup>
<MyProperty Condition="'$(BuildingInsideVisualStudio)' == 'true'">This build is done by VS</MyProperty>
<MyProperty Condition="'$(BuildingInsideVisualStudio)' != 'true'">This build is done from command line of by TFS</MyProperty>
</PropertyGroup>
Add a property to the .csproj project file, example:
<PropertyGroup>
<FromMSBuild>false</FromMSBuild>
</PropertyGroup>
Then in the task you want to run, put a condition that evaluates that property. For example, i f you want to open notepad.exe whenever the build is executed from command line and NOT visual studio:
<Target Name="BeforeBuild">
<Exec Command="C:\Windows\Notepad.exe" Condition="$(FromMSBuild)" />
</Target>
Of course, this is dependent on setting the $(FromMSBuild) property correctly when you run the build via command line, like so:
MSBuild myProject.csproj /p:FromMSBuild=true
If I understand you correctly, you want to open a file when building in visual studio but not from command line with MSBuild?
If that is the case, specify a PreBuild or PostBuild in Visual Studio.
Right click on the project in the solution explorer and select Properties
Select the Events tab
Add either a Pre or Post Build event to open the desired file

Using a project file as a parameter in MSBuild with Hudson

I'm currently using the Hudson build system with MSBuild steps. As part of the build, I have a project file with various targets in, one of which is to start a build with visual studio. However, I need to pass through a seperate project file to this target in order for it to build, but I keep getting the exception 'MSBUILD : error MSB1008: Only one project can be specified.'
I believe this is because the system is unable to calculate which project is supposed to be the parameter, and which the top-level target? If so, is there anyway to resolve this.
Here is a snippet of the target project file:
<Target Name="VisualStudioTask">
<!-- Required Properties:
$(BuildType)
$(ConfigurationSetup)
$(Solution)-->
<Exec Command="C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.exe $(BuildType) $(ConfigurationSetup) $(Solution)" />
</Target>
The MSBuild step calling this looks like this:
/t:VisualStudioTask -p:BuildType="/Build" p:ConfigurationSetup="Release" -p:Solution="%22..\MyProject.vcproj%22"
Many thanks
Chris
I have figured it out, the problem was that I'd left out a '-' when declaring the 'ConfigurationSetup' parameter, so if you look in my original example it has this:
/t:VisualStudioTask -p:BuildType="/Build" p:ConfigurationSetup="Release" -p:Solution="%22..\MyProject.vcproj%22"
When it should have this..
/t:VisualStudioTask -p:BuildType="/Build" -p:ConfigurationSetup="Release" -p:Solution="%22..\MyProject.vcproj%22"

How do I specify the platform for MSBuild?

I am trying to use MSBuild to build a solution with a specified target platform (I need both binaries, x86 and x64). This is how I tried it:
C:\WINDOWS\Microsoft.NET\Framework\v3.5>MsBuild SolutionPath\Solution.sln /t:Rebuild /p:Configuration=Release /p:Platform="x86"
However the build always fails if the platform is different from "Any CPU". What am I doing wrong?
This is the while output MSBuild prints:
C:\WINDOWS\Microsoft.NET\Framework\v3.5>MsBuild
SolutionPath\Solution.sln /t:Rebuild
/p:Configuration=Release
/p:Platform="x86" Microsoft (R) Build
Engine Version 3.5.30729.1 [Microsoft
.NET Framework, Version
2.0.50727.3082] Copyright (C) Microsoft Corporation 2007. All rights
reserved.
Build started 1.7.2010 8:28:10.
Project "SolutionPath\Solution.sln" on
node 0 (Rebuild targe t(s)).
SolutionPath\Solution.sln : error
MSB4126: The specified sol ution
configuration "Release|x86" is
invalid. Please specify a valid
solution c onfiguration using the
Configuration and Platform properties
(e.g. MSBuild.exe Solution.sln
/p:Configuration=Debug
/p:Platform="Any CPU") or leave those
prope rties blank to use the default
solution configuration. Done Building
Project "SolutionPath\Solution.sln"
(Rebuild t arget(s)) -- FAILED.
Build FAILED.
"SolutionPath\Solution.sln" (Rebuild
target) (1) ->
(ValidateSolutionConfiguration target)
-> SolutionPath\Solution.sln : error MSB4126: The specified s olution
configuration "Release|x86" is
invalid. Please specify a valid
solution configuration using the
Configuration and Platform properties
(e.g. MSBuild.ex e Solution.sln
/p:Configuration=Debug
/p:Platform="Any CPU") or leave those
pro perties blank to use the default
solution configuration.
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:00.03
If I try to build it for x86/x64 with devenv it works perfectly, however I am trying to set up a build server without installing all the necessary versions of Visual Studio. By the way, if there is a better free tool (that supports .NET framework 4) out there, I'd love to hear about it.
In MSBuild or Teamcity use command line
MSBuild yourproject.sln /property:Configuration=Release /property:Platform=x64
or use shorter form:
MSBuild yourproject.sln /p:Configuration=Release /p:Platform=x64
However you need to set up platform in your project anyway, see the answer by Julien Hoarau.
If you want to build your solution for x86 and x64, your solution must be configured for both platforms. Actually you just have an Any CPU configuration.
How to check the available configuration for a project
To check the available configuration for a given project, open the project file (*.csproj for example) and look for a PropertyGroup with the right Condition.
If you want to build in Release mode for x86, you must have something like this in your project file:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
...
</PropertyGroup>
How to create and edit the configuration in Visual Studio
(source: microsoft.com)
(source: msdn.com)
(source: msdn.com)
How to create and edit the configuration (on MSDN)
If you're trying to do this from the command line, you may be encountering an issue where a machine-wide environment variable 'Platform' is being set for you and working against you. I can reproduce this if I use the VS2012 Command window instead of a regular windows Command window.
At the command prompt type:
set platform
In a VS2012 Command window, I have a value of 'X64' preset. That seems to interfere with whatever is in my solution file.
In a regular Command window, the 'set' command results in a "variable not defined" message...which is good.
If the result of your 'set' command above returns no environment variable value, you should be good to go.
Hopefully this helps someone out there.
For platform I was specifying "Any CPU", changed it to "AnyCPU" and that fixed the problem.
msbuild C:\Users\Project\Project.publishproj /p:Platform="AnyCPU" /p:DeployOnBuild=true /p:PublishProfile=local /p:Configuration=Debug
If you look at your .csproj file you'll see the correct platform name to use.
For VS2017 and 2019... with the modern core library SDK project files, the platform can be changed during the build process. Here's an example to change to the anycpu platform, just before the built-in CoreCompile task runs:
<Project Sdk="Microsoft.NET.Sdk" >
<Target Name="SwitchToAnyCpu" BeforeTargets="CoreCompile" >
<Message Text="Current Platform=$(Platform)" />
<Message Text="Current PlatformTarget=$(PlatformName)" />
<PropertyGroup>
<Platform>anycpu</Platform>
<PlatformTarget>anycpu</PlatformTarget>
</PropertyGroup>
<Message Text="New Platform=$(Platform)" />
<Message Text="New PlatformTarget=$(PlatformTarget)" />
</Target>
</Project>
In my case, I'm building an FPGA with BeforeTargets and AfterTargets tasks, but compiling a C# app in the main CoreCompile. (partly as I may want some sort of command-line app, and partly because I could not figure out how to omit or override CoreCompile)
To build for multiple, concurrent binaries such as x86 and x64: either a separate, manual build task would be needed or two separate project files with the respective <PlatformTarget>x86</PlatformTarget> and <PlatformTarget>x64</PlatformTarget> settings in the example, above.
When you define different build configurations in your visual studio solution for your projects using a tool like ConfigurationTransform, you may want your Teamcity build, to build you a specified build configuration. You may have build configurations e.g., Debug, Release, Dev, UAT, Prod etc defined. This means, you will have MSBuild Configuration transformation setup for the different configurations. These different configurations are usually used when you have different configurations, e.g. different database connection strings, for the different environment. This is very common because you would have a different database for your production environment from your playground development environment.
They say a picture is worth a thousand words, please see the image below how you would specify multiple build configurations in Teamcity.
In the commandline input text box, specify as below
/p:OutputPath=Publish;Configuration=Dev
Here, I have specified two commandline build configurations/arguments OutputPath and build Configuration with values Publish and Dev respectively, but it could have been, UAT or Prod configuration. If you want more, simply separate them by semi-colon,;
There is an odd case I got in VS2017, about the space between ‘Any’ and 'CPU'.
this is not about using command prompt.
If you have a build project file, which could call other solution files. You can try to add the space between Any and CPU, like this (the Platform property value):
<MSBuild Projects="#(SolutionToBuild2)" Properties ="Configuration=$(ProjectConfiguration);Platform=Any CPU;Rerun=$(MsBuildReRun);" />
Before I fix this build issue, it is like this (ProjectPlatform is a global variable, was set to 'AnyCPU'):
<MSBuild Projects="#(SolutionToBuild1)" Properties ="Configuration=$(ProjectConfiguration);Platform=$(ProjectPlatform);Rerun=$(MsBuildReRun);" />
Also, we have a lot projects being called using $ (ProjectPlatform), which is 'AnyCPU' and work fine. If we open proj file, we can see lines liket this and it make sense.
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
So my conclusion is,
'AnyCPU' works for calling project files, but not for calling solution files,
for calling solution files, using 'Any CPU' (add the space.)
For now, I am not sure if it is a bug of VS project file or MSBuild.
I am using VS2017 with VS2017 build tools installed.
In Visual Studio 2019, version 16.8.4, you can just add
<Prefer32Bit>false</Prefer32Bit>

Is there a way not to let MsBuild run static contract analysis with code contracts?

In my project, static checking is disabled, but still, when I run msbuild.exe with cmd, it starts static checking for each project... Is there a way, with parameters, to disable this?
This might be a 'little' late, but since I just encountered the same problem and /p:RunCodeAnalysis=false doesn't work for me:
Try msbuild ... /p:CodeContractsRunCodeAnalysis=false.
That works as of Feb. 2011 according to the code contracts documentation and my experience.
The following should do it:
MSBuild ... /p:RunCodeAnalysis=false
If you don't want to pass parameters to msbuild or you are building from Visual Studio, there is a way to suppress static code contracts check and code analysis.
Notice: each *.csproj file contains this: <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />.
For .Net 4.0 msbuild.exe and Microsoft.CSharp.targets path is "C:\Windows\Microsoft.NET\Framework\v4.0.30319\"
Open Microsoft.CSharp.targets
Add new PropertyGroup inside Project like:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<PropertyGroup>
<CodeContractsRunCodeAnalysis>false</CodeContractsRunCodeAnalysis>
<RunCodeAnalysis>Never</RunCodeAnalysis>
<CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
</PropertyGroup>
...
<!-- a lot of stuff -->
...
</Project>
Doing so will emulate msbuild command line arguments (i.e /p:CodeContractsRunCodeAnalysis=false,RunCodeAnalysis=Never,CodeContractsReferenceAssembly=DoNotBuild
All your builds now on your pc (either from MSBuild and Visual Studio) will skip code and static code contracts analysis, so you don't need to pass args from Command Line.