Calling RAKE from MSBUILD

These days, I am spending quite a bit of time with Ruby,  Ruby On Rails and RAKE. I am not into the Ruby religion yet,
and not drinking the ruby Kool-aid that much. Just a little.

I needed to integrate the TeamBuild (Team System) with Ruby/RAKE.  So in other words, I needed to
call RAKE from MSBUILD. It turned out to be slightly harder than I expected. I am new to MSBUILD, Ruby and RAKE,
so I had to figure out quite a few of things.

I ended up writing a custom task. From the custom task, I called Rake and captured the output.
Definitely not rocket science, but getting everything working properly is not easy either.

So here it is.

First the custom task.

Here is the entire code file

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Build.Framework;
using System.Diagnostics;
using System.IO;
namespace RubyIntegration
    public class RunRake : ITask
        private IBuildEngine engine;              
        public IBuildEngine BuildEngine
            get { return engine; }
            set { engine = value; }

        private ITaskHost host;
        public ITaskHost HostObject
            get { return host; }
            set { host = value; }

        private string RakeFileDir;
        public string RakeFileDirectory
            get { return RakeFileDir; }
            set { RakeFileDir = value; }

        private string RubyInstallDir;
        public string RubyInstallDirectory
            get { return RubyInstallDir; }
            set { RubyInstallDir = value; }
        private string RakeTargetName;
        public string RakeTarget
            get { return RakeTargetName; }
            set { RakeTargetName = value; }

        private string strOutput;
        public string RakeOutput
            get { return strOutput; }
            set { strOutput = value; }

        private void LogMessage(string message, MessageImportance imp)
            BuildMessageEventArgs args = new BuildMessageEventArgs(
                message, string.Empty, "RubyIntegration.RunRake", MessageImportance.Normal);

        public bool Execute()
            bool result = false;
                LogMessage("***** MSBUILD  <--> RAKE ********", MessageImportance.Normal);
                LogMessage("Preparing to invoke Rake", MessageImportance.Normal);
                LogMessage("*** INPUTS", MessageImportance.Normal);
                LogMessage("Ruby Install Directory " + RubyInstallDir, MessageImportance.Normal);
                LogMessage("Rake File Directory " + RakeFileDirectory, MessageImportance.Normal);
                LogMessage("RakeTargetName " + RakeTargetName, MessageImportance.Normal);
                LogMessage("***", MessageImportance.Normal);

                LogMessage("*** CHEKING PARAMETERS", MessageImportance.Normal);
                if (Directory.Exists(RubyInstallDir)){
                    LogMessage("Ruby Install Directory " + RubyInstallDir + " exists.", MessageImportance.Normal);
                    LogMessage("Ruby Install Directory " + RubyInstallDir + " does not exist - exiting task.", MessageImportance.High);
                string RubyPath = Path.Combine(RubyInstallDir, "ruby.exe");
                if (File.Exists(RubyPath))
                    LogMessage("Ruby.exe is found at " + RubyPath, MessageImportance.Normal);
                    LogMessage("Ruby.exe is not found at path" + RubyPath + " . - exiting task.", MessageImportance.High);
                string RakePath = Path.Combine(RubyInstallDir, "rake");
                if (File.Exists(RakePath))
                    LogMessage("rake file (rake ruby code) is found at " + RakePath, MessageImportance.Normal);
                    LogMessage("rake file (rake ruby code) is is not found at path" + RakePath + ". - exiting task.", MessageImportance.High);

                LogMessage("***", MessageImportance.Normal);
                ProcessStartInfo info = new ProcessStartInfo();
                info.RedirectStandardOutput = true;
                info.UseShellExecute = false;
                info.FileName = RubyPath;
                info.Arguments = RakePath + " "  + RakeTargetName;
                info.WorkingDirectory = RakeFileDirectory;
                Process p = Process.Start(info);
                strOutput = p.StandardOutput.ReadToEnd();
                result = true;
            catch (Exception ex)
                LogMessage(ex.ToString(), MessageImportance.High);
            return result;


Here is the MSBUILD FILE

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="">
  <UsingTask AssemblyFile="RunRake.dll" TaskName="RubyIntegration.RunRake" />
  <Target Name="default" >
    <RunRake    RubyInstallDirectory ="C:\ruby\bin"
      <Output TaskParameter="RakeOutput" PropertyName="RakeOutput"/>
    <Message Text="The output from Rake is... $(RakeOutput)" />


Fist I attempted to creating a RAKE process by trying to call rake.  (pass rake as the file name to the process start info).
The process failed to start saying that the file not found.
Then I tried with rake.bat
(pass rake.bat as the file name to the process start info).
The problem seems to be that RAKE.BAT does some
manipulation and calls ruby.exe and passes the file "rake" to ruby.exe.  Normally it would end up something like
[ruby.exe c:\ruby\bin\rake ..].
However The path to rake is getting resolved incorrectly when I pass the rake.bat as the
program name.  It is using the working directory and ending up with

[ruby.exe <MY WORKING DIR>\rake...]
Obviously there is no file called "rake"  in my working directory.
I need to resolve this, but for now this should get me going.


The installation for for Ruby could be possibly obtained by resolving
the file extension .rb to an executable. That is another task that can be added
to eliminate the need to send the ruby install directory as a parameter.

Comments (2)
  1. sgundu says:

    Hello, excuse me for being offtopic: I was searching for "nee meeda naaku, idayyo, andam ney daachalenu, padayyo" on youtube. One search led to another, and here I am! Footstomping music there on Eswara shows. Didn’t know you sang, though knew from college days you were a flautist. Passeable voice 😉 Drop a line at sikhivahan at gmail sometime.

    Re whether to be agile or not to be. You’re on the dot when you say that methodologies are irrelevant as long as programmers are self-disciplined. But that’s the crux of the matter: most aren’t, and many, the less experienced ones generally, don’t know to be.  They need to be disciplined, especially when somebody is paying them good money to build software. If you got a bunch of brilliant programmers working together, maybe you don’t need any methodology. A lot of quality open source is written without any. However in typical commercial software building environments, methodologies are better than having nothing. I look at the evolution of programming languages the same way. Couldn’t data encapsulation and information hiding be done in C?  Good programmers wrote modularized code with lean interfaces even in C. Of course, it would be simplistic to say that languages evolved to impose discipline on programmers but I believe that’s one implicit dimension to their evolution.

Comments are closed.

Skip to main content