How can I build a SharePoint 2010 package using command line? - visual-studio-2010

I have a Visual Studio 2010 SharePoint project. If I choose 'Package' from the project menu, a .wsp file is generated. How can I invoke the same build from command line (i.e. what /target is required for MSBuild)?

I got it to work, finally. The tricky part is the fact that the SharePoint targets do not exist when MSBuild loads the .sln file, you have to load the individual .csproj files.
set msbuild="C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe"
set config=Debug
set outdir="C:\out\"
%msbuild% /p:Configuration=%config% /m ../My.SharePoint.Project/My.SharePoint.Projectcsproj /t:Package /p:BasePackagePath=%outdir%

This is also a useful document here: http://msdn.microsoft.com/en-us/ff622991.aspx
"To generate packages when building in
TFS 2010, set the parameter
/p:IsPackaging=True on MSBuild"

Also to package project with msbuild you can use target Package:
Define new target "BuildAndPackage"
<Target Name="BuildAndPackage">
<CallTarget Targets="Build"/>
<CallTarget Targets="Package"/>
</Target>
Use new target in build process:
<Project ToolsVersion="4.0" DefaultTargets="BuildAndPackage">
But this approach not recommended because it may cause errors in TFS Build process..

Set the MSBuild's verbosity to 'maximum' and you should see what is called from the build console.
In VS2010 of course :)

Related

How to avoid that Visual Studio incremental build does not run when files outside <Compile> and <EmbeddedResource> are changed?

I have a VS2017 csharp project and the .csproj file looks like the following:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<MyItem Include="file.dat" />
</ItemGroup>
<PropertyGroup>
<PrepareResourcesDependsOn>
$(PrepareResourcesDependsOn);
MyCompileTarget
</PrepareResourcesDependsOn>
<CoreCompileDependsOn>
$(CoreCompileDependsOn);
MyCompileTarget
</CoreCompileDependsOn>
</PropertyGroup>
<Target Name="MyCompileTarget" Inputs="#(MyItem)" Outputs="#(MyItem->'%(FileName).out')">
...
</Target>
</Project>
Where MyCompileTarget is a target that generates the file.out from file.dat (in the actual code the incremental build target and properties are in a target file automatically included via a NuGet package).
The issue is that if I change file.dat and press on Build, no target is executed at all, (but MyTarget is correctly executed with Rebuild or when running with msbuild). I would expect the MyCompileTarget to be executed so that the file.out file is updated.
The same issue occurs if I use BeforeBuild or AfterBuild instead of PrepareResourcesDependsOn etc.
It seems that Visual Studio incremental build won't start unless some file in #(Compile) or #(EmbeddedResource) is changed. Indeed, if I add the following
<EmbeddedResource>file.dat</EmbeddedResource>
the incremental build works as expected (but clearly I do not want to embeed the file.dat into the generated assembly).
Is it possible to force Visual Studio to enable incremental build if file.dat is modified, and if the corresponding generated file is older than file.dat or it does not exist?
Note: the same issue occurs using VS2015, with .NET CORE or .NET FRAMEWORK.
Also, incremental build will be triggered if I change a csharp file, and it will therefore trigger MyTask, but only if file.dat is newer than the generated file (as expected).
Thanks in advance,
Fabio.
Is it possible to force Visual Studio to enable incremental build if file.dat is modified
You can set the property DisableFastUpToDateCheck to true in the project file to disable FastUpToDateCheck for Visual Studio build manager:
<PropertyGroup>
<DisableFastUpToDateCheck>True</DisableFastUpToDateCheck>
</PropertyGroup>
Check MSDN about DisableFastUpToDateCheck:
A boolean value that applies to Visual Studio only. The Visual Studio
build manager uses a process called FastUpToDateCheck to determine
whether a project must be rebuilt to be up to date. This process is
faster than using MSBuild to determine this. Setting the
DisableFastUpToDateCheck property to true lets you bypass the Visual
Studio build manager and force it to use MSBuild to determine whether
the project is up to date
Update:
Also, we can set the UpToDateCheckInput to the item:
<UpToDateCheckInput Include="file.dat" />
Disabling the VS fast up-to-date check will make your builds much slower. Don't do it!
Instead, make sure the up-to-date check knows about the items in your project and how they relate to build. There are two kinds of item you can add to your project for this:
UpToDateCheckInput for inputs
UpToDateCheckBuilt for outputs
In your case you need the second option as there is both an input and an output. You need to ensure that if you delete the output, it is rebuilt.
<PropertyGroup>
<UpToDateCheckBuilt Original="#(MyItem)" Include="#(MyItem->'%(FileName).out')">
</PropertyGroup>
For more information, see the documentation:
https://github.com/dotnet/project-system/blob/main/docs/up-to-date-check.md

TFS 2017 Build Definition: Packaging Web API Project for deployment

I have a Visual Studio solution that contains four projects:
1 Desktop app;
1 Windows Service;
2 Web API projects.
These projects have been migrated from VS2010 -> 2013 -> 2017. I've removed/edited as much legacy stuff as I recognise.
The solution builds fine in 2017.
I wish to only build one of the Web API projects, generate a deployment package, and publish the package as an artifact. A release definition is going to use WinRM to deploy the package on a Windows Server 2012 system running IIS.
In my build definition I have a MSBuild task.
The parameters of this task are as follows:
Project is set to the path of my webAPI .csproj in TFS source control
Platform is set to "AnyCPU" - ("Any CPU" doesn't work.. its a known (old) issue)
Configuration is "Release"
MSBuild arguments are:
/p:DeployOnBuild=true /p:WebPublishMethod=Package
/p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation=$(Build.ArtifactStagingDirectory)\webapi.zip
Clean is set to true
The build completes successfully, however the webapi.zip package that is produced contains a massive folder structure:
C:\agent2_work\27\a\webapi.zip\Content\C_C\agent2_work\27\s\MyProduct.WebApi\obj\release\Package\PackageTmp
Questions:
Why is it packing this full path? (c:\agent2_work is my build agent's directory)
How do I change it?
It's the expected behavior, it's based on your Package Location. If you publish the project in VS, you will find the similar folder structure. See Create a Web Deployment Package in Visual Studio for details. And this thread for your reference.
However you can change the folder structure with publish profile used in MSBuild Arguments. Following below steps to do that:
1, Create a publish profile.
To create a web deploy package in VS you
will first create a publish profile for that. When you do this, a
.pubxml file will be created for you under
Properties\PublishProfiles. This is your publish profile file, its an MSBuild file. You can customize your publish process by editing
this file. We will modify this file in order to update these paths
in the package.
2, Edit the .pubxml file for the profile and add the following before
the closing </Project> tag. (Create the target AddReplaceRuleForAppPath, and inject that into the package process by adding it to PackageDependsOn property. Once this target is executed it will add a replace rule into the MSDeployReplaceRules item group.)
<PropertyGroup>
<PackagePath Condition=" '$(PackagePath)'=='' ">WebApi</PackagePath>
<EnableAddReplaceToUpdatePacakgePath Condition=" '$(EnableAddReplaceToUpdatePacakgePath)'=='' ">true</EnableAddReplaceToUpdatePacakgePath>
<PackageDependsOn>
$(PackageDependsOn);
AddReplaceRuleForAppPath;
</PackageDependsOn>
</PropertyGroup>
<Target Name="AddReplaceRuleForAppPath" Condition=" '$(EnableAddReplaceToUpdatePacakgePath)'=='true' ">
<PropertyGroup>
<_PkgPathFull>$([System.IO.Path]::GetFullPath($(WPPAllFilesInSingleFolder)))</_PkgPathFull>
</PropertyGroup>
<!-- escape the text into a regex -->
<EscapeTextForRegularExpressions Text="$(_PkgPathFull)">
<Output TaskParameter="Result" PropertyName="_PkgPathRegex" />
</EscapeTextForRegularExpressions>
<!-- add the replace rule to update the path -->
<ItemGroup>
<MsDeployReplaceRules Include="replaceFullPath">
<Match>$(_PkgPathRegex)</Match>
<Replace>$(PackagePath)</Replace>
</MsDeployReplaceRules>
</ItemGroup>
</Target>
3, Save the Publish Profile file and check in the changes
4, Enter below MSBuild arguments: (In this example my publish profile name is 1011DP.pubxml)
/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:PublishProfile=1011DP /p:SkipInvalidConfigurations=true /p:PackageLocation=$(Build.ArtifactStagingDirectory)
5, Run the build, then check the folder structure.
To make things a bit easier I just created a nuget package that performs these steps automatically for you. See https://www.nuget.org/packages/SharpSvn.ShortMSDeployWebContentPath
Just installing this in your web application project from Visual Studio will change the long path below 'Contents' with just the single word 'web'

Building InstallShield LE project with MSBuild - Error MSB4062

I work with Visual Studio 2012, and I just switched my deployment tools from NSIS to InstallShield. I've added new projects to my solution for InstallShield installers. When I build in Visual Studio (the IDE) I've no errors, no warnings and I'm happy.
Now, I want to have a script that build the full solution without launching the IDE. But when I run MSBuild in the command line, like that
MSBuild MySolution.sln /t:Build /p:Configuration=Release
I get following error MSB4062
C:\Program Files (x86)\MSBuild\InstallShield\2012SpringLimited\InstallShield.targets(21,3): error MSB4062: The "Microsoft.Build.Tasks.AssignProjectConfiguration" task could not be loaded from the assembly Microsoft.Build.Tasks.v3.5. Could not load file or assembly 'Microsoft.Build.Tasks.v3.5' or one of its dependencies. The system cannot find the file specified. Confirm that the <UsingTask> declaration is correct, that the assembly and all its dependencies are available, and that the task contains a public class that implements Microsoft.Build.Framework.ITask.
My searches lead me to the conclusion that I must buy the Premier Edition of InstallShield to take profit of ISCmdBuild. But I can't afford it, and I think there might be another solution.
Any idea?
Using Fusion logging the MSBuild checks for the DLL here: file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/Microsoft.Build.Tasks.v3.5.DLL.
I copied
c:\Windows\Microsoft.NET\Framework\v3.5\Microsoft.Build.Tasks.v3.5.dll
to
c:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Build.Tasks.v3.5.dll
And the error is gone.
Alternatively open your *.isproj file and change from "3.5" to "4.0" on top on the tag:
<Project ToolsVersion="3.5"...> --> <Project ToolsVersion="4.0" ...>
Another solution is to force MSBuild to use the x86 platform. See https://stackoverflow.com/a/1074699/870604
If you're building from a TFS build, this can be configured from the build options:
I found the solution. Use the command devenv.exe instead of MSBuild.exe. It will be similar to launching Visual Studio and clicking the Build button. That's all!
devenv.exe MySolution.sln /build Release

Using MSBuild.exe to "Publish" a ASP.NET MVC 4 project with the cmd line

I'm looking for a command to run against the MSBuild.exe that just takes a MVC 4 project and publishes it to a given directory.
For example,
MSBuild <solution>/<project>.csproj -publish -output=c:/folder
This is obviously incorrect syntax. I'm trying to simplify my question.
This question talks of a build XML, but I'm not trying to do anything with that much detail.
I'm simply trying to do a deploy.
Further down in that question, someone speaks of "MSDeploy". I can look into that, but is it the only option? I do not have the ability to install web deploy on the server. In which case, all I really need to do is "Publish" and send the contents of the published project to a given directory on the server/file-system.
Does anyone have a one liner I can use?
Do I have to use MSDeploy?
Does MSDeploy require web deploy to be installed on the server?
Doesn't setting up web deploy on the server require setting up some ports, permissions, and installing some IIS add-ons?
I'd love to just execute something simple.
In VS 2012 (as well as the publish updates available in the Azure SDK for VS 2010) we have simplified command line publishing for web projects. We have done that by using Publish Profiles.
In VS for a web project you can create a publish profile using the publish dialog. When you create that profile it is automatically stored in your project under Properties\PublishProfiles. You can use the created profile to publish from the command line with a command line the following.
msbuild mysln.sln /p:DeployOnBuild=true /p:PublishProfile=<profile-name>
If you want to store the publish profile (.pubxml file) in some other location you can pass in the path to the PublishProfile.
Publish profiles are MSBuild files. If you need to customize the publish process you can do so directly inside of the .pubxml file.
If your end goal is to pass in properties from the command line. I would recommend the following. Create a sample publish profile in VS. Inspect that publish profile to determine what MSBuild properties you need to pass in on the command line. FYI not all publish method support command line publishing (i.e. FTP/FPSE).
FYI if you are building the .csproj/.vbproj instead of the .sln and you are using VS 2012 you should also pass in /p:VisualStudioVersion=11.0. For more details as to why see http://sedodream.com/2012/08/19/VisualStudioProjectCompatabilityAndVisualStudioVersion.aspx.
Create a build.xml file thats look like below
Start Visual Studio command prompt
Run msbuild build.xml
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Build">
<PropertyGroup>
<Build>$(MSBuildProjectDirectory)\Build</Build>
<ProjectFile>MyProject.csproj</ProjectFile>
<ProjectName>MyProjectNameInVisualStudio</ProjectName>
<CopyTo>$(MSBuildProjectDirectory)\CopyTo</CopyTo>
</PropertyGroup>
<Target Name="Build">
<RemoveDir Directories="$(Build)"/>
<MSBuild Projects="$(ProjectFile)" Properties="Configuration=Release;OutputPath=$(Build);OutDir=$(Build)/"></MSBuild>
<Exec Command="robocopy.exe $(Build)\_PublishedWebsites\$(ProjectName) $(CopyTo) /e /is
if %errorlevel% leq 4 exit 0 else exit %errorlevel%"/>
</Target>
</Project>
The command below works perfect:
msbuild Myproject.sln /t:Rebuild /p:outdir="c:\outproject\\" /p:Configuration=Release /p:Platform="Any CPU"
I found Sayed's answer was deploying the default configuration i.e. Debug. The configuration selected in the Publishing Profile seems to get ignored by MSBuild. Accordingly I changed the command to specify the correct configuration for the deployment...
msbuild mysln.sln /p:Configuration=[config-name] /p:DeployOnBuild=true /p:PublishProfile=[profile-name]
where config-name = Release or some other build configuration you've created
With web projects you need to build, as per above, but then you also need to package/copy. We use a file copy, rather than the "publish"...
Also; we use DEBUG/RELEASE to build the website; but then actual environments, ie "QA" or "PROD" to handle the web.config transforms.
So we build it initially with RELEASE, and then package it with QA - in the example below.
<PropertyGroup>
<SolutionName>XXX.Website</SolutionName>
<ProjectName>XXX.Website</ProjectName>
<IisFolderName>XXX</IisFolderName>
<SolutionConfiguration>QA</SolutionConfiguration> <!--Configuration will be set based on user selection-->
<SolutionDir>$(MSBuildThisFileDirectory)..</SolutionDir>
<OutputLocation>$(SolutionDir)\bin\</OutputLocation>
<WebServer>mywebserver.com</WebServer>
</PropertyGroup>
<Target Name="BuildPackage">
<MSBuild Projects="$(SolutionDir)\$(SolutionName).sln" ContinueOnError="false" Targets="Clean;Rebuild" Properties="Configuration=Release" />
<MSBuild Projects="$(SolutionDir)\$(ProjectName)\$(ProjectName).csproj" ContinueOnError="false" Targets="Package" Properties="Configuration=$(SolutionConfiguration);AutoParameterizationWebConfigConnectionStrings=False" />
</Target>
<Target Name="CopyOutput">
<ItemGroup>
<PackagedFiles Include="$(SolutionDir)\$(ProjectName)\obj\$(SolutionConfiguration)\Package\PackageTmp\**\*.*"/>
</ItemGroup>
<Copy SourceFiles="#(PackagedFiles)" DestinationFiles="#(PackagedFiles->'\\$(WebServer)\$(IisFolderName)\$(SolutionConfiguration)\%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>
So;
Setup your properties
Call the BuildPackage target
Call the CopyOutput target
And voila!

Use different pre-build events for different build configurations in Visual Studio

Is it possible to use different pre-build events for different build configurations in Visual Studio?
For example, I'd like both a release configuration for a beta & live system and have the relevant app.[type].config get copied to app.config before it is compiled.
At the moment the configuration settings are baked into the .settings file, using the settings from the default app.config file.
Or just put the Condition on your target ... eg.,
Condition="'$(Configuration)' == 'Debug'"
.. or on your task.
If you're using Visual Studio VB/C# simple post build events, you can hand-edit the project file to put such conditions on the PreBuildEvent/PostBuildEvent property tags; and repeat the tags for Release.
Dan (msbuild dev)
You can do this in a couple of ways, depending on your exact situation:
Option 1: Check the $(ConfigurationName) variable in your pre-build script, like so:
IF EXISTS $(ProjectDir)app.$(ConfigurationName).config
COPY $(ProjectDir)app.$(ConfigurationName).config $(ProjectDir)app.config
Option 2: Add a "BeforeCompile" MSBuild target to your project file:
<Target Name="BeforeBuild">
<!-- MSBuild Script here -->
</Target>
Option 3: Use configuration file transformations; this VSIX plug-in adds the web.config transform features to non-web projects. These are XSLT files that let you rewrite your config files on build (unlike web projects, where it happens on publish.)
To use different build events for different configuration in visual studio, open the cs proj file of the project. in the pre build section
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Condition="'$(Configuration)'=='Release'" Command="echo Release" />
<Exec Condition="'$(Configuration)'=='Debug'" Command="echo Debug" />
</Target>
The command in "Command" parameter will only execute if this condition is met.

Resources