发布到 IIS,设置环境变量

Publish to IIS, setting Environment Variable

阅读这两个 questions/answers 我能够 运行 IIS 8.5 服务器上的 Asp.net 5 应用程序。

Asp.net vNext early beta publish to IIS in windows server

问题是 Web 应用程序仍在使用 env.EnvironmentName 和值 Development,即使在 IIS 上 运行 也是如此。

此外,我想 运行 在同一台服务器上安装同一网站的两个版本(暂存版、生产版),因此我需要一种方法来分别为每个网站设置变量。

怎么做?

经过广泛的谷歌搜索后,我找到了一个可行的解决方案,它包括两个步骤。

第一步是将系统范​​围的环境变量 ASPNET_ENV 设置为 Production 并 重新启动 Windows 服务器 。此后,所有 Web 应用程序都将值 'Production' 作为 EnvironmentName.

第二步(为暂存 Web 启用值 'Staging')更难正常工作,但这里是:

  1. 在服务器上创建新的 windows 用户,例如 StagingPool
  2. 为此用户,创建新的用户变量 ASPNETCORE_ENVIRONMENT,值为 'Staging'(您可以通过以该用户身份登录或通过 regedit 来完成)
  3. 在 IIS 管理器中以管理员身份返回,找到暂存 Web 所在的应用程序池 运行,然后在高级设置中将身份设置为用户 StagingPool.
  4. 同时将 Load User Profile 设置为 true,以便加载环境变量。 <- 非常重要!
  5. 确保 StagingPool 有权访问 Web 文件夹以及停止和启动应用程序池。

现在暂存网络的 EnvironmentName 应该设置为 'Staging'。

更新:在 Windows 7+ there is a command 中,也可以从 CMD 提示符为指定用户设置环境变量。此输出帮助和示例:

>setx /?

编辑:从 RC2 和 RTM 版本开始,此建议已过时。我发现在发行版中完成此操作的最佳方法是在 IIS 中为每个环境编辑以下 web.config 部分:

system.webServer/aspNetCore:

编辑环境变量条目并添加环境变量设置:

ASPNETCORE_ENVIRONMENT : < Your environment name >


作为 drpdrp 方法的替代方法,您可以执行以下操作:

  • 在您的 project.json 中,添加将 ASPNET_ENV 变量直接传递给 Kestrel 的命令:

    "commands": {
        "Development": "Microsoft.AspNet.Server.Kestrel --ASPNET_ENV Development",
        "Staging": "Microsoft.AspNet.Server.Kestrel --ASPNET_ENV Staging",
        "Production": "Microsoft.AspNet.Server.Kestrel --ASPNET_ENV Production"
    }
    
  • 发布时,使用--iis-command选项指定环境:

    dnu publish --configuration Debug --iis-command Staging --out "outputdir" --runtime dnx-clr-win-x86-1.0.0-rc1-update1
    

我发现与创建额外的 IIS 用户相比,这种方法的侵入性更小。

此答案最初是为 ASP.NET Core RC1 编写的。在 RC2 ASP.NET 中,Core 从通用的 httpPlafrom 处理程序转移到 aspnetCore 特定的处理程序。请注意,第 3 步取决于您使用的 ASP.NET 核心版本。

原来 ASP.NET 核心项目的环境变量可以设置,而无需为用户设置环境变量或创建多个命令条目。

  1. 转到 IIS 中的应用程序并选择 Configuration Editor
  2. Select Configuration Editor
  3. Section组合框中选择system.webServer/aspNetCore(RC2和RTM)或system.webServer/httpPlatform(RC1)
  4. From 组合框中选择 Applicationhost.config ...
  5. 右键单击 enviromentVariables 元素,select 'environmentVariables' element,然后 Edit Items
  6. 设置环境变量。
  7. 关闭 window 并单击“应用”。
  8. 完成

这样您就不必为您的池创建特殊用户或在 project.json 中创建额外的命令条目。 此外,为每个环境添加特殊命令会中断 "build once, deploy many times",因为您必须为每个环境单独调用 dnu publish,而不是发布一次并多次部署生成的工件。

更新了 RC2 和 RTM,感谢 Mark G 和 tredder。

使用 [=20= 下的 部分更新 web.config ]

<configuration>
  <system.webServer>
    <aspNetCore .....>
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</configuration>

或者为避免在覆盖 web.config 时丢失此设置,对 applicationHost.config 进行类似更改,按照@NickAb 建议指定站点位置。

<location path="staging.site.com">
  <system.webServer>
    <aspNetCore>
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</location>
<location path="production.site.com">
  <system.webServer>
    <aspNetCore>
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</location>

要扩展@tredder 的回答,您可以使用 appcmd

更改环境变量

分期

%windir%\system32\inetsrv\appcmd set config "staging.example.com" /section:system.webServer/aspNetCore /+environmentVariables.[name='ASPNETCORE_ENVIRONMENT',value='Staging'] /commit:APPHOST

生产

%windir%\system32\inetsrv\appcmd set config "example.com" /section:system.webServer/aspNetCore /+environmentVariables.[name='ASPNETCORE_ENVIRONMENT',value='Production'] /commit:APPHOST

@tredder 编辑解决方案 applicationHost.config 如果您在 IIS 上的虚拟目录中有多个不同的应用程序,那么这个解决方案是可行的。

我的情况是:

  • 我有API项目和APP项目,在同一个域下,放在不同的虚拟目录下
  • 根页面 XXX 似乎没有将 ASPNETCORE_ENVIRONMENT 变量传播给它在虚拟目录中的子页面并且...
  • ...我无法按照@NickAb 所述在虚拟目录中设置变量(出现错误不支持该请求。(HRESULT 异常:0x80070032)在配置编辑器中保存更改期间):
  • 进入 applicationHost.config 并像这样手动创建节点:

    <location path="XXX/app"> <system.webServer> <aspNetCore> <environmentVariables> <clear /> <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" /> </environmentVariables> </aspNetCore> </system.webServer> </location> <location path="XXX/api"> <system.webServer> <aspNetCore> <environmentVariables> <clear /> <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" /> </environmentVariables> </aspNetCore> </system.webServer> </location>

然后重新启动 IIS 就完成了工作。

我将我的 Web 应用程序(生产、暂存、测试)托管在 IIS Web 服务器上。因此不可能依赖 ASPNETCORE_ENVIRONMENT 操作员的系统环境变量,因为将其设置为特定值(例如 STAGING)会对其他应用程序产生影响。

作为 work-around,我在我的 visualstudio 解决方案中定义了一个自定义文件 (envsettings.json):

内容如下:

{
  // Possible string values reported below. When empty it use ENV variable value or Visual Studio setting.
  // - Production
  // - Staging
  // - Test
  // - Development
  "ASPNETCORE_ENVIRONMENT": ""
}

然后,根据我的应用程序类型(生产、暂存或测试)我相应地设置了这个文件:假设我正在部署测试应用程序,我将有:

"ASPNETCORE_ENVIRONMENT": "Test"

之后,在 Program.cs 文件中检索此值,然后设置 webHostBuilder 的环境:

    public class Program
    {
        public static void Main(string[] args)
        {
            var currentDirectoryPath = Directory.GetCurrentDirectory();
            var envSettingsPath = Path.Combine(currentDirectoryPath, "envsettings.json");
            var envSettings = JObject.Parse(File.ReadAllText(envSettingsPath));
            var enviromentValue = envSettings["ASPNETCORE_ENVIRONMENT"].ToString();

            var webHostBuilder = new WebHostBuilder()
                .UseKestrel()
                .CaptureStartupErrors(true)
                .UseSetting("detailedErrors", "true")
                .UseContentRoot(currentDirectoryPath)
                .UseIISIntegration()
                .UseStartup<Startup>();

            // If none is set it use Operative System hosting enviroment
            if (!string.IsNullOrWhiteSpace(enviromentValue)) 
            { 
                webHostBuilder.UseEnvironment(enviromentValue);
            }

            var host = webHostBuilder.Build();

            host.Run();
        }
    }

记得在 publishOptions (project.json) 中包含 envsettings.json:

  "publishOptions":
  {
    "include":
    [
      "wwwroot",
      "Views",
      "Areas/**/Views",
      "envsettings.json",
      "appsettings.json",
      "appsettings*.json",
      "web.config"
    ]
  },

这个解决方案让我可以自由地将 ASP.NET 核心应用程序托管在同一个 IIS 上,独立于环境变量值。

一站式了解:

  • 对于覆盖任何配置设置的环境变量,它们必须以 ASPNETCORE_ 为前缀。
  • 如果要匹配 JSON 配置中的子节点,请使用 : 作为分隔符。如果平台不允许在环境变量键中使用冒号,请改用 __
  • 您希望您的设置在 ApplicationHost.config 结束。使用 IIS 配置编辑器会将您的输入写入应用程序的 Web.config -- 并将被下一次部署覆盖!
  • 修改ApplicationHost.config,你要用appcmd.exe来确保你的修改是一致的。示例:%systemroot%\system32\inetsrv\appcmd.exe set config "Default Web Site/MyVirtualDir" -section:system.webServer/aspNetCore /+"environmentVariables.[name='ASPNETCORE_AWS:Region',value='eu-central-1']" /commit:site

  • 不是 URL-safe 的字符可以作为 Unicode 转义,例如 %u007b 用于左大括号。

  • 列出您当前的设置(结合 Web.config 中的值):%systemroot%\system32\inetsrv\appcmd.exe list config "Default Web Site/MyVirtualDir" -section:system.webServer/aspNetCore
  • 如果你运行命令为同一个键多次设置一个配置键,它会被添加多次!要删除现有值,请使用类似 %systemroot%\system32\inetsrv\appcmd.exe set config "Default Web Site/MyVirtualDir" -section:system.webServer/aspNetCore /-"environmentVariables.[name='ASPNETCORE_MyKey',value='value-to-be-removed']" /commit:site.
  • 的内容

要获取有关错误的详细信息,我必须 为相应的应用程序池 system.applicationHost/applicationPools 添加 ASPNETCORE_ENVIRONMENT 环境变量。

注意:我的 Web 应用程序是 ASP.NET Core 2 托管在 IIS 10 上的 Web 应用程序。可以通过 IIS Manager 中的 Configuration Editor 来完成(请参阅 Editing Collections with Configuration Editor 以找出在 IIS Manager 中可以找到此编辑器的位置)。

我已经使用 Web.config 中的环境配置创建了用于发布 IIS 的存储库。

https://github.com/expressiveco/AspnetCoreWebConfigForEnvironment

  • 设置
    • 将 .csproj 和 .user.csproj 文件中的部分获取到您的项目文件中。
    • 获取 MyAspNetEnvironment.props、web.development.config 和 web.production.config 文件。
  • 配置
    • 相应地更改user.csproj中ASPNETCORE_ENVIRONMENT属性的值。

与其他答案类似,我想确保我的 ASP.NET 核心 2.1 环境设置在部署过程中持续存在,但也仅应用于特定站点。

根据 Microsoft 的文档,可以在 IIS 10 中使用以下 PowerShell 命令在应用程序池上设置环境变量:

$appPoolName = "AppPool"
$envName = "Development"
cd "$env:SystemRoot\system32\inetsrv"
.\appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='$appPoolName'].environmentVariables.[name='ASPNETCORE_ENVIRONMENT',value='$envName']" /commit:apphost

不幸的是,我仍然必须使用 IIS 8.5,我认为我运气不好。但是,仍然可以 运行 一个简单的 PowerShell 脚本来为 ASPNETCORE_ENVIRONMENT:

设置站点特定的环境变量值
Import-Module -Name WebAdministration
$siteName = "Site"
$envName = "Development"
Set-WebConfigurationProperty -PSPath IIS:\ -Location $siteName -Filter /system.webServer/aspNetCore/environmentVariables -Name . -Value @{ Name = 'ASPNETCORE_ENVIRONMENT'; Value = $envName }

您也可以将所需的 ASPNETCORE_ENVIRONMENT 作为参数传递到 dotnet publish 命令中,使用:

/p:EnvironmentName=Staging

例如:

dotnet publish /p:Configuration=Release /p:EnvironmentName=Staging

这将生成具有为您的项目指定的正确环境的 web.config:

<environmentVariables>
  <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" />
</environmentVariables>

除了上面提到的选项之外,还有一些其他解决方案可以很好地与自动部署配合使用或需要较少的配置更改。

1.修改项目文件(.CsProj)文件

MSBuild 支持 EnvironmentName 属性,这有助于根据您希望部署的环境设置正确的环境变量。环境名称将在发布阶段添加到 web.config。

只需打开项目文件 (*.csProj) 并添加以下内容 XML.

<!-- Custom Property Group added to add the Environment name during publish
  The EnvironmentName property is used during the publish for the Environment variable in web.config
  -->
  <PropertyGroup Condition=" '$(Configuration)' == '' Or '$(Configuration)' == 'Debug'">
    <EnvironmentName>Development</EnvironmentName>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)' != '' AND '$(Configuration)' != 'Debug' ">
    <EnvironmentName>Production</EnvironmentName>
  </PropertyGroup>

以上代码会将环境名称添加为 Development 用于调试配置,或者如果未指定配置。对于任何其他配置,环境名称在生成的 web.config 文件中将是 Production。更多详情 here

2。在发布配置文件中添加环境名称 属性。

我们也可以在发布配置文件中添加 <EnvironmentName> 属性。打开位于 Properties/PublishProfiles/{profilename.pubxml} 的发布配置文件 这将在发布项目时在 web.config 中设置环境名称。更多详情 here

<PropertyGroup>
  <EnvironmentName>Development</EnvironmentName>
</PropertyGroup>

3。使用 dotnet publish

的命令行选项

此外,我们可以将 属性 EnvironmentName 作为命令行选项传递给 dotnet publish 命令。以下命令会将环境变量作为 Development 包含在 web.config 文件中。

dotnet publish -c Debug -r win-x64 /p:EnvironmentName=Development

我修改了 @Christian Del Bianco 给出的答案。我现在将 .net core 2 和更高版本的进程更改为 project.json 绝对文件。

  1. 首先,在根目录下创建appsettings.json文件。含内容

      {
         // Possible string values reported below. When empty it use ENV 
            variable value or Visual Studio setting.
         // - Production
         // - Staging
         // - Test
        // - Development
       "ASPNETCORE_ENVIRONMENT": "Development"
     }
    
  2. 然后创建另外两个设置文件 appsettings.Development.jsonappsettings.Production.json配置.

  3. 将设置环境所需的代码添加到 Program.cs 文件。

    public class Program
    {
    public static void Main(string[] args)
    {
        var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
    
      ***var currentDirectoryPath = Directory.GetCurrentDirectory();
        var envSettingsPath = Path.Combine(currentDirectoryPath, "envsettings.json");
        var envSettings = JObject.Parse(File.ReadAllText(envSettingsPath));
        var enviromentValue = envSettings["ASPNETCORE_ENVIRONMENT"].ToString();***
    
        try
        {
            ***CreateWebHostBuilder(args, enviromentValue).Build().Run();***
        }
        catch (Exception ex)
        {
            //NLog: catch setup errors
            logger.Error(ex, "Stopped program because of setup related exception");
            throw;
        }
        finally
        {
            NLog.LogManager.Shutdown();
        }
    }
    
    public static IWebHostBuilder CreateWebHostBuilder(string[] args, string enviromentValue) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .ConfigureLogging(logging =>
            {
                logging.ClearProviders();
                logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
            })
            .UseNLog()
            ***.UseEnvironment(enviromentValue);***
    

    }

  4. envsettings.json 添加到您的 .csproj 文件以复制到已发布的目录。

       <ItemGroup>
            <None Include="envsettings.json" CopyToPublishDirectory="Always" />
        </ItemGroup>
    
  5. 现在只需在 envsettings.json 文件中根据需要更改 ASPNETCORE_ENVIRONMENT 和出版。

我知道已经给出了很多答案,但就我而言,我在我的项目中添加了 web.{Environment}.config 版本,当针对特定环境发布时,该值会被替换。


例如,对于分期 (web.Staging.config)

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <location>
        <system.webServer>
            <aspNetCore>
                <environmentVariables xdt:Transform="InsertIfMissing">
                    <environmentVariable name="ASPNETCORE_ENVIRONMENT"
                                         value="Staging"
                                         xdt:Locator="Match(name)"
                                         xdt:Transform="InsertIfMissing" />
                </environmentVariables>
            </aspNetCore>
        </system.webServer>
    </location>
</configuration>

对于发布或生产,我会这样做 (web.Release.config)

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <location>
        <system.webServer>
            <aspNetCore>
                <environmentVariables xdt:Transform="InsertIfMissing">
                    <environmentVariable name="ASPNETCORE_ENVIRONMENT"
                                         value="Release"
                                         xdt:Locator="Match(name)"
                                         xdt:Transform="InsertIfMissing" />
                </environmentVariables>
            </aspNetCore>
        </system.webServer>
    </location>
</configuration>

然后在发布的时候我会选择或者设置环境名称。这将替换最终 web.config 文件中的环境值。

对于那些在 azure devops 管道中寻找这个的人,这可以通过添加 PowerShell on target machines 任务和 运行 以下脚本来实现:

$envVariables = (
  @{name='VARIABLE1';value='Value1'},
  @{name='VARIABLE2';value='Value2'}
)

Set-WebConfigurationProperty -PSPath IIS:\ -Location $('mySite') -Filter /system.webServer/aspNetCore/environmentVariables -Name . -Value $envVariables

只需将 <EnvironmentName> 添加到您的发布配置文件:

<PropertyGroup>
  <EnvironmentName>Development</EnvironmentName>
</PropertyGroup>

该信息被复制到 web.config。 (不要手动设置 web.config,因为它会被覆盖。)

来源:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments