ASP.NET MVC应用程序的自主
我有一个完整的工作ASP.NET MVC应用程序(包括5组件,.NET 4.5.1,ASP.NET MVC 5.2.2),它运行在Visual Studio精细(使用IISEx preSS)。
I have a full-working ASP.NET MVC application (consisting of 5 assemblies, .NET 4.5.1, ASP.NET MVC 5.2.2) which runs fine in Visual Studio (which uses IISExpress).
我现在想有一个控制台应用程序这需要在MVC应用程序并进行托管(自托管)。
I would now like to have a console application which takes the MVC application and hosts it (self hosting).
我试着用 Microsoft.Owin.Host.HttpListener
和 Nancy.Owin
但是当我拿到404页我配置中没有映射到我的MVC的应用程序。
I tried with Microsoft.Owin.Host.HttpListener
and Nancy.Owin
but while I get 404 pages my configurations lacks the mapping to my MVC-app.
我
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseNancy();
}
}
和
static void Main(string[] args)
{
StartOptions so = new StartOptions("http://localhost:9000/");
using (WebApp.Start<Startup>(so))
{
Console.WriteLine("Press Enter to Exit");
Console.ReadLine();
}
}
但很明显的配置,缺少使用 MyMvcApplication
从运行的MVC应用程序。怎么做?或如何否则selfhost呢?
But obviously the configuration to use MyMvcApplication
from the running MVC application is missing. How to do that? Or how to selfhost it otherwise?
我在网上找到的答案是指旧版本,我希望今天有一个更简单的方法。
The answers I found on the web refer to older versions and I was hoping to have a more easy way today.
由于ASP.NET vNext尚不可用,我的应用程序使用MVC5我会完全地迁移MVC应用程序南锡或类似的东西。 MVC5太dependend在IIS上。
As ASP.NET vNext is not yet available and my app uses MVC5 I would have to migrate the MVC app completly to Nancy or something similar. MVC5 is too dependend on IIS.
要解决这个同时,我决定在中间解决方案,性能是不是一个问题:
To solve this meanwhile I decided on an intermediate solution as performance is not an issue:
我的控制台应用程序创建一个IIS配置文件,并启动一个IIS前preSS:
My console app creates an IIS config file and launches an IIS express:
// start IIS
bool systray = Debugger.IsAttached;
ProcessStartInfo psi = new ProcessStartInfo(iisExecutable, String.Format("/config:\"{0}\" /site:Ecm2.Web /trace:info /systray:{1}", configFile, systray));
psi.UseShellExecute = false;
psi.RedirectStandardInput = false;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.CreateNoWindow = true;
if (this.iisProcess != null) throw new NotSupportedException("Multiple starts not supported");
this.iisProcess = new Process();
this.iisProcess.StartInfo = psi;
this.iisProcess.ErrorDataReceived += OnErrorDataReceived;
this.iisProcess.OutputDataReceived += OnOutputDataReceived;
this.iisProcess.Start();
this.iisProcess.BeginErrorReadLine();
this.iisProcess.BeginOutputReadLine();
如果有人想,这就是停止片段的一部分:
If someone would like, this is part of the "stop" fragment:
if (this.iisProcess == null) throw new Exception("Does not look like there was something started yet!");
if (this.iisProcess.HasExited)
{
log.WarnFormat("IIS has already exited with code '{0}'", this.iisProcess.ExitCode);
this.iisProcess.Close();
return;
}
log.InfoFormat("Stopping IIS instance #{0}", this.instanceId);
ProcessCommunication.SendStopMessageToProcess(this.iisProcess.Id);
bool exited = this.iisProcess.WaitForExit(30000);
if (!exited)
{
log.WarnFormat("Failed to stop IIS instance #{0} (PID {1}), killing it now", this.instanceId, this.iisProcess.Id);
this.iisProcess.Kill();
}
this.iisProcess.Close();
要停止IIS进程一般就发送WM_QUIT它。这可能是有益的这个:
To stop the iis process ordinary you should send WM_QUIT to it. This might be helpful for this:
/// <summary>
/// Sends a WM_QUIT message to another process.
/// </summary>
/// <param name="pid">PID of the other process</param>
public static void SendStopMessageToProcess(int pid)
{
log.DebugFormat("Sending stop message to PID #{0}", pid);
try
{
for (IntPtr ptr = NativeMethods.GetTopWindow(IntPtr.Zero); ptr != IntPtr.Zero; ptr = NativeMethods.GetWindow(ptr, 2))
{
uint num;
NativeMethods.GetWindowThreadProcessId(ptr, out num);
if (pid == num)
{
HandleRef hWnd = new HandleRef(null, ptr);
NativeMethods.PostMessage(hWnd, 0x12, IntPtr.Zero, IntPtr.Zero);
return;
}
}
}
catch (ArgumentException ex)
{
log.Error(String.Format("Failed to send WM_QUIT to PID #{0}", pid), ex);
}
}
/// <summary>
/// Provides the native methods to post messages to other windows processes.
/// </summary>
internal class NativeMethods
{
// Methods
[DllImport("user32.dll", SetLastError = true)]
internal static extern IntPtr GetTopWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
internal static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
[DllImport("user32.dll", SetLastError = true)]
internal static extern uint GetWindowThreadProcessId(IntPtr hwnd, out uint lpdwProcessId);
[DllImport("user32.dll", SetLastError = true)]
internal static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
}