nant vs. msbuild: stopping a service - msbuild

I'm trying to decide which side I'm on in the MsBuild vs. Nant war. I'm starting with: stop a service, deploy some files, restart the service. Just from looking at these two links, that is much easier to do in Nant.
MSBuild: Example of using Service Exists MSBuild task in Microsoft.Sdc.Tasks?
<target name="service_exists">
<script language="C#">
<references>
<include name="System.ServiceProcess.dll" />
</references>
<code><![CDATA[
public static void ScriptMain(Project project) {
String serviceName = project.Properties["service.name"];
project.Properties["service.exists"] = "false";
project.Properties["service.running"] = "false";
System.ServiceProcess.ServiceController[] scServices;
scServices = System.ServiceProcess.ServiceController.GetServices();
foreach (System.ServiceProcess.ServiceController scTemp in scServices)
{
etc...
Nant: http://ryepup.unwashedmeme.com/blog/2007/01/04/restart-a-windows-service-remotely/
<!-- Send the stop request -->
<exec program="sc.exe">
<arg line="\\server stop shibd_Default"/>
</exec>
<!-- Sleep a little bit, to give the service a chance to stop -->
<sleep seconds="5"/>
<!-- Send the start request -->
<exec program="sc.exe">
<arg line="\\server start shibd_Default"/>
</exec>
I wonder if the SO community agrees with me. Is it much easier to get basic things like this done in Nant? Sure looks that way. C# code in a CDATA block? WTF?
Our current build process is a) lots of bat files b) lots of cursing. I'd really like to find a good replacement, but that MsBuild stuff looks like a world of pain to my eyes. I'm thinking the way to go is to build scripts in Nant, then use MsBuild to do any .NET builds that need to be done.
One important question: which one is better at catching errors in the script before the script is run? I was thinking of rolling my own here and that was very important part of it: line up all your data and make sure that it makes sense before attempting to run.

In msbuild you could also use the ServiceController task that is packaged in the msbuild community tasks.

You can execute sc.exe using MSBuild every bit as easily ...
<Exec Command="sc.exe \\server stop shibd_Default" />
By default this will "fail" if the exit code (of sc.exe) is non-zero, but that can be customized.

With Nant, there are 2 other ways to stop a service, and one is able to track an error.
First one (using Net Stop):
<exec program="net" failonerror="false"><arg value="stop"/><arg value="${serviceName}"/></exec>
Second one (much cleaner):
<servicecontroller action="Stop" service="${serviceName}" if="${service::is-installed(serviceName,'.') and service::is-running(serviceName,'.')}" />
Note that the second line verifies that the service already exists and is running, which allows to track any weird error.

In addition to #nulpptr's answer for MSBuild, if you don't have the option of using the community tasks, you might have to resort to a hack to wait for your service to stop before moving on. If you have the resource kit you can use the EXEC task with the sleep command.
No resource kit? Use the ping trick...
However, if you don't have the resource kit, you can use the ping trick to force a delay. For instance, the following will stop your service using the sc command, and then pause for about 5 seconds:
<Exec Command="sc.exe \\server stop shibd_Default" ContinueOnError="true" />
<Exec Command="ping 127.0.0.1 -n 5 > nul" ContinueOnError="true" />

Related

Wait for an Exec task to finish

One of my msbuild targets works as following:
get configuration files
start window service with those configuration files
exec service specific task
stop window service
repeat
The issue is that sometimes service stop executable task (Exec Command="sc stop myservice") takes longer time and when "sc start myservice" is called it says that service is already running. So my question is: how can I wait for "exec" command ot finish? I tried to put each executable in target and call with "CallTarget" and putting appropriate "DependsOnTargets" or "AfterTargets" and it didn't work. Can you help me? Thanks in advance.
The problem was that Exec actually did finished command execution (he simply thrown "sc stop myservice") and after that another exec started to work. I added timeout for the "sc start myservice" for a minute and it solved. The result looked like:
<Exec Command="sc stop myservice" ContinueOnError="true" />
<Exec Command="sc start myservice" ContinueOnError="true" Timeout="60000" />

Make an HTTP request from MSBuild script

I'm looking for a way to hit a web app/restful service URL from msbuild script to trigger remote procedure.
Is there any way how I can do that except calling that external app?
Ideally I'm looking for a way to break a build sequence if service returned something else that http 200
I use the MSBuild Community Tasks a lot. They add extra tasks for MSBuilds. In there is a HttpRequest task which, from the look of it, does what you want.
<HttpRequest Url="http://<mydomain.com>/index.php?checkdb=1"
EnsureResponseContains="Database upgrade check completed successfully."
FailOnNon2xxResponse="true" />
Hope this helps
In version 4 of the MSBuild Community Tasks, the HttpRequest task was replaced by HttpWebRequest with a different syntax:
<MSBuild.ExtensionPack.Web.HttpWebRequest
TaskAction="GetResponse" Url="http://www.freetodev.com">
<Output TaskParameter="Response" ItemName="ResponseDetail"/>
<Output TaskParameter="Status" PropertyName="ResponseStatus"/>
</MSBuild.ExtensionPack.Web.HttpWebRequest>

How can I remotely start/stop a service using MSBuild?

I'd like to remotely start or stop a windows service on another machine using MSBuild. To accomplish this, I wrote this script:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="C:\Program Files (x86)\MSBuild\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<Target Name="MyTarget">
<ServiceController MachineName="Box2" ServiceName="MyService" Action="Stop" />
</Target>
</Project>
When I run that on a machine that can see Box2, I get this:
Project
"C:\Scripts\Test.xml" on node 1 (default
targets).
C:\Scripts\Test.xml(4,5): error : Couldn't
find the 'MyService'
service on 'Box2' Done Building
Project
"C:\Scripts\Test.xml" (default targets) --
FAILED.
I know that I have the service name correct (I copied and pasted it from the actual service list), and I'm pretty sure that it can see Box2 because if I change it to a machine name that doesn't exist (e.g. Box2asdf), it takes about 10 seconds to come back (with the exact same error, mind you), as opposed to the nearly immediate response that I get when I provide the correct machine name.
How might I debug this issue?
You might try this instead...
You can use the command line program sc and execute that...
ie
SC \ServerName stop ServiceName
http://support.microsoft.com/kb/166819
For more information on how to execute a command from msbuild check this out..
execute a command with parameters using msbuild
The community tasks should work. Just use Sc query to check that the service does work. as for using msbuild its still using msbuild if you wrap sc in an exec?
At least you dont have a dependency on a third party dll in your build process.
ServiceController Target internally uses ServiceController Class. But it doesn't return the reason why it couldn't find the service. If you are shure that both computer and service names are correct, the next thing I can suggest to analyze is access violation problems.
And #jsobo's answer can be very useful to diagnose the actual reason because it can show native errors without .Net exception wrappers around them:
sc.exe \Box2 stop MyService

CruiseControl.Net and NUnit - tests finish, but task doesn't?

I've got a CruiseControl.Net setup using Nant to clean the previous logs, and then it kicks off a msbuild of a VS project, finally running nunit-console to execute the tests.
It seems to build for a few seconds (fine) and then hops on to running the 600 tests, which takes about a minute. However even though the log files are there, it sits there doing 'nothing' for 10 minutes, at which point the built times out and the process exits. The CruiseControl.NET webpage then shows the result as failed, with an exception:
ThoughtWorks.CruiseControl.Core.Tasks.BuilderException: Command Line Build timed out (after 600 seconds)
at ThoughtWorks.CruiseControl.Core.Tasks.ExecutableTask.Execute(IIntegrationResult result)
at ThoughtWorks.CruiseControl.Core.Tasks.TaskBase.Run(IIntegrationResult result)
at ThoughtWorks.CruiseControl.Core.Project.RunTask(ITask task, IIntegrationResult result, Boolean isPublisher)
at ThoughtWorks.CruiseControl.Core.Project.RunTasks(IIntegrationResult result, IList tasksToRun, Dictionary`2 parameterValues)
at ThoughtWorks.CruiseControl.Core.Project.Run(IIntegrationResult result)
at ThoughtWorks.CruiseControl.Core.IntegrationRunner.Build(IIntegrationResult result)
at ThoughtWorks.CruiseControl.Core.IntegrationRunner.Integrate(IntegrationRequest request) BaseDirectory: , Executable: C:\Program Files\NUnit 2.5.8\bin\net-2.0\nunit-console.exe
The ccnet.config script is below. I've tried changing the timeout to 3 minutes just in case that was something to do with it, but even if that did work (it didn't) it's a dodgy hack, as by rights when the tests are finished running, they should exit gracefully!
I've run the command at the commandline and confirmed it only takes about a minute to run. Any theories?
<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
<project name="CodeTests">
<workingDirectory>C:\Source\Wholesale\Comp.EventControl.TestingFramework\</workingDirectory>
<artifactDirectory>C:\Source\Wholesale\Comp.EventControl.TestingFramework\</artifactDirectory>
<prebuild>
<!-- clean nunit output to avoid CCNET reporting
about previous build tests if current build fails -->
<nant>
<executable>C:\Nant\bin\nant.exe
</executable>
<baseDirectory>C:\Source\Wholesale\Comp.EventControl.TestingFramework</baseDirectory>
<nologo>false</nologo>
<buildFile>nant.build</buildFile>
<targetList>
<target>cleanNunit</target>
</targetList>
</nant>
</prebuild>
<tasks>
<msbuild>
<executable>C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
</executable>
<workingDirectory>C:\Source\Wholesale\Comp.EventControl.TestingFramework\CodeReboot
</workingDirectory>
<projectFile>CodeReboot.sln</projectFile >
<buildArgs>/noconsolelogger
/v:quiet
/noconlog
/p:Configuration=Debug
/p:ReferencePath="C:\Program Files\NUnit 2.5.8\bin;C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"
/p:AdditionalReferencePath="C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"
</buildArgs>
<targets>ReBuild</targets >
<timeout>180</timeout >
<logger>c:\Program Files\CruiseControl.NET\server\Rodemeyer.MsBuildToCCNet.dll</logger>
</msbuild>
<exec>
<executable>C:\Program Files\NUnit 2.5.8\bin\net-2.0\nunit-console.exe
</executable >
<buildArgs>/xml:C:\Source\Wholesale\Comp.EventControl.TestingFramework\nunit-results.xml
/nologo C:\Source\Wholesale\Comp.EventControl.TestingFramework\CodeReboot\CodeReboot\bin\Debug\CodeReboot.dll
</buildArgs>
</exec>
</tasks>
<publishers>
<merge>
<files>
<file>C:\Source\Wholesale\Comp.EventControl.TestingFramework\nunit-results.xml
</file>
</files>
</merge>
<xmllogger />
<statistics />
<artifactcleanup cleanUpMethod="KeepLastXBuilds"
cleanUpValue="20" />
</publishers>
</project>
</cruisecontrol>
What version of nunit are you using? There were some problems in the 2.5.7/2.5.8 version that causes nunit-agent to hang at the end of a test. I had this problem and reverted back to an older version of nunit and the hang problem went away. In the release notes for 2.5.9 they show that "602761 nunit-agent hangs after tests complete" has been fixed. I have not upgraded to 2.5.9 yet but that may fix your problem.
The first thing you should do try and replicate the problem locally. Do your tests run properly and exit cleanly? Run them locally and see if the nunit process hangs around.
If your tests run fine locally, try and figure out which test the build server is stalling on or whether it is completing all of the tests. If your build scripts cannot be run locally, it's a bit harder to diagnose.
Back in the day when our tests were riddled with threaded code, it was nearly always the case that a test (or the code under test) was creating threads and then failing to shut them down, causing NUnit to hang around. Threading issues are irritating because they're non-deterministic may only be visible when run on machines with more cores (like .. build servers).
If you have tests with threading / external dependencies, I'd try disabling those first (the fact that 600 tests takes a minute to run indicates that external dependencies and/or threading is involved, as a unit test usually takes ~1ms to run).

How do I start my Java program with more than one java agent?

I'm aware of how to start a java progam with a java agent:
java -javaagent:myAgent.jar MyJavaProgram
But what if I want to add 2 or more java agents to instrument my program? I do not want to reinvoke the java -javaagent:... for every agent I have to load in JVM.
I've tried something like this :
java -javaagent:agentA.jar, agentB.jar MyJavaProgram
or something like this:
java -javaagent:agentA.jar agentB.jar MyJavaProgram
But have no success.
Is there an answer to solve my problem ?
Thank you.
How about two javaagent parameters?
java -javaagent:agentA.jar -javaagent:agentB.jar MyJavaProgram
It would appear you can do this by using multiple arguments. From the documentation:
On implementations with a command-line interface, an agent is started by adding this option to the command-line:
-javaagent:jarpath[=options]
jarpath is the path to the agent JAR file. options is the agent options. This switch may be used multiple times on the same command-line, thus creating multiple agents. More than one agent may use the same jarpath. An agent JAR file must conform to the JAR file specification.
(my emphasis)
Adding to the above answers, if you are using ant and want to include <jvmargs /> with more than one jar to -javaagent to start the server, here's how I did it,
build.xml
<target name="blah">
...
<jvmarg value="-javaagent:${jar1.path}" />
<jvmarg value="-javaagent:${jar2.path}" />
...
</target>
There is a new project with the goal to support multiple Java agents. Currently it is limited to specific ones.
Agent Bond is a super agent, which wraps and dispatches on several other agents. That way, you only have to install a single agent within your JVM with a single set of configuration data (which contains multiple separate parts).
See https://github.com/fabric8io/agent-bond/blob/master/README.md for details