Getting rid of the `My` namespace - vb.net

I've been developing a Vb.Net app lately, and I'm trying to make it as lightweight as possible (ie make the binaries as small as possible).
I've done all the trivial stuff, but while browsing the binary with ILDasm, I noticed that it has a My namespace, with a lot of methods, although I don't use any of these in my program. It seems that there are default Get/Set methods for every form, and other methods.
Is there a way to get rid of those?
Or, can you show me a use case for the methods bundled by default in the binary?
PS: I guess it's not going to make a huge difference in binary size: I'm just asking this out of curiosity; why would the compiler bundle useless methods in every binaries? Perhaps I'll learn that these methods are actually used somewhere under the hood.
PPS: Here's a minimal example:
Module Test
Sub Main()
End Sub
End Module
The output is:

Follow these steps:
Click Show All Files in the solution explorer
Open the My Project branch
Open the Settings.settings branch
Open Settings.designer.vb
Edit the My namespace as you wish
There is an additional My sub-namespace called My.Resources which is hiding under the Resources.resx branch.

After furious head-scratching...:
How much is included depends on the value of the _MYTYPE define. It's all documented in MSDN, I failed to find it at first.

In order to remove most of the generated types in the My namespace you will have to set the _MYTYPE define to Empty. To do so you will have to open the .vbproj file in a text editor (using Visual Studio you can do this by first unloading the project and than open it).
Look for the element <MyType> in the first <PropertyGroup> and change its value to Empty:
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C6DC5A64-1E50-48B0-97A5-649D2D323E5E}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>Some.Component</RootNamespace>
<AssemblyName>Some.Component</AssemblyName>
<FileAlignment>512</FileAlignment>
<MyType>Empty</MyType>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
I have not found a way of removing the InternalXmlHelper that is generated by Visual Studio.
As Clément pointed out it is possible to configure the My namespace using other values of the _MYTYPE define.
This procedure will work for Visual Studio 2012.

Related

Include file to VS2017 c++ project by condition

I am trying to build the c/c++ project in VS2017
[https://git.postgresql.org/gitweb/?p=psqlodbc.git;a=blob;f=winbuild/psqlodbc.vcxproj;h=c54c93007c07c2b13bbea4ede14a6ee0e11fdf5a;hb=c54c93007c07c2b13bbea4ede14a6ee0e11fdf5a][1]
There are conditions in the project file
<ClCompile Include="$(srcPath)odbcapi30.c" />\r
<ClCompile Condition="'$(ANSI_VERSION)'=='no'" Include="$(srcPath)odbcapi30w.c" />\r
<ClCompile Condition="'$(ANSI_VERSION)'=='no'" Include="$(srcPath)odbcapiw.c" />\r
I have created
Unicode Debug/Release
ANSI Debug/Release
configurattions
and in the project properties->c\c++->Preprocessor I have added the ANSI_VERSION=no for Unicode and ANSI_VERSION=yes for ANSI.
But for any Platform/Configuration I see these files in the Solution Explorer and they are compiled by VS2017. How to include these files into project when condition is true only?
The condition requires that ANSI_VERSION is a MSBuild property. These are different from the C++ Preprocessor definitions (which are inputs used when compiling a file but not used by MSBUILD when testing for which files to compile - strictly speaking its used by the pre-processor but its part of the compile step from an msbuild point of view)
You can set the ANSI_VERSION as an MSBUILD property in your project file:-
For example:-
<PropertyGroup>
<ANSI_VERSION>no</ANSI_VERSION>
<ANSI_VERSION Condition="'$(Configuration)' == 'ANSI_DEBUG'">yes</ANSI_VERSION>
<ANSI_VERSION Condition="'$(Configuration)' == 'ANSI_RELEASE'">yes</ANSI_VERSION>
</PropertyGroup>
The above defaults ANSI_VERSION to no and overrides to yes when condition is met, but you could just as well test each possible configuration in turn instead if you prefer.
The conditions could also be combined into a single condition with an or if you prefer.
Personally I'd use true/false rather than yes/no. With true false you can just test the property as a Boolean rather than compare to string (although maybe this also works with yes/no - but I haven't tried that)
Edit in response to question:
The above conditionally excludes the files from the build, excluding them from the display is a little different as it would require the UI to re-parse the projects to update the list of files. You may find things works better for you to create a filter in the project for these files (i.e. right click on project in solution view and use Add->New Filter). Then conditionally use the ExcludeFromBuild setting to control which configurations actually compile them instead of making the CLCompile include conditional, something like:-
<ClCompile Include="SomeFile.cpp">
<ExcludedFromBuild Condition="'$(Configuration)'=='Debug'">true</ExcludedFromBuild>
</ClCompile>

Identifying a build as being due to a dependent project reference

In MSBuild is there a property, or some other mechanism, that indicates that the current project is being built because it was a referenced by another project?
After looking around a bit this does not seem possible using built-in functionaility. From one point of view this makes sense: why would a project have to know whether it's built directly by the user vs being built as a dependency? Possibly the MSBuild team followed that logic as well: there are quite a lot of extensions points in MSBuild but not for doing this.
Two problems: the code for building the dependent projects is just using the MSBuild Task and does not provide a way to pass properties. But even if it did, it would only work when building from the command line, not in VS, so it's not a 'complete' solution. Here's a snippet taken from the ResolveProjectReferences which builds the dependent projects:
<!--
Build referenced projects when building from the command line.
-->
<MSBuild
Projects="#(_MSBuildProjectReferenceExistent)"
Targets="%(_MSBuildProjectReferenceExistent.Targets)"
BuildInParallel="$(BuildInParallel)"
Properties="%(_MSBuildProjectReferenceExistent.SetConfiguration); %(_MSBuildProjectReferenceExistent.SetPlatform)"
Condition="'%(_MSBuildProjectReferenceExistent.BuildReference)' == 'true' and '#(ProjectReferenceWithConfiguration)' != '' and '$(BuildingInsideVisualStudio)' != 'true' and '$(BuildProjectReferences)' == 'true' and '#(_MSBuildProjectReferenceExistent)' != ''"
ContinueOnError="$(ContinueOnError)"
RemoveProperties="%(_MSBuildProjectReferenceExistent.GlobalPropertiesToRemove)">
...
</MSBuild>
So, no way to add properties here. Though as you figured you can remove properties by setting a ProjectReference's GlobalPropertiesToRemove; depending on what you're after this could be valueable.
For the rest there aren't many options left; you can specify the target used: _MSBuildProjectReferenceExistent.Targets gets set to $(ProjectReferenceBuildTargets) so you can override the target called but then you'd need all your projects which could possibly be dependent projects to declare a custom target (which would in turn call the Build target as well in order not to break things). Doable, but not nice, and not a direct answer to the question. Same goes for other solutions: you could just override the whole ResolveProjectReferences target (for any project which can have dependent projects) by copying it and adding a property in the snippet shown above.
But as said (and as shown in the Condition in the above snippet): none of these possible solutions would apply when building in VS. I don't know exactly why or how that works, but if A depends on B and you build A in VS and it sees B is out of date it just fires up a build for it before even building A and I don't know of any standard way to interact with that.
In addition to #stijn's answer, I've discovered that you can also prevent a property from being passed to dependent projects.
For example, you can prevent Web Project dependencies from building with the top level project by updating their <ProjectReference> to include <GlobalPropertiesToRemove>DeployOnBuild</GlobalPropertiesToRemove>. Or, to do it automatically based on another property:
<PropertyGroup Condition="'$(DisableProjectReferenceDeployOnBuild)'=='true'">
<BeforeResolveReferences>
$(BeforeResolveReferences);
DisableProjectReferenceDeployOnBuild
</BeforeResolveReferences>
</PropertyGroup>
<Target Name="DisableProjectReferenceDeployOnBuild">
<ItemGroup>
<_ProjectReferencesTmp Include="#(ProjectReferences)" />
<ProjectReferences Remove="#(ProjectReferences)" />
<ProjectReferences Include="#(_ProjectReferencesTmp)">
<GlobalPropertiesToRemove>%(GlobalPropertiesToRemove);DeployOnBuild</GlobalPropertiesToRemove>
</ProjectReferences>
</ItemGroup>
</Target>
(I won't mark this as the answer since it doesn't directly answer the question I asked)
With modern versions of visualstudio/.net SDK, you can do this in your Directory.Build.targets to apply this to all (as this requires participation from the project which is depending on other projects):
<?xml version="1.0"?>
<Project>
<PropertyGroup>
<IsBuildDueToProjectReference Condition=" '$(IsBuildDueToProjectReference)' == '' ">false</IsBuildDueToProjectReference>
</PropertyGroup>
<Target AfterTargets="AssignProjectConfiguration" Name="SetIsBuildDueToProjectReferenceOnProjectReferences">
<ItemGroup>
<ProjectReferenceWithConfiguration>
<AdditionalProperties>%(ProjectReferenceWithConfiguration.AdditionalProperties);IsBuildDueToProjectReference=true</AdditionalProperties>
</ProjectReferenceWithConfiguration>
</ItemGroup>
</Target>
</Project>
This works because targets build items from ProjectReferenceWithConfiguration. So you can treat that item as if it is passed as the Projects parameter of the MSBuild Task because its metadata will be carried along.
To see the effect, you can put something like the following in each of your project files:
<Target AfterTargets="Build" Name="PrintInfo">
<Warning Text="IsBuildDueToProjectReference=$(IsBuildDueToProjectReference)"/>
</Target>
For example, if I build ConsoleApp1.csproj which has a dependency on ClassLibrary1.csproj, I get:
C:\Users\ohnob\source\repos\ConsoleApp1\ClassLibrary1\ClassLibrary1.csproj(10,5): warning : IsBuildDueToProjectReference=true
C:\Users\ohnob\source\repos\ConsoleApp1\ConsoleApp1\ConsoleApp1.csproj(15,5): warning : IsBuildDueToProjectReference=false
And if I build ClassLibrary.csproj direct, I get:
C:\Users\ohnob\source\repos\ConsoleApp1\ClassLibrary1\ClassLibrary1.csproj(10,5): warning : IsBuildDueToProjectReference=false

Vb.net project reference libraries locations for different configuration

Related: Conditionally use 32/64 bit reference when building in Visual Studio
Normally when you add vb.net projects as reference in the same solution there is a reference added with a hint location. now in C# as far as i remember it adds it based on architecture. Why not in Vb.net or am i just doing it wrong. Check the related question.
<Reference Include="MyComAssembly.Interop">
<HintPath>..\..\lib\x86\MyComAssembly.Interop.dll</HintPath>
</Reference>
<ItemGroup Condition=" '$(Platform)' == 'x64' ">
<Reference Include="MyComAssembly.Interop">
<HintPath>..\..\lib\x64\MyComAssembly.Interop.dll</HintPath>
</Reference>
To clarify i do get the entry but its not architecture based by default. The related question does talk about manually editing the file but I am trying to understand why its not happening automatically for VB.net compared to C#. Is there any open feature request as well.
Edit on 6/6/2017
for Vb.net it shows the references correctly as explained in first response, but why doesn't a COM reference work in the same way.
I am posting this as answer, because I need to show some code here
You said:
Normally when you add vb.net projects as reference in the same solution there is a reference added with a hint location
Answer:
No. Project reference is created as following
<ProjectReference Include="..\..\..\MyProject\MyProject.csproj">
<Project>{7316c328-7716-4b5c-b736-f5811c764158}</Project>
<Name>MyProject</Name>
</ProjectReference>
Your XML shows DLL reference. If you reference from DLL, you get the hint.
And the ItemGroupcondition is not added by default, not in C#, not in VB. This is something you do manually. I am telling you this as build master who constantly configures projects and solutions.

Default or specify msbuild properties in an external file

Ok, so I have a few dozen solutions all built using the exact same command line.
msbuild SolutionName.sln /p:property1=value1;property2=value2;etc etc etc.
Except the number of properties just grows and grows.
Is there a way to specify an external file some how so I don't end up with a 10 line msbuild command? (Think property 100, property 101, etc).
I'm aware of .wpp.target files. However, having to copy them into each project folder really... is my last resort.
And no, I'm not modifying any default MSBuild targets/files whatsoever.
To answer the original question, yes you can specify properties in an external file. They are called MSBuild response files.
msbuild somesolution.sln #PathToResponseFile.rsp
Inside the response file you can put your properties, one per line.
/verbosity:detailed
/target:build
/platform:AnyCPU
/configuration=Release
Some links to better understand:
http://dailytechlearnings.wordpress.com/2011/08/24/msbuild-response-file/
http://msdn.microsoft.com/en-us/library/vstudio/ms404301.aspx
However, using an msbuild file to build your solutions and projects is a better solution. You can create global targets that will do exactly as you want. You can create your own custom Clean and Build targets that will then build/clean your solutions.
First of all - I would recommend you to use msbuild scripts to build your solutions, instead of direct building sln file using command line. E.g. use something like this:
msbuild SolutionName.Build.proj
and inside this Solution1.Build.proj you can put anything as simple as
<Project ToolsVersion="4.0" DefaultTargets="BuildMe" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="BuildMe">
<MSBuild Projects="SolutionName.sln" Properties="property1=value1;property2=value2;"/>
</Target>
</Project>
After this step, which adds flexibility to your build process, you can start leverage AdditionalProperties metadata for MSBuild task.
Then you can use <Import construction to store your list of shared properties in a separate file and item metadata for passing property values:
<Project ToolsVersion="4.0" DefaultTargets="BuildMe" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="MySharedProperies.props" />
<ItemGroup>
<ProjectToBuild Include="SolutionName.sln">
<AdditionalProperties>SomeProjectSpecificProperty</AdditionalProperties>
</ProjectToBuild>
</ItemGroup>
<Target Name="BuildMe">
<MSBuild Projects="#(ProjectToBuild)" Properties="#(MySharedProperies)"/>
</Target>
</Project>
You can check this post for more details about properties and additional properties metadata or this original MSDN reference (scroll to Properties Metadata section)
This is the base idea how to do it, if you have any questions - feel free to ask.
I use an Import file for things that are common across various projects.
<Import Project="CommonBuildProperties.proj"/>
That file contains a PropertyGroup that has the things I want to have the same value across build projects. There's also a conditional statement there that sets certain folder names depending on the name of the computer it's running on. At runtime, if I need to override anything on the command line I do that.
I also have some project-specific Import files (one of our builds is a Powerbuilder application with its own toolset and pecadilloes); order of Import ensures if they require different values for the same element name I get what I want.
My command lines aren't horrible unless I'm doing something odd that needs most everything overridden. About the only things I have to pass in are version number and build type (release or debug).

CreateItem vs ItemGroup

What is the difference between creating an item inside a target like this:
<Target Name="DoStuff">
<CreateItem Include="#(IntermediateAssembly)" >
<Output TaskParameter="Include" ItemName="FileWrites"/>
</CreateItem>
</Target>
and like this:
<Target Name="DoStuff">
<ItemGroup>
<FileWrites Include="#(IntermediateAssembly)" />
</ItemGroup>
</Target>
When would you use one or the other and why?
In versions of MSBuild prior to 3.5 you could not define properties or items inside of targets (like in your second example). So a task was used instead (CreateItem and CreateProperty)
If you are using ToolsVersion 3.5 then you don't need to use CreateItem anymore (though you still can if you prefer).
In the end they both create the item the same, with the same scope. Using the second syntax is more readable and setting up custom meta data is much easier (in my opinion).
NOTE: The 3.5 version of MSBuild is installed with .NET 3.5. Though you need to define ToolsVersion="3.5" in the Project tag of your MSBuild file to use 3.5 features.
In case you are wondering, I got most of this info from the book Inside the Microsoft® Build Engine: Using MSBuild and Team Foundation Build which I really liked (but am not affiliated with in any way).
CreateItem and CreateProperty are obsoleted in MSBuild 3.5 (though will always continue to work, of course). It was pretty obvious we needed the same familiar syntax for ItemGroup and PropertyGroup to work inside targets.
But ItemGroup inside a target has some special extra powers. It can modify items: for example, this will add true to all items in Resources list that have a metadata named Primary with value of true; only if there isn't already Copy metadata:
<ItemGroup>
<Resources Condition=" '%(Primary)' == 'true' ">
<Copy Condition=" '%(Copy)' == '' ">true</Copy>
</Resources>
</ItemGroup>
One other magic power: you can now remove items from a list. This example will remove all items from the Resources list that have metadata Type with value Bitmap:
<ItemGroup>
<Resources Condition=" '%(Type)'=='Bitmap' " Remove="#(Resources)"/>
</ItemGroup>
These magic powers only work inside at present, not outside.
For full details of this stuff, I highly recommend Sayed Hashimi's book on MSBuild. It's easily found on Amazon.
Dan -- msbuild team.
I dont think the answer accepted has defined the difference.
The difference is:
ItemGroup is evaluated when the MSBuild script is loaded.
CreateItem is evaluated when the Target is executed
This can lead to different values of the Item within the script.
Take the example of a Task that does something with a all the files that match "*.txt" in a directory. If your MSBuild script is loaded in visual studio, only the files that existed when VS started will be in the Item if you use ItemGroup.
If you use CreateItem - it will do a search for all *.txt files when the target is executed.
As an additional info for others passing here: The Build-Engine that contains an API to construct MSBuild projects does not support adding ItemGroups the new way to a Target. Here you WILL have to use the old-fashioned way.