How to Automate Publish using Cruise control and MsBuild - msbuild

I tried to automate update, build and Publish using cruise Control, SVN and Ms build . Take update from svn repository and build is working fine but publishing time, in the bin folder only the project dlls are coming , but other dlls like 'system.web' , 'Newtonsoft.Json' , etc and many more dlls are not updating. My 'ccnet.config' file is given :
<cruisecontrol xmlns:cb="urn:ccnet.config.builder" xmlns="http://thoughtworks.org/ccnet/1/8">
<project name="MyProjectBuild" queue="Q1" queuepriority="1">
<sourcecontrol type="svn">
<trunkurl>https://ip/svn//trunk/CruiseControlTest</trunkurl>
<workingdirectory>F:\CruiseControlPOC\src</workingdirectory>
<username>username</username>
<password>password</password>
</sourcecontrol>
<tasks>
<msbuild>
<executable>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable>
<workingdirectory>F:\CruiseControlPOC\BuildScript\</workingdirectory>
<projectfile>Build.xml</projectfile>
</msbuild>
</tasks>
</project>
</cruisecontrol>
My 'Build.xml' file which 'ccnet.config' refer is given here:
<target name="Run">
<calltarget targets="Compile" />
<calltarget targets="DoPublish" />
</target>
<target name="Compile">
<msbuild projects="..\src\HelloWorld\HelloWorld.sln" />
</target>
<target name="DoPublish">
<msbuild projects="..\src\HelloWorld\HelloWorld\HelloWorld.csproj" targets="_CopyWebApplication;_BuiltWebOutputGroupOutput" properties="OutDir=..\Output\;WebProjectOutputDir=..\..\..\Publish\HelloWorldSite\;"> </msbuild>
<copy sourcefiles="..\Output\" destinationfolder="..\Publish\HelloWorldSite\bin\"> </copy>
</target>
Can anyone tell how to use copy command so as to copy build dlls from Output folder to Publish/bin folder , or is there any other to Publish files using MsBuild and Cruise Control. Thanks

You could add another task after your MSBuild task in the ccnet.config to call a Power Shell script after the build like so:
<exec>
<executable>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</executable>
<baseDirectory>D:\Tools</baseDirectory>
<buildArgs>-File "D:\Tools\ProgramNamePostBuildTasks.ps1"</buildArgs>
<buildTimeoutSeconds>600</buildTimeoutSeconds>
</exec>
Then in your powershell script you could use xcopy to copy files where ever you want. If you are going to copy the files to a server, you will need to map a connection to the server first. But here is a simple example of how the powershell script will look:
del "D:\Binfolder\*.*"
xcopy "D:\OutputDirectory\ProgramX.dll" "D:\BinFolder\"

Related

.NET Core msbuild ProjectReference

I have a solution that contains a console application with a .csproj file like the this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
</Project>
I also have a library project that uses the console application to generate a heap of C# code that get compiled into the library, the library .csproj file looks like this.
<Project Sdk="Microsoft.NET.Sdk" InitialTargets="RunGenerator">
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../generator/generator.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Target Name="RunGenerator">
<Exec Command="dotnet run -p "../generator/generator.csproj" input output" />
</Target>
</Project>
This fails because the dependency analysis says that a netstandard1.4 assembly cannot reference a netcoreapp1.1 assembly. That is correct except that I am not referencing the assembly.
I can work around that issue by building the generator project like this:
<Project Sdk="Microsoft.NET.Sdk" InitialTargets="RunGenerator">
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
</PropertyGroup>
<Target Name="RunGenerator">
<Exec Command="dotnet build "../generator/generator.csproj"" />
<Exec Command="dotnet run -p "../generator/generator.csproj" input output" />
</Target>
</Project>
The problem is that the generator project no longer takes part in the dependency analysis when these projects are built using the containing solution file and the explicit build of the generator project sometimes runs concurrently with another build of the same project initiated by the solution build and this results in errors because files are locked etc.
Is it possible to have a project dependency without checking the target framework?
Can anyone suggest a workaround?
Thanks.
Here are some MSBuild tips. You might need to combine a few of these ideas.
You can use your solution file to add an explicit project dependency. See https://learn.microsoft.com/en-us/visualstudio/ide/how-to-create-and-remove-project-dependencies (This question was originally asked here: Visual Studio 2010: How to enforce build order of projects in a solution?). Unfortunately, this is really hard to do if you don't have VS. The format is .sln files is kinda a nightmare.
To avoid the concurrent build issue, use the MSBuild task instead of the Exec task. See https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-task
<Target Name="CompileAnotherProject">
<MSBuild Projects="../generator/generator.csproj" Targets="Build" />
</Target>
dotnet-run invokes "dotnet build" automatically. This is actually problematic in concurrent builds. You can instead add a target to your generator.csproj that runs the app after it has been built. "dotnet filepath.dll" runs the compiled app without building it.
<Target Name="RunCodeGen" AfterTargets="Build">
<Exec Command="dotnet $(AssemblyName).dll input output"
WorkingDirectory="$(OutDir)" />
</Target>

MC.exe in msbuild

How do I compile with mc.exe in the correct way. Currently I have a build step which runs the relevant command but looking at developer network
There seems to be a better way.
I am not a expert with msbuild so please excuse how easy this question is. Googling has revealed no help
<Project
DefaultTargets="Build"
ToolsVersion="14.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Message Source Files">
<Extensions>mc;</Extensions>
<UniqueIdentifier>{B796B525-44D3-4260-8C76-705DBADA1043}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<MessageCompile Include="a.mc">
<GenerateBaselineResource>true</GenerateBaselineResource>
</MessageCompile>
</ItemGroup>
<Target Name="Build">
<DontKnowWhatGoesHere Sources="#(MessageCompile)"/>
</Target>
</Project>
MSBuild build are usually extended via .targets files, that have to be included in the project, and they extend the existing build proces. The WDK tasks for MSBuild page confirms this:
These command-line tools need to be exposed to MSBuild as tasks (contained in targets) so that they can be run during the build process.
The WDK MSDN page also has a help page on Windows driver targets:
The WindowsDriver.Common.targets, WindowsDriver.masm.targets, and WindowsDriver.arm.targets files provide the targets that are necessary to build a driver.
A quick grep in my C:\Program Files (x86)\Windows Kits\10\build directory showed that the MessageCompile target (the step that actually processes the MessageCompile items) is defined in the build\WindowsDriver.Common.targets file.
After importing the targets in your project you can do one of the following:
<Import
Project="C:\Program Files (x86)\Windows Kits\10\build\build\WindowsDriver.Common.targets" />
<!-- Option A: -->
<Target Name="Build" DependsOnTargets="MessageCompile">
<!-- no need to do anything, the dependency target should do the work -->
</Target>
<!-- Option B: -->
<Target Name="Build" DependsOnTargets="MessageCompile">
<!-- Use the Mc task which is the actual wrapper around the .exe,
see the .common.targets file for the list of all parameters -->
<Mc
Sources ="#(MessageCompile)"
ToolExe ="$(MessageCompileToolExe)"
ToolPath ="$(MessageCompileToolPath)"
Generated
/>
</Target>

MSBuild CreateItem condition include based on config file

I'm trying to select a list of test dlls that contain corresponding config files
MyTest.Tests.dll
MyTest.Tests.config
I have to use a createItem as the dlls are not available at the time of the script loading
<CreateItem Include="$(AssemblyFolder)\*.Tests.dll"
Condition="???"
<Output TaskParameter="Include" ItemName="TestBinariesWithConfig"/>
</CreateItem>
Is there a condition I can use or is this the wrong approach?
Thanks
Mac
EDIT:
ok, to clarify, I need to construct a xUnit.Net project file. I need to do this because I'm running the tests through the xUnit.Console runner via nCover (don't ask!) but the long and short of it is I can only use a project file. The problem I'm having is when I have a test dll with an associated .config file. Without the config file, the test runner will fail.
This means I need to conditionally add an extra attribute (config-file) in the test project file.
The project template file:
<?xml version="1.0" encoding="utf-8"?>
<xunit>
<assemblies>
<!-- SAMPLE <assembly filename="Tests.dll" shadow-copy="false" config-file="Tests.dll.config" /> -->
<!-- #TARGETS# -->
</assemblies>
</xunit>
The FileUpdate task for the test dlls with no config file.
<FileUpdate
Files="$(AssemblyFolder)\$(XUnitProjectFileName)"
Regex="<!-- #TARGETS# -->"
ReplacementText="<!-- #TARGETS# -->%0D%0A<assembly filename='$(AssemblyFolder)\%(TestBinaries.FileName)%(TestBinaries.Extension)' shadow-copy='false' />"
/>
So I need a way to conditionally add the extra attribute in the FileUpdate task depending on whether there is a corresponding config file for the test dll.
You could just use the MSBuild Task output as a source for your CreateItem Task.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectReferences Include="*.*proj" />
</ItemGroup>
<Target Name="BuildMyProjects">
<MSBuild
Projects="#(ProjectReferences)"
Targets="Build">
<Output
TaskParameter="TargetOutputs"
ItemName="AssembliesBuiltByChildProjects" />
</MSBuild>
</Target>
<Target Name="AddConfigMetadata" DependsOnTargets="BuildMyProjects">
<CreateItem
Include="#(AssembliesBuiltByChildProjects)"
AdditionalMetadata="config-file=%(Identity).config">
<Output
TaskParameter="Include"
ItemName="MySourceItemsWithMetadata" />
</CreateItem>
</Target>
<Target Name="WhatEverYouLikeToDo" DependsOnTargets="AddConfigMetadata">
<Message Text="%(MySourceItemsWithMetadata.config-file)" />
</Target>
</Project>
Your problem discription isn't really clear to me, but your .Tests.dll's should always be available because you should build your project first before testing it. Whenever you've build your project, you can run the CreateItem task. The CreateItem is a good approach to retrieve the .dll's but you don't need a condition for it.
So in your build file you should have something like this:
- Build project/solution
-> .dll's will be created
- Execute CreateItem
- Do something with the Item
With this awnser I'm assuming you're trying to automate your tests?

Problems using MsBuild using command line for Publish Click Once

I have Windows application in csproj in my solution, and I want generate Publish using command line (bat, cmd).
My script is (I put \r\n for better reading):
SET MSBUILD="%SystemRoot%\Microsoft.NET\Framework\v3.5\MSBuild.exe"
SET CARWIN="..\..\Security.CarWin.csproj"
rem msbuild para publish
%MSBUILD% /target:rebuild;publish %CARWIN%
/p:ApplicationVersion="1.0.0.0"
/p:Configuration=release
/p:PublishUrl="C:\ClickOnce\CarWin.WebInstall\Publicacion\"
/p:InstallUrl="http://desserver/carwinclickonce/Publicacion/"
/p:PublishDir="C:\ClickOnce\CarWin.WebInstall\Publicacion\"
note: I'll try too using /target:publish
But in path PublishDir or PublishUrl (C:\ClickOnce\CarWin.WebInstall\Publicacion) not generates any files.
I have seen many posts in this site and google but I not found any solution.
Use PublishDir instead of PublishUrl when running from command line.
msbuild /target:publish /p:Configuration=Release;PublishDir=c:\playground\
You can also change version, like ApplicationRevision=666;MinimumRequiredVersion=1.1
Take a look at this Stack Overflow question. Basically the PublishUrl property is ignored when running ClickOnce from the command line. But you can easily add the behaviour with an additional MSBuild-task.
I've created an additional MSBuild-File, for example a build.csproj. This contains a publish-task. This task first invokes the regular MS-Build of the target-project. Afterwards it copies the result to the publish-directory. Now I invoke the 'build.csproj' instead of the reguar project-file from the command-line:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Publish" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- project name-->
<ProjectName>MyExampleProject</ProjectName>
<!--properties for the project-build-->
<DefaultBuildProperties>Configuration=Release</DefaultBuildProperties>
<!-- location of the click-once stuff, relative to the project -->
<ProjectPublishLocation>.\bin\Release\app.publish</ProjectPublishLocation>
<!-- Location you want to copy the click-once-deployment. Here an windows-share-->
<ProjectClickOnceFolder>\\TargetServer\deployments</ProjectClickOnceFolder>
</PropertyGroup>
<Target Name="Publish" DependsOnTargets="Clean">
<Message Text="Publish-Build started for build no $(ApplicationRevision)" />
<!-- run the original build of the project -->
<MSBuild Projects="./$(ProjectName).csproj"
Properties="$(DefaultBuildProperties)"
Targets="Publish"/>
<!-- define the files required for click-once-->
<ItemGroup>
<SetupFiles Include="$(ProjectPublishLocation)\*.*"/>
<UpdateFiles Include="$(ProjectPublishLocation)\Application Files\**\*.*"/>
</ItemGroup>
<!-- and copy them -->
<Copy
SourceFiles="#(SetupFiles)"
DestinationFolder="$(ProjectClickOnceFolder)\"/>
<Copy
SourceFiles="#(UpdateFiles)"
DestinationFolder="$(ProjectClickOnceFolder)\Application Files\%(RecursiveDir)"/>
</Target>
<Target Name="Clean">
<Message Text="Clean project" />
<MSBuild Projects="./$(ProjectName).csproj"
Properties="$(DefaultBuildProperties)"
Targets="Clean"/>
</Target>
</Project>
I don't know if this is a problem, but I noticed that you pass the /target parameter twice?
you could you use a semi-colon delimited example:
/target:rebuild;publish
MSDN Documentation on command line parameters and MSBuild
If that also does not work you could perhaps try to debug it by passing
/verbosity:diag

Copy files from one project to another after build

I have a project for all my javascripts in side (that I made common for three projects).
During a build I want to move these scripts to the three projects, how can I do this by editing .csproj and how?
Update:
I have in the same solution webapplication1 and webapplication2 and i'm editing .csproj for webapplication1, and i want to copy all files in test folder
<Target Name="AfterBuild">
<Copy SourceFiles="$(WDTargetDir)test\"
DestinationFolder="$(SolutionRoot)WebApplication2">
</Copy>
</Target>
However nothing is happening.
There is two ways to do that:
_ Edit the .csproject, at the end of the file you should find a Target named AfterBuild (uncomment the target).
<ItemGroup>
<JavascriptFiles Include="*.js"/>
</ItemGroup>
<Target Name="AfterBuild">
<Copy
SourceFiles="#(JavascriptFiles)"
DestinationFolder="PathWhereYouWantToCopyYourJavascriptFiles"
/>
</Target>
_ Post build events in visual studio (in project properties)
I found my solution:
<Target Name="AfterBuild">
<Copy SourceFiles="test\CodeFile1.cs"
DestinationFolder="..\WebApplication2\scripts">
</Copy>
</Target>
If you can use Visual Studio to build then use post build events in visual studio. Failing that if you have access to the command line just issue a copy command