Geeks With Blogs

@moitoius
  • moitoius Warcraft II on my HTC Wizard (still waiting for the TyTN II), Apple eat your heart out... about 2206 days ago
  • moitoius getting my tytn II hopefully today! hold thumbs! about 2207 days ago
  • moitoius going to hillsong on the 22nd! yeah! about 2209 days ago
  • moitoius nearly home, ready for the weekend and ttf fun. about 2216 days ago
  • moitoius also trying my hand at ROAM landscapes. with geomorphs. in xna. hell yeah. about 2216 days ago
  • moitoius is very impressed with the twitter support in fring. about 2216 days ago

News This blog has moved to http://jonathan.dickinsons.co.za/blog.
Jonathan Dickinson Moved to: jonathan.dickinsons.co.za/blog

I am currently RNDing Continuous Integration for our build process, as well as automating certain build processes that we use throughout the company.

One issue that I found is that TFS Build Server 2005 plain refuses to build Visual Studio 2008 solution files, and after some research I found that it is because of the SLN version number. One method involves using a shim in place of MSBuild to call the .Net 3.5 MSBuild executable. The current shims are really weak and don't do the job properly, so I have made one that does.

It handles incoming input, as well as the standard out and error streams. This will allow MSBuild to report back to the server on things such as compile errors.

To use the tool, rename shim.exe to the name of the original file (in this case MSBuild.exe) and replace that file. Open regedit and create (or open) a key at HKLM\Software\jonathand\Shim. In this key place a new string value with the original file as the name and the new file as the value. The shim will now call the file as it should. This should theoretically also help with MSTest.exe (I think that's the name) when it comes to integrated unit tests.

HTH.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using Microsoft.Win32;
using System.Diagnostics;
using System.Threading;

namespace Shim
{
    class Program
    {
        private static Process _process;

        static int Main(string[] args)
        {
            if (TargetFile == "")
            {
                Console.Error.WriteLine("No target for shim found in registry for '{0}'.", EntryAssemblyFileName);
                return 9009; // File not found.
            }

            // Create process.
            _process = new Process();
            _process.StartInfo.Arguments = Arguments;
            _process.StartInfo.CreateNoWindow = true;
            _process.StartInfo.FileName = TargetFile;
            _process.StartInfo.RedirectStandardError = true;
            _process.StartInfo.RedirectStandardInput = true;
            _process.StartInfo.RedirectStandardOutput = true;
            _process.StartInfo.UseShellExecute = false;
            _process.StartInfo.WorkingDirectory = Environment.CurrentDirectory;

            // Wire up events.
            _process.OutputDataReceived += new DataReceivedEventHandler(_process_OutputDataReceived);
            _process.ErrorDataReceived += new DataReceivedEventHandler(_process_ErrorDataReceived);
            Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);

            _process.Start(); 
            _process.BeginErrorReadLine();
            _process.BeginOutputReadLine();

            // Create read thread.
            Thread readThread = new Thread(ReaderWorker);
            readThread.IsBackground = true; // Terminate when I terminate.
            readThread.Start();

            _process.WaitForExit();

            return _process.ExitCode;
        }

        static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
        {
            e.Cancel = true;
            _process.Kill();
        }

        static void ReaderWorker()
        {
            while (true)
            {
                string data = Console.ReadLine();
                _process.StandardInput.WriteLine(data);
            }
        }

        static void _process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            Console.Error.WriteLine(e.Data);
        }

        static void _process_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            Console.Out.WriteLine(e.Data);
        }

        private static string _targetFile;
        private static string TargetFile
        {
            get
            {
                if (_targetFile == null)
                {
                    using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\\jonathand\\Shim"))
                    {
                        if (key == null)
                            _targetFile = "";
                        else
                            _targetFile = (string)key.GetValue(EntryAssembly.ToLowerInvariant(), "");
                    }
                }
                return _targetFile;
            }
        }

        private static string _arguments;
        private static string Arguments
        {
            get
            {
                if (_arguments == null)
                {
                    _arguments = Environment.CommandLine;
                    int remString = EntryAssembly.Length + 1;
                    if (_arguments.StartsWith("\""))
                        remString += 2;
                    _arguments = _arguments.Remove(0, remString);
                }
                return _arguments;
            }
        }

        private static string _entryAssembly;
        static string EntryAssembly
        {
            get
            {
                if (_entryAssembly == null)
                {
                    _entryAssembly = Assembly.GetExecutingAssembly().CodeBase;
                    if (_entryAssembly.StartsWith("file:///"))
                        _entryAssembly = _entryAssembly.Remove(0, 8);
                    _entryAssembly.Replace('/', Path.DirectorySeparatorChar);
                }
                return _entryAssembly;
            }
        }

        private static string _entryAssemblyFileName;
        private static string EntryAssemblyFileName
        {
            get
            {
                if (_entryAssemblyFileName == null)
                    _entryAssemblyFileName = Path.GetFileName(EntryAssembly).ToLowerInvariant();
                return _entryAssemblyFileName;
            }
        }
    }
}
Posted on Thursday, September 18, 2008 8:37 PM C# , Tips | Back to top

Copyright © Jonathan Dickinson | Powered by: GeeksWithBlogs.net | Join free