Wednesday, May 25, 2011

MSBuild Building multiple Configurations and Platforms at the same time

Here is a MSBuild project file that allows you to specify multiple configurations and platforms. The advantage of this approach is that you get a single report with all the build results.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Rebuild" ToolsVersion="4.0">
<ItemGroup>
<ConfigurationList Condition=" '@(ConfigurationList)' == '' and $(Configuration) != '' " Include="$(Configuration.Split(';'))" />
<ConfigurationList Condition=" '@(ConfigurationList)' == '' " Include="Debug" />
<PlatformList Condition=" '@(PlatformList)' == '' and $(Platform) != '' " Include="$(Platform.Split(';'))" />
<PlatformList Condition=" '@(PlatformList)' == '' " Include="Xbox 360" />
<TargetList Condition=" '@(TargetList)' == '' and $(Targets) != '' " Include="$(Targets.Split(';'))" />
<TargetList Condition=" '@(TargetList)' == '' " Include="Rebuild" />
<ProjectList Condition=" '@(ProjectList)' == '' and $(Projects) != '' " Include="$(Projects.Split(';'))" />
<ProjectList Condition=" '@(ProjectList)' == '' " Include="$(MSBuildProjectDirectory)\Test.sln" />
ItemGroup>
<Target Name="Rebuild" Outputs="%(PlatformList.Identity)">
<PropertyGroup>
<CurrentPlatform>%(PlatformList.Identity)CurrentPlatform>
PropertyGroup>
<MSBuild Projects="@(ProjectList)"
Properties="Configuration=%(ConfigurationList.Identity);Platform=$(CurrentPlatform);"
Targets="@(TargetList)"
SkipNonexistentProjects="true"
/>
Target>
Project>

usage:
msbuild BuildProject.proj /p:Projects="ProjA;ProjB" /p:Configuration="Debug;Release" /p:Platform="XBox 360;Win32;x86" /p:Targets="target"
examples:
msbuild BuildProject.proj
-- this will rebuild default solution for Debug|Xbox 360

msbuild BuildProject.proj /p:Projects="Test2.sln;Test1.sln" ^
/p:Configuration="Debug;Release" ^
/p:Platform="XBox 360;Win32;x86" ^
/p:Targets="clean;build"
-- this will build everything

Using Custom section in app.config for Visual Studio 2010

Sample app.config:
<configuration>
<configSections>
<sectionGroup name="machineSettings">
<section name="apple" type="System.Configuration.NameValueSectionHandler"/>
</sectionGroup>
</configSections>

<appSettings>
<add key="TestMode" value="false" />
<add key="sdpBatPath" value="e:\sdpack\sdp.bat" />
</appSettings>

<machineSettings>
<apple>
<add key="myKeyA" value="AAA"/>
<add key="myKeyB" value="BBB"/>
</apple>
</machineSettings>

Code:
// NOTE: this is a case sensitive lookup
NameValueCollection userConfig = ConfigurationManager.GetSection("machineSettings/" + System.Environment.MachineName.ToLower()) as NameValueCollection;


Trouble Shooting:

Could not find schema information for the attribute 'key'
This message can be resolved by changing the schema for the app.config:

  • Open Properties window
  • Open app.config in Visual Studio
  • Goto Properties window
  • Select Schemas
  • Edit the Schemas
  • Choose /add a new schema
  • In my chase adding DotNetConfig20.xsd worked.

Monday, May 9, 2011

Using Linq to filter SQL based on Lists (or arrays)

Here is handy way of filtering your results based on passed in lists, which can be null.

The key is to handle the empty list case in the where clause using list.Count == 0 || . This will allow you to generate the appropriate query

public List GetData(List Numbers, List Letters)
{
if (Numbers == null)
Numbers = new List();

if (Letters == null)
Letters = new List();

var q = from d in database.table
where (Numbers.Count == 0 || Numbers.Contains(d.Number))
where (Letters.Count == 0 || Letters.Contains(d.Letter))
select new Data
{
Number = d.Number,
Letter = d.Letter,
};
return q.ToList();

}