MS Build – Publish to FileSystem

I’m working for a simple project and wanted to deploy it to the webserver in my church. I installed TeamCity and set it up to pull the source code from github and build it.

The challenge was, unexpectedly, publish. Initially, I used MS Web Deploy. For some reason I couldn’t figure out, it didn’t work. Also, I had to install an extra service. So I went for a simple msbuild file system deploy.


msbuild .\WebDrive.csproj /t:Package
    /p:_PackageTempDir="\\webserver\output" /p:Configuration="Release"

On TeamCity, I added an additional build step and configure it like these

  • Runner type: MSBuild
  • Build file path: WebDrive/WebDriveWeb.csproj
  • Targets: Clean;Build;Publish
  • Command line parameters: /t:Package /p:_PackageTempDir=”\\web\output” /p:Configuration=”Release”

Much simpler that web deployment.

MS Build – Publish to FileSystem

error CS0227: Unsafe code may only appear if compiling with /unsafe

This is the error message you get, when you build a project with some bit of unsafe code in it.

Simply you need to “Alt + Enter” on the project to see the properties and tick on “Allow unsafe code” on build tab. Then it compiles lovely in visual studio.

However, I came across the error message again in the build. with MSBuiild, I got the message. It’s still ticked on the project’s property page. What’s wrong? …

The culprit was build type. In VS, you usually set the build type to DEBUG. so the Allow unsafe code option is turned on against debug, not release. So, open the project file in a simple text editor. I used Sublime text 2. Make sure the option exists in both debug and release.

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>..\..\bin\Penge\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>
error CS0227: Unsafe code may only appear if compiling with /unsafe

MSBUild task: Get the latest code from TFS and build

Resource

This is a simple task, but it took some time for me to udnerstand, as MSBuild was a new thing to me.
First, Get the latest code from TFS is TFS task, not MSBUild task. So, you can use tf.exe command-line utility.

"C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\tf.exe" get $/root/MSBUILD/Team/Sapphire /force /recursive

the batch file is like this

"C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\tf.exe" get $/root/OccupyingSpace/GoYocal /force /recursive
"C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe" "C:\TEMP\Test_GoYocalBuild.proj" /t:Clean;Test
pause

You need SDC taks in order to build .sln file. Please download it from codeplex. I created a simple proj file that builds .sln file

<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets" />
    <Import Project="C:\vss\root\MSBUILD\bin\Microsoft.Sdc.Common.tasks"/>
    <Target Name="Test" >
        <Tools.DevEnv
            VisualStudio="9.0"
            Path="C:\VSS\root\OccupyingSpace\GoYocal\GoYocal.sln"
            Config="Release"
            OutputFolder="C:\VSS\root\OccupyingSpace\GoYocal\src\app\bin"
            Clean="true">
        </Tools.DevEnv>
    </Target>

    <PropertyGroup>
        <TFSServerName>http://rbi101:8080</TFSServerName>
        <SourceControlMainDirectory>$/root/OccupyingSpace/GoYocal</SourceControlMainDirectory>
        <WorkspaceName>myworkspace</WorkspaceName>
        <TfCommand>"C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\tf.exe"</TfCommand>
        <DevenvCommand>"C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe"</DevenvCommand>
        <WorkingDirectory>c:\</WorkingDirectory>
    </PropertyGroup>
</Project>

After I used the batch file, I realised I could use <Exce Command=”> for any dos command. So, I moved “GetLatest” bit into msbuild proj.
Also, included remote copy to the server. The final codes are like the below

batch file

"C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe" MSBUld_Build.proj /t:GetLatest;Build;Deploy
pause

and msbuild proj file

<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets" />
<Import Project="C:\MSBUILD\bin\Microsoft.Sdc.Common.tasks"/>

<PropertyGroup>
<TF>"C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\tf.exe"</TF>
<TFSourceLocation>$/Occup/GoYocal</TFSourceLocation>
<SolutionRoot>C:\Occu\GoYocal</SolutionRoot>
<RemoteWebRoot>\\TJ103\d$\Occu\WebSites\GoYocal</RemoteWebRoot>
<Copy>xcopy /E /I /R /Y</Copy>
</PropertyGroup>

<Target Name="GetLatest">
<Exec Command="$(TF) get $(TFSourceLocation) /force /recursive /version:T /noprompt" ContinueOnError="true" />
</Target>

<Target Name="Build" >
<Tools.DevEnv VisualStudio="9.0" Path="$(SolutionRoot)\GoYocal.sln" Config="Release" OutputFolder="$(SolutionRoot)\src\app\bin" Clean="true">
</Tools.DevEnv>
</Target>

<Target Name="Deploy">
<Exec Command='net use "x:" "$(RemoteWebRoot)" /u:domain\username pwd' />
<Exec Command='$(Copy) "$(SolutionRoot)\src\app" "x:" '/>
<Exec Command='net use x: /d' />
</Target>

</Project>
MSBUild task: Get the latest code from TFS and build