我可能会做一些奇怪的事情,但我不确定。我正在尝试在安装了IIS Express的Windows XP计算机上配置TeamCity构建代理。我想创建一个构建步骤,它将启动IIS Express,然后是另一个构建步骤,它将阻止它。
我可以使用类似于以下的命令创建命令行构建步骤来启动IIS Express实例:
"C:\Program Files\IIS Express\iisexpress.exe" /path:%1\src\Web /port:80 /systray:false
这启动了服务器,但随后我的日志显示“输入'Q'以停止IIS Express”并且步骤等待。我不希望构建步骤等待。我希望构建进入下一步。
有没有人对此有任何想法?
答案 0 :(得分:4)
答案比编写简单的批处理文件更复杂,因为在大多数情况下,您需要等到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的输出传递给它自己的控制台,以便您可以使用它来运行客户端单元测试,但可以轻松地适应可能需要托管的任何构建步骤。
如果您想了解更多信息,请参阅我的帖子,了解如何使用IIS Express在TeamCity中运行Jasmine单元测试:http://roysvork.wordpress.com/2013/03/29/running-jasmine-tests-hosted-in-iis-express-as-part-of-a-teamcity-build/
答案 1 :(得分:2)
编写一个简单的包装器可执行文件或批处理文件,其参数与iisexpress.exe完全相同,并且包装器可以使用给定的命令行参数启动iisexpress.exe并立即返回。