如何从TeamCity中启动和停止IIS Express?

Gar*_*ton 1 teamcity iis-express

我可能会做一些奇怪的事情,但不确定。我正在尝试在安装了IIS Express的Windows XP计算机上配置TeamCity构建代理。我想创建一个将启动IIS Express的构建步骤,然后再另一个将其停止的构建步骤。

我可以创建一个命令行构建步骤,以使用类似于以下命令的方式启动IIS Express实例:

"C:\Program Files\IIS Express\iisexpress.exe" /path:%1\src\Web /port:80 /systray:false
Run Code Online (Sandbox Code Playgroud)

这将启动服务器,但随后我的日志显示“输入'Q'以停止IIS Express”,并且该步骤等待。我不想等待构建步骤。我希望构建可以进行下一步。

有人对此有任何想法吗?

bey*_*ode 5

答案比编写简单的批处理文件要复杂得多,因为在大多数情况下,您将需要等到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();
    }
}
Run Code Online (Sandbox Code Playgroud)

该应用程序还将phantom.js的输出通过管道传输到其自己的控制台,因此您可以将其用于运行客户端单元测试,但也可以轻松地适应可能需要托管的任何构建步骤。

如果您需要更多信息,请参阅我的有关如何通过IIS Express在TeamCity中运行Jasmine单元测试的文章:http : //roysvork.wordpress.com/2013/03/29/running-jasmine-tests-hosted-in-iis表示为团队建设的一部分/