在aspnet核心运行时检查托管服务器是IIS还是Kestrel

dzjeubhm  于 2023-10-19  发布在  其他
关注(0)|答案(4)|浏览(106)

我目前正在Kestrel(本地)或IIS InProcess(生产)下运行应用程序。

return WebHost.CreateDefaultBuilder(args)
    .ConfigureKestrel(options => options.AddServerHeader = false)
    .UseIIS()
    .UseStartup<Startup>();

我希望能够在运行时在控制器中获取托管服务器名称,这样我就可以实现以下功能:

if (hostingServer == "kestrel")
{
    DoSomething();
}
else
{
    DoSomethingElse();
}

在这个特定的例子中,它是为了解决Kestrel的响应头不支持非ASPACK字符的事实。理想情况下,我会删除non-asktop头,但目前它是遗留互操作性所必需的。
任何帮助将不胜感激。

rwqw0loc

rwqw0loc1#

最简单的方法可能是阅读System.Diagnostics.Process.GetCurrentProcess().ProcessName。如果它是w3wpiisexpress,您知道主机是IIS/IIS Express,而dotnet(或使用自包含部署时的其他名称)表示Kestrel。这只适用于进程中部署。如果你在进程之外,这将不起作用。在https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/aspnet-core-module了解更多信息
范例:

/// <summary>
/// Check if this process is running on Windows in an in process instance in IIS
/// </summary>
/// <returns>True if Windows and in an in process instance on IIS, false otherwise</returns>
public static bool IsRunningInProcessIIS()
{
    if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
    {
        return false;
    }

    string processName = Path.GetFileNameWithoutExtension(Process.GetCurrentProcess().ProcessName);
    return (processName.Contains("w3wp", StringComparison.OrdinalIgnoreCase) ||
        processName.Contains("iisexpress", StringComparison.OrdinalIgnoreCase));
}
p8h8hvxi

p8h8hvxi2#

检查进程名对我不起作用,即使在IIS中使用InProcess托管,它仍然代理dotnet进程(我猜你需要获取父进程才能获取w3wp进程)。
内部.NET Core在NativeMethods.cs中调用IsAspNetCoreModuleLoaded(),可以在WebHostBuilderIISExtensions.cs中找到。因此,可以使用以下代码检查IIS。

internal static class NativeMethods
{
    internal const string AspNetCoreModuleDll = "aspnetcorev2_inprocess.dll";

    [DllImport("kernel32.dll")]
    private static extern IntPtr GetModuleHandle(string lpModuleName);

    public static bool IsAspNetCoreModuleLoaded()
    {
        return GetModuleHandle(AspNetCoreModuleDll) != IntPtr.Zero;
    }
}
xqk2d5yq

xqk2d5yq3#

当应用程序启动时,托管方法可以在IApplicationBuilder.ServerFeatures中公开。通过这里,您可以找到引用Kestrel vs反向代理配置的项目。
Startup.Configure方法中可用的IApplicationBuilder公开IApplicationCollection类型的ServerFeatures属性。Kestrel和HTTP.sys各自只公开一个特性,即IServerAddressesFeature,但不同的服务器实现可能会公开其他功能。IServerAddressesFeature可用于找出服务器实现在运行时绑定了哪个端口。
该属性是一个集合,因此您需要筛选属于IIS反向代理和Kestrel的特定宿主方法。

sbtkgmzw

sbtkgmzw4#

另一种方法是测试IServer实现类型。对于IIS In-Proc,它将是IISHttpServer,对于IIS Out-of-Proc和纯Kestrel,它将是KestrelServerImpl。不幸的是,这些类型是内部类型,所以你需要检查字符串名称,这并不比检查进程名称更可靠:

var server = serviceProvider.GetRequiredService<Microsoft.AspNetCore.Hosting.Server.IServer>();

if (server.GetType().Name.Equals("IISHttpServer", StringComparison.OrdinalIgnoreCase))
 {
   // IIS In-Proc
 }
 else
 {
   // Kestrel (including IIS Out-of-Proc)
 }

为了使其更可靠,您可以在类型名称中搜索类似“iis”的内容,而不是进行序数比较,这在代码重构后更有可能保留在类型名称中。

相关问题