Setting Environment Variables in IIS Without Triggering App Pool Restarts
In this post, Andrew Lock provides practical strategies for setting environment variables in IIS application pools on Windows, covering both UI and command-line techniques, and explains how to prevent unwanted app pool restarts.
Setting Environment Variables in IIS Without Triggering App Pool Restarts
By Andrew Lock
Introduction
This post provides a comprehensive guide on configuring environment variables for IIS (Internet Information Services) worker processes on Windows. Andrew Lock explores several approaches, including system-wide, service-specific, and application pool-level settings. The article also offers advice on how to avoid unnecessary IIS application pool recycles when changing environment-related configurations.
How IIS Works: An Overview
Understanding how IIS routes HTTP requests is fundamental to effective configuration. The main components involved are:
- HTTP.sys: A kernel-mode driver handling HTTP requests, forwarding them to worker processes.
- Windows Process Activation Service (WAS): Manages application pool configuration and worker process lifecycles.
- World Wide Web Publishing Service (W3SVC): Bridges WAS and HTTP.sys, updating configurations and dispatching requests.
- Application Pools: Containers for worker processes, potentially hosting multiple sites or applications.
- Worker Processes (w3wp.exe): Processes that run managed and native modules for request handling.
IIS Request Flow
- Client sends a request, intercepted by HTTP.sys.
- HTTP.sys consults W3SVC/WAS for configuration.
- WAS retrieves config from applicationHost.config and site-level web.config.
- WAS relays app pool and site config to W3SVC, which updates HTTP.sys.
- WAS starts a worker process if necessary.
- HTTP.sys passes details to the worker process, which generates a response.
- HTTP.sys sends the response back to the client.
Methods for Setting Environment Variables
Lock explores three main methods for adjusting environment variables for IIS worker processes:
1. System-Wide Environment Variables
System variables affect all processes and can be set with PowerShell:
[System.Environment]::SetEnvironmentVariable("MY_SPECIAL_KEY", "Some value", [System.EnvironmentVariableTarget]::Machine)
To apply these changes to running services:
net stop /y was
net start w3svc
Caveat: This method applies the variable to every process and may have unintended consequences, especially for variables like the .NET profiling API.
2. Service-Specific Environment Variables (W3SVC and WAS)
Variables can be scoped to W3SVC and WAS through the Windows Registry:
Set-ItemProperty HKLM:SYSTEM\CurrentControlSet\Services\W3SVC -Name Environment -Value 'MY_SPECIAL_KEY=Something' -Type MultiString
Set-ItemProperty HKLM:SYSTEM\CurrentControlSet\Services\WAS -Name Environment -Value 'MY_SPECIAL_KEY=Something' -Type MultiString
Alternatively, use the Registry Editor UI to add multi-string values.
Restart services for changes to take effect:
net stop /y was
net start w3svc
This method ensures only processes started by these services (i.e., IIS worker processes) inherit the variable.
3. Application Pool-Level Variables via applicationHost.config
applicationHost.config, typically located at C:\Windows\System32\inetsrv\config\applicationHost.config
, defines IIS app pools in the <system.applicationHost>
section.
Sample configuration:
<applicationPools>
<add name="DefaultAppPool" />
<add name="dotnet7" autoStart="true" managedRuntimeVersion="">
<environmentVariables>
<add name="MY_VAL" value="1" />
<add name="MY_SPECIAL_KEY" value="Something" />
</environmentVariables>
</add>
<applicationPoolDefaults managedRuntimeVersion="v4.0">
<processModel identityType="ApplicationPoolIdentity" loadUserProfile="true" setProfileEnvironment="false" />
<environmentVariables>
<add name="MY_SPECIAL_KEY" value="Something" />
</environmentVariables>
</applicationPoolDefaults>
</applicationPools>
Adding or Updating Variables
- To apply a variable for all pools: Add it to
<applicationPoolDefaults>
. - To override for a specific pool: Add directly beneath the pool’s configuration.
Note: If a pool defines its own <environmentVariables>
, it will not inherit from the defaults.
Editing applicationHost.config
- Via IIS UI: Navigate Configuration Editor >
system.applicationHost/applicationPools
, expand and editenvironmentVariables
for pools and defaults using ellipsis buttons. Apply and restart as necessary. - Via appcmd.exe: Use command-line for faster edits.
To add:
C:\Windows\System32\inetsrv\appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='dotnet7'].environmentVariables.[name='MY_SPECIAL_KEY',value='Something']" /+"applicationPoolDefaults.environmentVariables.[name='MY_SPECIAL_KEY',value='Something']" /commit:apphost;
To update existing variables:
C:\Windows\System32\inetsrv\appcmd.exe set config -section:system.applicationHost/applicationPools /"[name='dotnet7'].environmentVariables.[name='MY_SPECIAL_KEY'].value:'Something'" /"applicationPoolDefaults.environmentVariables.[name='MY_SPECIAL_KEY'].value:'Something'" /commit:apphost;
A helpful guide explains the nuances of this syntax.
Preventing Automatic App Pool Restarts on Config Changes
By default, changing applicationHost.config triggers immediate recycling of application pools, potentially causing short downtime. To delay this:
- Set the
disallowRotationOnConfigChange
attribute totrue
in the<recycling>
element of each app pool or in<applicationPoolDefaults>
.
Sample configuration:
<applicationPools>
<add name="dotnet7">
...
<recycling disallowRotationOnConfigChange="true" />
</add>
<applicationPoolDefaults>
...
<recycling disallowRotationOnConfigChange="true" />
</applicationPoolDefaults>
</applicationPools>
Corresponding appcmd.exe command:
C:\Windows\System32\inetsrv\appcmd.exe set config -section:system.applicationHost/applicationPools /"[name='dotnet7'].recycling.disallowRotationOnConfigChange:true" /"applicationPoolDefaults.recycling.disallowRotationOnConfigChange:true" /+"[name='dotnet7'].environmentVariables.[name='MY_SPECIAL_KEY',value='Something']" /+"applicationPoolDefaults.environmentVariables.[name='MY_SPECIAL_KEY',value='Something']" /commit:apphost;
To revert to default recycling behavior:
C:\Windows\System32\inetsrv\appcmd.exe set config -section:system.applicationHost/applicationPools /"[name='dotnet7'].recycling.disallowRotationOnConfigChange:false" /"applicationPoolDefaults.recycling.disallowRotationOnConfigChange:false" /commit:apphost;
Changing this attribute does not itself trigger recycling, providing a method to suppress unwanted restarts during configuration changes.
Summary
- IIS worker process environment variables can be set globally, per service, or per application pool.
- Using the
disallowRotationOnConfigChange
attribute allows implementing changes without immediate app pool restarts, preventing unnecessary application downtime. - Methods include Windows UI, Registry modification, command-line (appcmd.exe), and IIS Configuration Editor.
References and Links:
*Andrew Lock | .Net Escapades* |
This post appeared first on “Andrew Lock’s Blog”. Read the entire article here