![]() |
Contact Craig |
![]() |
Show Changes |
![]() |
Edit |
![]() |
|
![]() |
Recent Changes |
![]() |
Subscriptions |
![]() |
Lost and Found |
![]() |
Find References |
![]() |
Rename |
| Search |
History
| 6/3/2005 11:10:46 AM |
| CraigAndera-68.10... |
| 6/3/2005 1:25:43 AM |
| -67.82.29.165 |
| 1/26/2005 8:48:43 AM |
| CraigAndera |
![]() |
List all versions |
I wrote a blog post about how I set up a series of colored lights to turn on and off based on the status of a build at a client of mine. It looks like this:

A few people asked me for the code I wrote. As it was pretty simple, and since I got permission to post it, you can find it below. A few notes:
settings.xml in the same directory as the service executable. If it doesn't find one there, it writes one with some defaults. I realize that writing to the program directory isn't necessarily a great idea, but see #1. sc create BuildLights binPath= \path\to\the\exe. Notice the space after binPath=. ThoughtWorks.CruiseControl.CCTrayLib.dll and ThoughtWorks.CruiseControl.Remote.dll.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.ServiceProcess;
using System.Threading;
using System.Xml;
using System.Xml.Serialization;
using ActiveHomeScriptLib;
using ThoughtWorks.CruiseControl.CCTrayLib;
using ThoughtWorks.CruiseControl.Remote;
namespace Wangdera.BuildLightsSvc
{
public class App
{
static void Main(string[] args)
{
Console.WriteLine("Starting...");
// If the user specifies /console, run interactively until they hit enter
if (args.Length > 0 && args[0].ToLower() == "/console")
{
BuildLightsService service = new BuildLightsService();
service.Start();
Console.WriteLine("Hit enter to terminate");
Console.ReadLine();
service.Stop();
}
// Otherwise, run as a service
else
{
System.ServiceProcess.ServiceBase[] ServicesToRun;
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new BuildLightsService() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}
}
}
public class BuildLightsService : ServiceBase
{
private ActiveHome activeHome;
private Thread thread;
// Here's where we actually do the monitoring and turn lights on and off.
public void Run()
{
// The ActiveHome object is Apartment model, so this seems like a good idea.
Thread.CurrentThread.ApartmentState = ApartmentState.STA;
activeHome = new ActiveHomeClass();
// Turn everything off until we figure out where we're at
SetRedState(false);
SetGreenState(false);
SetYellowState(false);
Settings settings = ReadSettings();
StatusMonitor monitor = new StatusMonitor(settings);
try
{
// Loop forever, asking the project its status periodically. I could also have
// used monitor.StartPolling(), but I had problems with it. They're probably not
// related to StartPolling(), but I was too lazy to switch back.
while (true)
{
monitor.Poll();
SetLightsForStatus(monitor.ProjectStatus);
Thread.Sleep(settings.PollingIntervalSeconds * 1000);
}
}
// The service stops work here by causing a ThreadInterruptException to be thrown, so
// we do our cleanup in a finally block.
finally
{
SetRedState(false);
SetGreenState(false);
SetYellowState(false);
}
}
protected override void Dispose( bool disposing )
{
base.Dispose( disposing );
}
// This is called when the service receives a start command from the system
protected override void OnStart(string[] args)
{
Start();
}
// Kick off a new thread to do the monitoring
public void Start()
{
thread = new Thread(new ThreadStart(Run));
thread.Start();
}
// This is called when the service receives a stop command from the system.
protected override void OnStop()
{
Stop();
}
public void Stop()
{
// Cause an exception in the thread that's doing the monitoring
thread.Interrupt();
// and wait for it to finish what it's doing
thread.Join();
}
// Here's where we figure out what lights should be on
private void SetLightsForStatus(ProjectStatus status)
{
if (status.Status == ProjectIntegratorState.Running)
{
// The yellow light goes on whenever a build is in progress.
if (status.Activity == ProjectActivity.Building)
{
SetYellowState(true);
}
else
{
SetYellowState(false);
}
// Turn on the red light when the last build failed
if (status.BuildStatus == IntegrationStatus.Failure)
{
SetRedState(true);
SetGreenState(false);
}
// Turn on the green light when the last build succeeded
else if (status.BuildStatus == IntegrationStatus.Success)
{
SetRedState(false);
SetGreenState(true);
}
// Turn off the red and green lights when we don't know what happened with the last build
else
{
SetRedState(false);
SetGreenState(false);
}
}
// If the build service isn't running or we can't communicate with it, turn off all the lights
else
{
SetRedState(false);
SetGreenState(false);
SetYellowState(false);
}
}
// Read a file called settings.xml from the same directory as the EXE. If it's not there, create a new
// one with some defaults.
private Settings ReadSettings()
{
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "settings.xml");
Settings settings = null;
if (File.Exists(path))
{
XmlSerializer ser = new XmlSerializer(typeof(Settings));
XmlTextReader reader = new XmlTextReader(path);
try
{
settings = (Settings) ser.Deserialize(reader);
}
finally
{
reader.Close();
}
}
else
{
settings = new Settings();
settings.RemoteServerUrl = "tcp://your-build-machine-name-here:21234/CruiseManager.rem";
settings.PollingIntervalSeconds = 5;
XmlSerializer ser = new XmlSerializer(typeof(Settings));
XmlTextWriter writer = new XmlTextWriter(path, System.Text.Encoding.UTF8);
try
{
writer.Formatting = Formatting.Indented;
ser.Serialize(writer, settings);
}
finally
{
writer.Close();
}
}
return settings;
}
private void SetRedState(bool state)
{
SetItemState("a3", state);
}
private void SetYellowState(bool state)
{
SetItemState("a1", state);
}
private void SetGreenState(bool state)
{
SetItemState("a2", state);
}
private void SetItemState(string item, bool state)
{
string action = null;
if (state)
{
action = " on";
}
else
{
action = " off";
}
// Turning a light on or off is as simple as sending a "sendplc" command with an
// address of something like "a1 on" or "a3 off"
activeHome.SendAction("sendplc", item + action, null, null);
}
}
}
About FlexWiki.
Recent Topics