Category Archives: MSBUILD

MSBuild notes

To examine what types of values the well-known metadata returns, take a look at the example below:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <PrjFile Include="Helloworld.proj" />
  </ItemGroup>
  <Target Name="Well known metadata">
    <Message Text="%40(PrjFile->'%25(Fullpath)'):@(PrjFile->'%(Fullpath)')"/>
    <Message Text="%40(PrjFile->'%25(Rootdir)'):@(PrjFile->'%(Rootdir)')"/>
    <Message Text="%40(PrjFile->'%25(Filename)'):@(PrjFile->'%(Filename)')"/>
    <Message Text="%40(PrjFile->'%25(Extension)'):@(PrjFile->'%(Extension)')"/>
    <Message Text="%40(PrjFile->'%25(RelativeDir)'):@(PrjFile->'%(RelativeDir)')"/>
    <Message Text="%40(PrjFile->'%25(Directory)'):@(PrjFile->'%(Directory)')"/>
    <Message Text="%40(PrjFile->'%25(RecursiveDir)'):@(PrjFile->'%(RecursiveDir)')"/>
    <Message Text="%40(PrjFile->'%25(Identity)'):@(PrjFile->'%(Identity)')"/>
    <Message Text="%40(PrjFile->'%25(ModifiedTime)'):@(PrjFile->'%(ModifiedTime)')"/>
    <Message Text="%40(PrjFile->'%25(CreatedTime)'):@(PrjFile->'%(CreatedTime)')"/>
    <Message Text="%40(PrjFile->'%25(AccessedTime)'):@(PrjFile->'%(AccessedTime)')"/>
  </Target>
</Project>
Share

Add “After build” event in project file Visual Studio

After build events can be added to the property page of a visual studio project. You can also add your own “targets” file to the afterbuild (or beforebuild) in the project file itself. Use the following method:

  1. Add a targets file to your project with the following contents (for example)
    <?xml version="1.0" encoding="utf-8" ?>
    <Project DefaultTargets="WSPBuild"
       xmlns=http://schemas.microsoft.com/developer/msbuild/2003>
       <PropertyGroup>
          <WSPBuilderPath>"....ToolsWSPBuilder.exe"</WSPBuilderPath>
       </PropertyGroup>
       <Target Name="WSPBuild">
          <Exec Command="cd $(ProjectDir)" Outputs="null" />
          <Message Text="Executing WSP Builder in directory $(ProjectDir)"/>
          <Exec Command="$(WSPBuilderPath) "/>
       </Target>
    </Project>
    
  2. Unload the project file
  3. Right click the project file and choose Edit…..
  4. Add an import tag below the last import tag in the projectfile:
    <Import Project="wspbuilder.Targets" />
    
  5. Uncomment the AfterBuild tag and add the following statements; remember to specify the adjust CallTarget!
    <Target Name="AfterBuild">    
         <CallTarget Targets="BuildSharePointPackage" />
    </Target> 
    
Share

AssemblyInfoTask will fail with duplicate entries in AssemblyInfo.cs

AssemblyVersionIncrementer will fail when entries in the AssemblyInfo.cs are not unique. For example:

#if debug    
 AssemblyInfoDescription("Debug mode")
#else
  AssemblyInfoDescription("Release mode") 
#endif 

The version incrementer will read the AssemblyInfo.cs and tries to store the entries in an internal Hashtable. This fails because of the multiple “AssembyInfoDescription” (line 2 and 4) entries (the preprocessor directives are ignored).

Exception text in build log:

Task “AssemblyInfo”
C:Program FilesMSBuildRdwDefaultBuildReleaseAssemblyInfoTaskMicrosoft.VersionNumber.Targets.Test(92,5):
error MSB4018: The “AssemblyInfo” task failed unexpectedly.
error MSB4018: System.ArgumentException: An item with the same key has already been added.
error MSB4018: at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
error MSB4018: at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
error MSB4018: at Microsoft.Build.Extras.AssemblyInfoWrapper..ctor(String filename)
error MSB4018: at Microsoft.Build.Extras.AssemblyInfo.Execute()
error MSB4018: at Microsoft.Build.BuildEngine.TaskEngine.ExecuteInstantiatedTask(EngineProxy engineProxy, ItemBucket bucket, TaskExecutionMode howToExecuteTask, ITask task, Boolean& taskResult)

Share

CreateItem in MSBuild

<!-- Signing step -->
<Target Name="MSISigningStep">

<!-- Select all MSI in the $(OutDir) for signing -->
<CreateItem Include="$(OutDir)***.msi">
<Output ItemName="MSIFilesToSign" TaskParameter="Include" />
</CreateItem>

<Message Text="No MSI files found for signing."
Condition="'@(MSIFilesToSing)' == '' "/>

<!-- Execute the sign command if any files found -->
<Exec
Command=""C:Program FilesMicrosoft SDKsWindowsv6.0Abinsigntool.exe"" +
"sign "%(MSIFilesToSign.Fullpath)""
Condition="'@(MSIFilesToSing)' != '' "/>

</Target>
Share