Category Archives: MSBUILD

MSBuild notes

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

[sourcecode language=”xml”]
<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>
[/sourcecode]

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)
    [sourcecode language=”html”]
    <?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>
    [/sourcecode]
  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:
    [sourcecode language=”html”]
    <Import Project="wspbuilder.Targets" />
    [/sourcecode]
  5. Uncomment the AfterBuild tag and add the following statements; remember to specify the adjust CallTarget!
    [sourcecode language=”html”]
    <Target Name="AfterBuild">
    <CallTarget Targets="BuildSharePointPackage" />
    </Target>
    [/sourcecode]
Share

AssemblyInfoTask will fail with duplicate entries in AssemblyInfo.cs

AssemblyVersionIncrementer will fail when entries in the AssemblyInfo.cs are not unique. For example:
[sourcecode language=”csharp”]
#if debug
AssemblyInfoDescription("Debug mode")
#else
AssemblyInfoDescription("Release mode")
#endif
[/sourcecode]
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

[sourcecode language=”html”]
<!– 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=”&quot;C:Program FilesMicrosoft SDKsWindowsv6.0Abinsigntool.exe&quot;” +
“sign &quot;%(MSIFilesToSign.Fullpath)&quot;”
Condition=”‘@(MSIFilesToSing)’ != ” “/>

</Target>
[/sourcecode]

Share