Как запустить и остановить IIS Express из TeamCity? - PullRequest
1 голос
/ 14 марта 2012

Я вполне могу делать что-то странное, но я не уверен. Я пытаюсь настроить агент сборки TeamCity на компьютере с Windows XP, на котором установлен IIS Express. Я хотел бы создать шаг сборки, который запустит IIS Express, а затем еще один шаг сборки, который остановит его.

Я могу создать шаг построения командной строки, чтобы запустить экземпляр IIS Express с помощью команды, подобной следующей:

"C:\Program Files\IIS Express\iisexpress.exe" /path:%1\src\Web /port:80 /systray:false

Это запускает сервер, но затем в моем журнале написано «Введите« Q », чтобы остановить IIS Express», и шаг ждет. Я не хочу ждать этапа сборки. Я хочу, чтобы сборка перешла на следующий шаг.

У кого-нибудь есть мысли по этому поводу?

Ответы [ 2 ]

5 голосов
/ 30 марта 2013

Ответ сложнее, чем написание простого пакетного файла, так как в большинстве случаев вам нужно подождать, пока IIS Express не будет запущен, затем выполнить некоторые функции, а затем снова остановить процесс IIS Express.

Этот последний этап важен, чтобы не запускать дубликаты сайтов с несколькими сборками, что приведет к ошибкам и неверным результатам. Нам также необходимо тщательно управлять процессами, чтобы приглашение «нажать Q для выхода» не блокировало наше приложение от продолжения и выполнения его основных функций.

Вот некоторый код, который я написал для консольного приложения на C # для запуска Phantom.JS, который будет делать именно это, также он должен изящно обрабатывать сценарии, в которых возникают ошибки.

using System;
using System.Diagnostics;
using System.Threading.Tasks;

internal class Program
{
    private static int Main(string[] args)
    {
        string iisExpressPath = args[0];
        string websitePath = args[1];
        string websitePort = args[2];
        string phantomJSPath = args[3];
        string jsControllerPath = args[4];

        var startIisTask = StartIis(iisExpressPath, websitePath, websitePort);

        Process iisexpress;
        try
        {
            iisexpress = startIisTask.Result;
        }
        catch (Exception)
        {
            Console.Write("An error occurred while starting IIS express");
            return -1;
        }

        if (iisexpress != null)
        {
            var phantomJS = new Process();
            phantomJS.StartInfo.FileName = phantomJSPath;
            phantomJS.StartInfo.Arguments = jsControllerPath;

            phantomJS.StartInfo.UseShellExecute = false;
            phantomJS.StartInfo.RedirectStandardOutput = true;

            var tcs = new TaskCompletionSource<bool>();

            phantomJS.Start();

            Task.Run(
                () =>
                {
                    string str;
                    while ((str = phantomJS.StandardOutput.ReadLine()) != null)
                    {
                        if (str == "Unable to load the address!")
                        {
                            tcs.SetException(new ArgumentException(str));
                            return;
                        }

                        Console.WriteLine(str);
                    }

                    tcs.SetResult(true);
                });

            try
            {
                var complete = tcs.Task.Result;
            }
            catch (Exception)
            {
                phantomJS.Kill();
                iisexpress.Kill();
                return -1;
            }

            iisexpress.Kill();
            return 0;
        }

        Console.Write("An error occurred while starting IIS express");
        return -1;
    }

    private static Task<Process> StartIis(string iisExpressPath, string websitePath, string websitePort)
    {
        var tcs = new TaskCompletionSource<Process>();

        var iisexpress = new Process();
        iisexpress.StartInfo.FileName = iisExpressPath;
        iisexpress.StartInfo.Arguments = string.Format("/path:{0} /port:{1}", websitePath, websitePort);
        iisexpress.StartInfo.RedirectStandardOutput = true;
        iisexpress.StartInfo.UseShellExecute = false;
        iisexpress.EnableRaisingEvents = true;

        // Implicit capture is ok here as we are capturing an object we need later.
        iisexpress.Exited += IisexpressOnExited(tcs);

        iisexpress.Start();

        Task.Run(
            () =>
            {
                string str;
                while ((str = iisexpress.StandardOutput.ReadLine()) != null)
                {
                    if (str.Contains("IIS Express is running"))
                    {
                        iisexpress.Exited -= IisexpressOnExited(tcs);
                        tcs.SetResult(iisexpress);
                    }
                }
            });

        return tcs.Task;
    }

    private static EventHandler IisexpressOnExited(TaskCompletionSource<Process> tcs)
    {
        return (sender, args) => tcs.TrySetCanceled();
    }
}

Приложение также перенаправит вывод phantom.js на собственную консоль, чтобы вы могли использовать его для запуска модульных тестов на стороне клиента, но его можно легко адаптировать для любого шага сборки, который может потребовать хостинга.

Если вам нужна дополнительная информация, см. Мой пост о том, как запускать модульные тесты Jasmine из TeamCity с IIS express: http://roysvork.wordpress.com/2013/03/29/running-jasmine-tests-hosted-in-iis-express-as-part-of-a-teamcity-build/

2 голосов
/ 14 марта 2012

Напишите исполняемый файл или командный файл простой оболочки, который принимает те же аргументы, что и iisexpress.exe, и эта оболочка может запустить iisexpress.exe с заданными аргументами командной строки и немедленно вернуться.

...