Failed Deployment for Plugins in MS CRM 2013 with ILMerge - visual-studio-2010

I developed a single plugin for on-premise crm 2013 (PreCreateOpportunityProduct - nothing special). In my visual studio crm solution I added a project (called BusinessLogic) that includes my generated Entities.cs as well as partial classes for each entity. Therefore I can encapsulate the logic for one special entitiy in one separate class. No big deal so far.
Now I want to use those logic, therefore I add the project reference in my plugin project. I know that I need to merge all needed DLL's to one, so I added a post-build event to merge all dll's with ILMerge.
Overview of Solution / Project with used DLLs:
The post-build command looks as follows:
mkdir "$(TargetDir)Merged"
"$(SolutionDir)Libs/ilmerge.exe" /keyfile:"$(ProjectDir)keypair.snk" /target:library /copyattrs /targetplatform:v4,"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0" /out:"$(TargetDir)Merged\Flag.Plugins.dll" "$(TargetDir)Flag.Plugins.dll" "$(TargetDir)BusinessLogic.dll" "$(TargetDir)Microsoft.Crm.Sdk.Proxy.dll" "$(TargetDir)Microsoft.Xrm.Sdk.dll"
del "$(TargetDir)*.*" /Q
move "$(TargetDir)Merged\*.*" "$(TargetDir)"
The RegisterFile.crmregister:
<?xml version="1.0" encoding="utf-8"?>
<Register xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/crm/2011/tools/pluginregistration">
<Solutions>
<Solution Assembly="Flag.Plugins.dll" Id="f4dff197-5b7a-e411-80c3-005056ba5a51" IsolationMode="None" SourceType="Database">
<PluginTypes>
<Plugin Description="Plug-in to PreOpportunityProductCreate" FriendlyName="PreOpportunityProductCreate" Name="Flag.Plugins.PreOpportunityProductCreate" Id="0f7bd0bc-2b7b-e411-80c3-005056ba5a51" TypeName="Flag.Plugins.PreOpportunityProductCreate">
<Steps>
<clear />
<Step CustomConfiguration="" Name="PreOpportunityProductCreate" Description="Pre-Operation of Opportunity Product Create" Id="107bd0bc-2b7b-e411-80c3-005056ba5a51" MessageName="Create" Mode="Synchronous" PrimaryEntityName="opportunityproduct" Rank="1" SecureConfiguration="" Stage="PreInsideTransaction" SupportedDeployment="ServerOnly">
<Images />
</Step>
</Steps>
</Plugin>
</PluginTypes>
</Solution>
</Solutions>
<XamlWorkflows />
</Register>
Note: I am Deployment Manager + System administrator -> all permissions
When I click Deploy on CrmPackage project, the error
Error registering plugins and/or workflows. Plug-in assembly does not contain the required types or assembly content cannot be updated. C:\Program Files (x86)\MSBuild\Microsoft\CRM\Microsoft.CrmDeveloperTools.CrmClient.targets
Note 2: When I deploy the plugin.dll without merging all the other DLLs the deployment works like charm, but the plugin throw the exception because the BusinessLogic.dll is not known.
Can anyone help me with this issue?
Thanks in advance

I found the problem: I was merging too many files! In detail: It was the Microsoft.Crm.Sdk.Proxy.dll and Microsoft.Xrm.Sdk.dll. Those libs are already in the crm server GAC. After removing those files from my ilmerge command, the deployment finally works.
Here is the link which gave me the important hints:
https://community.dynamics.com/crm/f/117/p/146347/326928.aspx#326928

Related

Visual Studio pré build event delete reference

I'm going to spare you the trouble of explaining why I want to do this, but I'm looking for a way to remove a reference to a dll when a project is build. I'm not talking about an unused reference, but a reference that might contain the same namespaces and the same classes which my project is using. I was thinking of a pré build event command line, but I don't know what the command will look like.
PS: For those of you who do care why I want this. I have a template project A that contains classes that use base classes defined in another project B. This template project (A) its only function is to be packed up in a Nuget package to then be deployed in multiple other projects, for simplicity sake imagine 3 projects C, D and E. Using the Nuget in projects C, D & E will generate all the classes and put a reference to the dll of project B, because we need the Base classes. At the moment I also get a reference to the DLL of template project (A). This is what should not happen because all classes with the same namespaces will exist in project A and in projects C, D & E. This is why I want to automatically remove the reference to the template project (A).
Thanks in advance.
Kind regards,
Yannick
Visual Studio pré build event delete reference
Do you want to delete the reference project A in the build event command line when you build the project? If yes, I am afraid there is no directly build event command line to do this, you can create a power shell script to delete the reference, then execute this power shell script in the build event.
However, just as imp said "Why do you need a reference to the Package A, if it's not going to be used at all?". So as a workaround, you can not add reference project A to the project C, D and E, To accomplish this, you can target the dll files to the tools folder instead of lib folder in the .nupsec file:
<files>
<file src="bin\Debug\ProjectA.dll" target="Tools\ProjectA.dll" />
</files>
The .nuspec of Project A should be:
<?xml version="1.0"?>
<package >
<metadata>
<id>MyModels</id>
<version>1.0.0</version>
<authors>Tester</authors>
<owners>Tester</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Package description</description>
<releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
<copyright>Copyright 2018</copyright>
<tags>Tag1 Tag2</tags>
</metadata>
<files>
<file src="bin\Debug\ProjectB.dll" target="lib\Net45\ProjectB.dll" />
<file src="bin\Debug\ProjectA.dll" target="Tools\ProjectA.dll" />
</files>
</package>
Then pack this .nuspec file, generate the nuget package, install this package to the project, the reference Project A will not be added to the project.
Hope this helps.

Is it possible to get NuGet.exe running disconnected from Visual Studio?

I've been wrestling with NuGet for a few days now and I'm turning to StackOverflow in frustration - hopefully someone here can be kind enough to point me in the right direction.
I've used NuGet several times for simple one-man pet projects, but this is the first time I've used it for something I really care about and want to have fully continuous builds, etc. I'm trying to create a simple NAnt build script to get the source for Git, ensure the external dependencies have been brought down, compile, and run tests - vanilla CI.
I originally went down the path of trying to get solution restore working, but it just didn't work or I didn't how it worked. Visual Studio is not on the build server and will not be installed there - that is not an option. As an aside, I couldn't get solution restore to work just with two developers (one trying to bring down the source fresh and build cleanly). I'm assuming it's because "allow solution restore" must be turned on everywhere (and is not by default). I punted on that approach before I got to the bottom of it - frankly, having my package manager so tightly coupled to the IDE makes me uncomfortable and was hoping I could do it another way. The package managers I'm used to using are simple command line tools - the CI build script invokes it on build, and developers do it on demand. I've spent the last two hours trying to get this working with the last 30 minutes in the NuGet source code. I feel like I'm fighting the tool and need to reboot.
Does anyone have any examples of the best to use NuGet in a multi-developer + CI scenario? This is what I want:
Any and all developers can get the source and run the tests in 3 or
less clicks (preferably 1). If the binaries are not present locally, that will be JIT fetched. If they are there, they will be updated if necessary, etc. This would ideally not even require NuGet to be installed (i.e. NuGet.exe would need to be in my repo).
Do #1 via a CI server like Jenkins, TeamCity, etc. (preferably using the same script)
If its not overly fighting the tool, I would like to have all this disconnected from Visual Studio with a single packages.config file and all binaries dumped into a single Lib folder in the root of the repo.
Any pointers would be very much appreciated.
Below, how I think you can achieve each your requisites:
You need to "Enable NuGet Package Restore" in your solution: http://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages
As #alexander-doroshenko mentioned for TeamCity you can use Nuget Installer: http://confluence.jetbrains.com/display/TCD7/NuGet+Installer, but if you want a script to run in Jenkins, try this (works at TC too, as a command line step) for each project:
nuget.exe install "[Project folder]/packages.config" -source "" -solutionDir "" -OutputDirectory "packages"
This requisite will be done by item 1 and 2.
TeamCity has a build step for that, called "NuGet Installer", it fetch required packages from .sln file and download the locally. It does not require Visual Studio to run.
Read more about it here: http://confluence.jetbrains.com/display/TCD7/NuGet+Installer
There are several different solutions for integrating NuGet into your build process depending on how much integration you require. In our case we wanted to use NuGet as package manager and allow developers to build their solutions even if they haven't got NuGet installed on their machine. For that to work we enabled package restore which adds the NuGet binaries to your solution folder and updates the project files. Note that NuGet doesn't always do the update of the project files correctly. In our case we found that some project files got updated but others didn't. To verify that the project was updated you will need to open the project file as XML file. To achieve this load the solution and right click the project in question and select unload project. Then right click the project again and select edit [PROJECT_NAME]. In the project file you should see
A RestorePackages property in the first propertygroup. This property should have the value true
An import statement at the very end of the project file. This import statement should point to the 'NuGet.targets file that accompanies the NuGet binary.
Below is an example of one of our project files (heavily edited)
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SolutionDir Condition="'$(SolutionDir)' == '' or '$(SolutionDir)' == '*undefined*'">$(MSBuildProjectDirectory)\..</SolutionDir>
<ProjectGuid>{8B467882-7574-41B2-B3A8-2F34DA84BE82}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>MyCompany.MyNamespace</RootNamespace>
<AssemblyName>MyCompany.MyNamespace</AssemblyName>
<!-- Allow NuGet to restore the packages if they are missing -->
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<Import Project="$(SolutionDir)\BaseConfiguration.targets" />
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="MyClass.cs" />
<!--
.... MANY MORE FILES HERE
-->
</ItemGroup>
<!-- Import the Nuget.targets file which integrates NuGet in the build process -->
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
The next step you'll need to take is to provide a solution level NuGet configuration file in which you'll indicate where the packages need to be 'installed' and what the URL of the package repository is. In our case the solution directory structure looks like:
(D) root
(D) build
(D) packages
(D) source
(D) .nuget
NuGet.config
NuGet.exe
NuGet.targets
(D) MyCoolProject
MyCoolProject.csproj
MyCoolProject.sln
(D) templates
NuGet.Config
Where (D) indicates a directory.
The NuGet.config file contains the following configuration settings.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageRestore>
<add key="enabled" value="True" />
</packageRestore>
<config>
<add key="repositorypath" value="packages" />
</config>
<packageSources>
<add key="OurPackageServer" value="PACKAGE_SERVER_ADDRESS" />
</packageSources>
<activePackageSource>
<add key="All" value="(Aggregate source)" />
</activePackageSource>
</configuration>
This configuration file indicates that package restore is enabled, that the repository path (where the packages are placed) is the packages directory and which package sources are active.
By placing a NuGet.config file in the root directory we can use the hierarchical configuration option with NuGet. This allows the individual solutions to override computer specific configurations. The other benefit is that this way we don't need to have NuGet installed on the build server (because the executable and the configurations are in the repository).
With this setup developers can build the solution from Visual Studio. The build should work fine on developers machines even if they don't have NuGet installed. Note however that they won't be able to add packages to a project without having NuGet installed in visual studio.
On the build server you can simply use MsBuild to build the solution which will automatically download the packages from your package repository. Visual Studio is not required to be installed on the build machine for that (just the .NET framework of your choice).

SlowCheetah executes after post-build events

I use SlowCheetah to transform my app.configs. I have a multi-project solution where one of the projects executes a post-build event where the output of the bin is copied elsewhere. I've found that SlowCheetah does it's transforms after the post-build event, so the app.config I'm copying is the pre-transformed version.
Does anyone have a suggestion of how I can execute my copy after the SlowCheetah transforms? Is this going to require that I write a custom build task?
If you are using msbuild 4.0 for building your projects - you can hook to slowcheetah targets with new AfterTargets BeforeTargets attributes.
I dont know what exactly target name you want to hook after but this code could gave you base concept how to do this
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Some_Target_Name" AfterTargets="TransformAllFiles" >
<Message Text="= Script here will run after SlowCheetah TransformAllFiles ="/>
</Target>
<Project>
Edited: I installed SlowCheetah and found that AfterTargets attribute should be "TransformAllFiles".
Just set up your target dependency AfterTargets="TransformAllFiles"
Alexey's answer leads to the correct solution but here it is in full:
Right-click your project and select Unload Project
Now right-click the project and select Edit [your project name].csproj
Scroll to the bottom and uncomment the target named AfterBuild and add this attribute AfterTargets="TransformAllFiles"
Move your post build actions into this target using the Exec command:
An example:
<Target Name="AfterBuild" AfterTargets="TransformAllFiles">
<Exec Command="ECHO Hello PostBuild World!" />
</Target>
I have bumped into this problem too... decided to update to latest version of SlowCheetah (current 2.5.8), and this problem appears to have been fixed! No more problems using post-build events to deploy a project with transformed XML!
After the NuGet package upgrade process, I had a strange issue, though... transforms were no longer happening. Editing the project like Naeem Sarfraz suggested, I have found that the SlowCheetah's PropertyGroup section was placed at the end of the .csproj.
It was just a matter of moving it to the top, near the other PropertyGroup sections, and now it works like a charm!
If you need to copy/move other .config files (other than web.config) around after the build before publishing here is how it can be done with Visual Studio 2013 (I didn't test it on earlier versions). This section can be added at the end of the .csproj file right before the closing tag </Project> and it'll be fired just before MSDeploy starts the Publishing process.
<Target Name="MoveConfigFile" BeforeTargets="MSDeployPublish">
<Move
SourceFiles="$(IntermediateOutputPath)Package\PackageTmp\ThirdPartyApp.config"
DestinationFolder="$(IntermediateOutputPath)Package\PackageTmp\bin"
OverwriteReadOnlyFiles="true"
/>
</Target>
The company I work for purchased a third party product that needs to have a .config files in the bin folder along with its assembly in order to work.
At the same time we need to process the product's .config file and be able to move it to the bin folder after transformations.
The $(IntermediateOutputPath)Package\PackageTmp folder contains the whole application that will be copied over the target server.

VS2010 Web Publish command line version of File System deploy

Folks,
In a nutshell, I want to replicate this dialog:
It's a Visual Studio 2010 ASP.Net MVC project. If I execute this command, I get all the files I want, including the transformed web.configs in the "C:\ToDeploy" directory.
I want to replicate this on the command line so I can use it for a QA environment build.
I've seen various articles on how to do this on the command line for Remote Deploys, but I just want to do it for File System deploys.
I know I could replicate this functionality using nAnt tasks or rake scripts, but I want to do it using this mechanism so I'm not repeating myself.
I've investigated this some more, and I've found these links, but none of them solve it cleanly:
VS 2008 version, but no Web.Config transforms
Creates package, but doesn't deploy it..do I need to use MSDeploy on this package?
Deploys package after creating it above...does the UI really do this 2 step tango?
Thanks in advance!
Ok, finally figured this out.
The command line you need is:
msbuild path/to/your/webdirectory/YourWeb.csproj /p:Configuration=Debug;DeployOnBuild=True;PackageAsSingleFile=False
You can change where the project outputs to by adding a property of outdir=c:\wherever\ in the /p: section.
This will create the output at:
path/to/your/webdirectory/obj/Debug/Package/PackageTmp/
You can then copy those files from the above directory using whatever method you'd like.
I've got this all working as a ruby rake task using Albacore. I am trying to get it all done so I can actually put it as a contribution to the project. But if anyone wants the code before that, let me know.
Another wrinkle I found was that it was putting in Tokenized Parameters into the Web.config. If you don't need that feature, make sure you add:
/p:AutoParameterizationWebConfigConnectionStrings=false
I thought I'd post a another solution that I found, I've updated this solution to include a log file.
This is similar to Publish a Web Application from the Command Line, but just cleaned up and added log file. also check out original source http://www.digitallycreated.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild
Create an MSBuild_publish_site.bat (name it whatever) in the root of your web application project
set msBuildDir=%WINDIR%\Microsoft.NET\Framework\v4.0.30319
set destPath=C:\Publish\MyWebBasedApp\
:: clear existing publish folder
RD /S /Q "%destPath%"
call %msBuildDir%\msbuild.exe MyWebBasedApp.csproj "/p:Configuration=Debug;PublishDestination=%destPath%;AutoParameterizationWebConfigConnectionStrings=False" /t:PublishToFileSystem /l:FileLogger,Microsoft.Build.Engine;logfile=Manual_MSBuild_Publish_LOG.log
set msBuildDir=
set destPath=
Update your Web Application project file MyWebBasedApp.csproj by adding the following xml under the <Import Project= tag
<Target Name="PublishToFileSystem" DependsOnTargets="PipelinePreDeployCopyAllFilesToOneFolder">
<Error Condition="'$(PublishDestination)'==''" Text="The PublishDestination property must be set to the intended publishing destination." />
<MakeDir Condition="!Exists($(PublishDestination))" Directories="$(PublishDestination)" />
<ItemGroup>
<PublishFiles Include="$(_PackageTempDir)\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(PublishFiles)" DestinationFiles="#(PublishFiles->'$(PublishDestination)\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="True" />
</Target>
this works better for me than other solutions.
Check out the following for more info:
1) http://www.digitallycreated.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild
2) Publish a Web Application from the Command Line
3) Build Visual Studio project through the command line
My solution for CCNET with the Web.config transformation:
<tasks>
<msbuild>
<executable>C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable>
<workingDirectory>E:\VersionesCC\Trunk_4\SBatz\Gertakariak_Orokorrak\GertakariakMS\Web</workingDirectory>
<projectFile>GertakariakMSWeb2.vbproj</projectFile>
<targets>Build</targets>
<timeout>600</timeout>
<logger>C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MSBuild.dll</logger>
<buildArgs>
/noconsolelogger /p:Configuration=Release /v:diag
/p:DeployOnBuild=true
/p:AutoParameterizationWebConfigConnectionStrings=false
/p:DeployTarget=Package
/p:_PackageTempDir=E:\Aplicaciones\GertakariakMS2\Web
</buildArgs>
</msbuild>
</tasks>
On VS2012 and above, you can refer to existing publish profiles on your project with msbuild 12.0, this would be equivalent to right-click and publish... selecting a publish profile ("MyProfile" on this example):
msbuild C:\myproject\myproject.csproj "/P:DeployOnBuild=True;PublishProfile=MyProfile"
I've got a solution for Visual Studio 2012: https://stackoverflow.com/a/15387814/2164198
However, it works with no Visual Studio installed at all! (see UPDATE).
I didn't checked yet whether one can get all needed stuff from Visual Studio Express 2012 for Web installation.
A complete msbuild file with inspiration from CubanX
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Publish">
<RemoveDir Directories="..\build\Release\Web\"
ContinueOnError="true" />
<MSBuild Projects="TheWebSite.csproj"
Targets="ResolveReferences;_CopyWebApplication"
Properties="Configuration=Release;WebProjectOutputDir=..\build\Release\Web;OutDir=..\build\Release\Web\bin\"
/>
</Target>
<Target
Name="Build"
DependsOnTargets="Publish;">
</Target>
</Project>
This places the published website in the Web..\build\Release folder

TeamCity - problem with Publish on ASP.net site

I am trying to configure TeamCity 5.0 to run "Publish" target on one of my projects.
When I load the solution in VS 2008 and click publish on the project the website is being build nicely - files on server appearing by themselves etc. Yet when I run the sln file via TeamCity Sln2008 runner the TeamCity returns:
[Project "Portal.csproj" (Publish target(s)):] Skipping unpublishable project.
Has anyone had the same problem?
Filip
You could create your own simple build file. For example:
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<PropertyGroup>
<PackageFolder>C:\Builds\AppServer\Actual</PackageFolder>
</PropertyGroup>
<Target Name="Build" DependsOnTargets="BeforeBuild">
<MSBuild Projects="TeamWork-AppServer.sln"
Targets="Rebuild"
Properties="Configuration=Debug;OutDir=$(PackageFolder)\;"></MSBuild>
</Target>
</Project>
Or you can use VS 2008 Web Deployment Project. Here is a great turtorial.
If it is a WebProject you can use the Microsoft.WebApplication.targets. Unless you have installed the windows SDK on your build agent you will need to copy the targets file into your source control and reference it from your web project by adding:
<Import Project="{path to your tools}\Microsoft.WebApplication.targets" />
You can find the targets file here (depending on your os):
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v9.0\WebApplications
Now you just need to update your msbuild task to reference the right targets:
<MSBuild Projects="{path to your web project file}"
Targets="Build;ResolveReferences;_CopyWebApplication"
Properties="Configuration=Release;Architecture=Any;WebProjectOutputDir={your web root};OutDir={your web root}\bin\" />
Here is how I modified the .csproj file for an ASP.NET MVC project to deploy via TeamCity 5.1.2. In the .csproj file, replace the AfterBuild target with this XML (If there are already commands in your existing AfterBuild, you will have to merge them into these targets):
<PropertyGroup>
<DeployTarget>0</DeployTarget>
<PublishTarget>0</PublishTarget>
<PublishFolder>..\Deployment\YourWebsiteName</PublishFolder>
</PropertyGroup>
<Target Name="PublishProperties">
<CreateProperty Value="$(PublishFolder)">
<Output TaskParameter="Value" PropertyName="WebProjectOutputDir"/>
</CreateProperty>
<CreateProperty Value="$(PublishFolder)\bin\">
<Output TaskParameter="Value" PropertyName="OutDir"/>
</CreateProperty>
</Target>
<Target Name="WebPublish" DependsOnTargets="BeforeBuild;PublishProperties">
<RemoveDir Directories="$(PublishFolder)"
ContinueOnError="true" />
<CallTarget Targets="ResolveReferences;_CopyWebApplication" />
</Target>
<Target Name="Deploy" DependsOnTargets="WebPublish">
<CreateProperty Value="Path\To\Your\Server" Condition="$(DeployFolder) == ''">
<Output TaskParameter="Value" PropertyName="DeployFolder"/>
</CreateProperty>
<RemoveDir Directories="$(DeployFolder)" Condition="$(CleanDeploy) == 1" />
<ItemGroup>
<DeploymentFiles Include="$(PublishFolder)\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(DeploymentFiles)"
DestinationFolder="$(DeployFolder)\%(RecursiveDir)" />
</Target>
<Target Name="AfterBuild">
<CallTarget Targets="WebPublish" Condition="$(PublishTarget) == 1" />
<CallTarget Targets="Deploy" Condition="$(DeployTarget) == 1" />
</Target>
This script uses the $(PublishTarget) and $(DeployTarget) properties to trigger additional steps after your project is built. The PropertyGroup at the beginning sets the default values to 0, so the extra targets are not run. You can override the default in TeamCity by going to the Properties and Environment Variables page of your build configuration and adding System Properties names "PublishTarget" and "DeployTarget" and setting their value to 1.
The Publish target contains most of the magic. This makes a call to the Visual Studio _CopyWebApplication target to output the website to the PublishFolder. By default the publish folder is "..\Deployment\YourWebsiteName" relative to the project file, but this can also be overridden with a System Property. The Deploy target takes the files output by the Publish target and copies them to the DeployFolder. DeployFolder can be set with a System Property in TeamCity or you can replace the "Path\To\Your\Server" path in the Deploy target.
You could also skip the extra Deploy step by simply setting the PublishFolder to whatever your deployment destination is. This script depends on the "Microsoft.WebApplication.Build.Tasks.Dll" and "Microsoft.WebApplication.targets" files installed by Visual Studio, but you can simply copy the files from your developer workstation to the build server. The default location is "C:\Program Files\MSBuild\Microsoft\VisualStudio\v10.0\WebApplications".
I have this same problem, here's what I've tried:
I have a solution file in Visual Studio 2010, committed to a Mercurial repository.
I have setup an FTP server for the root directory of the site to publish to, and publishing from within Visual Studio 2010 locally works nicely, it connects and uploads everything as expected, and the website works.
Now, I wanted to automate this on every push to the central Mercurial repository, and since I'm using TeamCity, I discovered that the field to specify the Target of the build, usually "Rebuild" can also take "Publish", so I specified "Rebuild;Publish", as per the documentation and help.
I have verified that after publishing in Visual Studio, and committing new files, a file named ProjectName.Publish.xml is accompanying my ProjectName.csproj file, and this file is pulled down into the server directory when TeamCity builds.
Yet, no publishing is done, and when I check the build log, it says:
[19:01:02]: [Project "Test.sln" (Rebuild;Publish target(s)):] Project "Test.UI.Web.csproj" (Publish target(s)):
[19:01:02]: [Project "Test.UI.Web.csproj" (Publish target(s)):] Skipping unpublishable project.
Exactly as the question here says.
Note that this is a development site, publishing just so that we can let more people test changes, so don't get into a discussion of whether this is actually a good idea or not.
Note: I do not care in which way the files are published, I just need the single TeamCity build-step to actually do it, so if anyone got a MSBuild-like solution that just sidesteps TeamCity, then I would be satisfied
Have you tried to execute Visual Studio directly, rather than relying on MSBuild to publish the project directly. MSBuild can't execute certain kinds of projects. I had a similar problem with getting MSI's built from within Team City.
I'm taking a guess at the exact commandline settings to this, since I don't know your exact setup.
<PropertyGroup>
<buildconfiguration>Release</buildconfiguration>
<DevEnv>C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\devenv.com</DevEnv>
</PropertyGroup>
<Exec Command="%22$(DevEnv)%22 /build $(buildconfiguration) $(teamcity_build_checkoutDir)\Test.sln /project Test.UI.Web.csproj"/>
If you're using the Team City solution runner as your build runner, you'll have to switch to MSBuild.
If you want to stay with the Team City runner, you could always try adding a project to your solution that will be the last one built, (or do it on the project that currently gets built last), and do the spawning trick as a post-build command line on the project.
Can TeamCity publish a Web project using the sln2008 build runner
Can TeamCity publish a Web project using the sln2008 build runner?
What type of project are you trying to publish?
http://social.msdn.microsoft.com/forums/en-US/msbuild/thread/7ec0d942-6354-41c3-9c97-7e7d1f461c29
Taken from above link:
What I discovered is that "Shared-addins" are not publishable
and are distinct and different from document and application level
VSTO addins, which are deployable.
When I rebuilt my application as an application level
VSTO addin, the publish option was available.
http://www.automise.com/Default.aspx?tabid=53&aft=9813
Taken from above link:
Assuming you're using Visual Studio 2008, we're unable to execute the web site
publish feature from FinalBuilder as it's partially implemented by the VS IDE.
You'll need to use to the MSBuild action to compile the application and then
use one of the other actions (FTP, File Copy, etc) in FinalBuilder to perform
the deployment. Visual Studio 2010 has fixed this problem by performing the
entire publish using MSBuild, see this post for more info:
http://www.finalbuilder.com/forums....&afv=topic
Two threads that might help
http://devnet.jetbrains.net/thread/280420;jsessionid=5E8948AE810FFFF251996D85E7EB3FE3
Visual Studio. Publish project from command line
For anyone using Web Application Projects in VS2010, I managed to get TeamCity to package the deliverables and then Web Deploy the package after successfully building the solution.
With a little tweaking, this had the same effect as hitting the 'Publish' button in VS.
My solution has a handful of projects, 1 of which is an ASP.NET MVC Web Application project. I build the solution, package the web app project, and msdeploy the package in 3 steps. I haven't figured out a (better|shorter|simpler|more elegant) way to do this.
I don't have VS installed on my TeamCity server, so I needed to grab both C:\Program Files\MSBuild\Microsoft\VisualStudio\v10.0\Web and C:\Program Files\MSBuild\Microsoft\VisualStudio\v10.0\Web Applications and put them both in the same spot on the TeamCity server (the second depends on the first). If you're working w/x64 machines, I'd grab them from both Program Files (x86) and Program Files. You also need to have Web Deploy installed on your machine and (I believe) IIS Management Service (i.e., something listening on https://yourservername:8172/MsDeploy.axd)
There are 3 build steps:
Visusal Studio (sln), Target=Rebuild, Configuration=Debug
MSBuild WebProject.csproj, Targets=Package Commandline=/p:PackageLocation=%teamcity.build.checkoutDir%\Debug.zip /p:Configuration=Debug
Commandline, Executable=%teamcity.build.checkoutDir%\Debug.deploy.cmd, Parameters=
/Y "-setParam:'IIS Web Application Name'='Default Web Site/PreCreatedAppInIis'"
In that last step, 'IIS Web Application Name' is an actual parameter name, don't change it. It's value can either be something like 'Default Web Site' or whatever you named your website in IIS and/or it can be an IIS application path below it. If the application doesn't exist, you may run into errors about the app pool not being configured correctly to host the application. Rather than investigate it, I just created an application in the appropriate app pool. In my case, I'm targeting ASP.NET 4.0 x64 where the default app pool is ASP.NET 2.0 x64.

Resources