How to Create an Application Pool in IIS from Batch Script
Application pools are the backbone of IIS process management. Each application pool runs as an isolated worker process (w3wp.exe), meaning a crash or resource leak in one web application does not affect others. Creating dedicated application pools for each website is a fundamental best practice for security, stability, and resource control.
In this guide, we will explore how to create and configure IIS application pools from a Batch Script using the appcmd.exe command-line tool.
Understanding Application Pools
An application pool defines:
- Which .NET runtime version to use (v2.0, v4.0, or none for static/PHP sites)
- Which pipeline mode to use (Integrated or Classic)
- Which identity the worker process runs under (ApplicationPoolIdentity, LocalService, NetworkService, or a custom account)
- Recycling rules (time-based, request-based, or memory-based triggers)
Each website or web application is assigned to exactly one application pool.
Method 1: Creating a Basic Application Pool
@echo off
setlocal
set "APPCMD=%SystemRoot%\System32\inetsrv\appcmd.exe"
set "POOL_NAME=MyAppPool"
:: Verify administrator privileges
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Administrator privileges required.
exit /b 1
)
:: Verify appcmd.exe exists
if not exist "%APPCMD%" (
echo [ERROR] appcmd.exe not found at: %APPCMD%
echo IIS may not be installed or Management Tools are missing.
exit /b 1
)
:: Check if the pool already exists
"%APPCMD%" list apppool /name:"%POOL_NAME%" >nul 2>&1
if %errorlevel% equ 0 (
echo [INFO] Application pool "%POOL_NAME%" already exists. No changes made.
exit /b 0
)
:: Create the application pool
echo Creating application pool "%POOL_NAME%"...
"%APPCMD%" add apppool /name:"%POOL_NAME%"
if %errorlevel% neq 0 (
echo [ERROR] Failed to create application pool "%POOL_NAME%".
exit /b 1
)
echo [SUCCESS] Application pool "%POOL_NAME%" created.
endlocal
exit /b 0
By default, a new pool uses:
- .NET CLR v4.0
- Integrated pipeline mode
- ApplicationPoolIdentity
Method 2: Creating a Pool with Specific Settings
For production deployments, you almost always need to specify the .NET version, pipeline mode, and other properties at creation time.
@echo off
setlocal
set "APPCMD=%SystemRoot%\System32\inetsrv\appcmd.exe"
set "POOL_NAME=ProductionApiPool"
:: Verify administrator privileges
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Administrator privileges required.
exit /b 1
)
:: Verify appcmd.exe exists
if not exist "%APPCMD%" (
echo [ERROR] appcmd.exe not found. IIS may not be installed.
exit /b 1
)
:: Check if pool already exists
"%APPCMD%" list apppool /name:"%POOL_NAME%" >nul 2>&1
if %errorlevel% equ 0 (
echo [INFO] Pool "%POOL_NAME%" already exists. Skipping creation.
echo To reconfigure, delete the pool first or use Method 5.
exit /b 0
)
:: Create the pool with specific .NET version and pipeline mode
echo Creating configured application pool "%POOL_NAME%"...
"%APPCMD%" add apppool /name:"%POOL_NAME%" /managedRuntimeVersion:"v4.0" /managedPipelineMode:"Integrated"
if %errorlevel% neq 0 (
echo [ERROR] Failed to create pool "%POOL_NAME%".
exit /b 1
)
echo [OK] Pool created. Configuring additional settings...
:: Set the identity to NetworkService instead of default ApplicationPoolIdentity
"%APPCMD%" set apppool /apppool.name:"%POOL_NAME%" /processModel.identityType:"NetworkService"
if %errorlevel% neq 0 echo [WARNING] Could not set identity type.
:: Enable 32-bit applications (needed for some legacy DLLs)
"%APPCMD%" set apppool /apppool.name:"%POOL_NAME%" /enable32BitAppOnWin64:true
if %errorlevel% neq 0 echo [WARNING] Could not enable 32-bit mode.
:: Set the idle timeout to 0 (never idle out)
"%APPCMD%" set apppool /apppool.name:"%POOL_NAME%" /processModel.idleTimeout:"00:00:00"
if %errorlevel% neq 0 echo [WARNING] Could not set idle timeout.
:: Display final configuration
echo.
echo [SUCCESS] "%POOL_NAME%" configured.
echo.
echo Configuration:
"%APPCMD%" list apppool /name:"%POOL_NAME%" /text:*
endlocal
exit /b 0
Key Configuration Properties
| Property | Values | Description |
|---|---|---|
managedRuntimeVersion | v2.0, v4.0, "" | .NET CLR version. Empty string for no managed code. |
managedPipelineMode | Integrated, Classic | Integration mode with the IIS pipeline. |
processModel.identityType | ApplicationPoolIdentity, LocalService, NetworkService, LocalSystem, SpecificUser | Account the worker process runs under. |
enable32BitAppOnWin64 | true, false | Run 32-bit applications on a 64-bit OS. |
processModel.idleTimeout | HH:MM:SS | Time before an idle pool shuts down. 00:00:00 disables the timeout. |
startMode | OnDemand, AlwaysRunning | Whether the pool starts immediately or on first request. |
Method 3: Creating a Pool for Static Content (No .NET)
If your site serves only static HTML, CSS, JavaScript, images, or runs PHP, the application pool should have no managed runtime.
@echo off
setlocal
set "APPCMD=%SystemRoot%\System32\inetsrv\appcmd.exe"
set "POOL_NAME=StaticContentPool"
:: Verify administrator privileges
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Administrator privileges required.
exit /b 1
)
:: Verify appcmd.exe exists
if not exist "%APPCMD%" (
echo [ERROR] appcmd.exe not found. IIS may not be installed.
exit /b 1
)
:: Check if pool already exists
"%APPCMD%" list apppool /name:"%POOL_NAME%" >nul 2>&1
if %errorlevel% equ 0 (
echo [INFO] Pool "%POOL_NAME%" already exists.
exit /b 0
)
:: Create with no managed code (empty managedRuntimeVersion)
echo Creating static content pool "%POOL_NAME%"...
"%APPCMD%" add apppool /name:"%POOL_NAME%" /managedRuntimeVersion:"" /managedPipelineMode:"Integrated"
if %errorlevel% neq 0 (
echo [ERROR] Failed to create pool "%POOL_NAME%".
exit /b 1
)
echo [SUCCESS] Static content pool "%POOL_NAME%" created (No .NET CLR^).
endlocal
exit /b 0
Setting managedRuntimeVersion to an empty string ("") tells IIS not to load any .NET CLR into the worker process. This reduces memory consumption and startup time for pools that serve only non-.NET content such as static files, PHP, or Node.js applications.
Method 4: Creating a Pool with Custom Recycling Rules
Application pool recycling automatically restarts the worker process to clear memory leaks, release file handles, and reset application state. The default recycling interval is every 1740 minutes (29 hours).
@echo off
setlocal
set "APPCMD=%SystemRoot%\System32\inetsrv\appcmd.exe"
set "POOL_NAME=RecyclingDemoPool"
:: Verify administrator privileges
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Administrator privileges required.
exit /b 1
)
:: Verify appcmd.exe exists
if not exist "%APPCMD%" (
echo [ERROR] appcmd.exe not found. IIS may not be installed.
exit /b 1
)
:: Check if pool already exists
"%APPCMD%" list apppool /name:"%POOL_NAME%" >nul 2>&1
if %errorlevel% equ 0 (
echo [INFO] Pool "%POOL_NAME%" already exists.
exit /b 0
)
:: Create the pool
echo Creating pool "%POOL_NAME%"...
"%APPCMD%" add apppool /name:"%POOL_NAME%" /managedRuntimeVersion:"v4.0"
if %errorlevel% neq 0 (
echo [ERROR] Failed to create pool "%POOL_NAME%".
exit /b 1
)
:: Disable the default periodic restart interval (use scheduled times instead)
"%APPCMD%" set apppool /apppool.name:"%POOL_NAME%" /recycling.periodicRestart.time:"00:00:00"
if %errorlevel% neq 0 echo [WARNING] Could not disable periodic restart interval.
:: Set specific recycling times (3:00 AM and 3:00 PM daily)
"%APPCMD%" set apppool /apppool.name:"%POOL_NAME%" /+recycling.periodicRestart.schedule.[value='03:00:00']
if %errorlevel% neq 0 echo [WARNING] Could not add 3:00 AM recycling schedule.
"%APPCMD%" set apppool /apppool.name:"%POOL_NAME%" /+recycling.periodicRestart.schedule.[value='15:00:00']
if %errorlevel% neq 0 echo [WARNING] Could not add 3:00 PM recycling schedule.
:: Set private memory limit (recycle if worker exceeds 1 GB)
"%APPCMD%" set apppool /apppool.name:"%POOL_NAME%" /recycling.periodicRestart.privateMemory:1048576
if %errorlevel% neq 0 echo [WARNING] Could not set private memory limit.
echo.
echo [SUCCESS] Pool "%POOL_NAME%" created with custom recycling rules.
echo - Periodic interval: Disabled (using scheduled times instead^)
echo - Scheduled times: 3:00 AM and 3:00 PM
echo - Memory limit: Recycle at 1 GB private memory
endlocal
exit /b 0
When using scheduled recycling times, disable the default periodic restart interval by setting recycling.periodicRestart.time to "00:00:00". Otherwise, both the periodic interval and the scheduled times apply simultaneously, and the pool may recycle more frequently than intended.
Memory Values
The privateMemory value is specified in kilobytes:
| Desired Limit | Value |
|---|---|
| 512 MB | 524288 |
| 1 GB | 1048576 |
| 2 GB | 2097152 |
| 4 GB | 4194304 |
Method 5: Comprehensive Pool Provisioning Script
A production-ready script that creates a pool, configures it fully, assigns it to a website, and verifies the result.
@echo off
setlocal enabledelayedexpansion
set "APPCMD=%SystemRoot%\System32\inetsrv\appcmd.exe"
:: =============================================
:: CONFIGURATION
:: =============================================
set "POOL_NAME=OrderSystemPool"
set "SITE_NAME=OrderSystem"
set "NET_VERSION=v4.0"
set "PIPELINE=Integrated"
set "IDENTITY=ApplicationPoolIdentity"
set "IDLE_TIMEOUT=00:20:00"
set "START_MODE=AlwaysRunning"
:: Verify administrator privileges
net session >nul 2>&1
if !errorlevel! neq 0 (
echo [ERROR] Administrator privileges required.
exit /b 1
)
:: Verify appcmd.exe exists
if not exist "%APPCMD%" (
echo [ERROR] appcmd.exe not found. IIS may not be installed.
exit /b 1
)
echo =============================================
echo APPLICATION POOL PROVISIONING
echo =============================================
echo.
:: Check if pool already exists
set "POOL_EXISTS=0"
"%APPCMD%" list apppool /name:"%POOL_NAME%" >nul 2>&1
if !errorlevel! equ 0 (
set "POOL_EXISTS=1"
echo [INFO] Pool "%POOL_NAME%" already exists.
set "OVERWRITE="
set /p "OVERWRITE=Reconfigure it? (Y/N): "
if /i not "!OVERWRITE!"=="Y" (
echo [CANCELLED] No changes made.
exit /b 0
)
echo.
)
:: Create the pool if it does not exist
if !POOL_EXISTS! equ 0 (
echo Creating pool "%POOL_NAME%"...
"%APPCMD%" add apppool /name:"%POOL_NAME%"
if !errorlevel! neq 0 (
echo [ERROR] Failed to create pool "%POOL_NAME%".
exit /b 1
)
echo [OK] Pool created.
)
:: Apply configuration
echo Applying settings...
set "CONFIG_ERRORS=0"
"%APPCMD%" set apppool /apppool.name:"%POOL_NAME%" /managedRuntimeVersion:"%NET_VERSION%" >nul 2>&1
if !errorlevel! neq 0 (
echo [WARNING] Could not set managedRuntimeVersion.
set /a "CONFIG_ERRORS+=1"
)
"%APPCMD%" set apppool /apppool.name:"%POOL_NAME%" /managedPipelineMode:"%PIPELINE%" >nul 2>&1
if !errorlevel! neq 0 (
echo [WARNING] Could not set managedPipelineMode.
set /a "CONFIG_ERRORS+=1"
)
"%APPCMD%" set apppool /apppool.name:"%POOL_NAME%" /processModel.identityType:"%IDENTITY%" >nul 2>&1
if !errorlevel! neq 0 (
echo [WARNING] Could not set identityType.
set /a "CONFIG_ERRORS+=1"
)
"%APPCMD%" set apppool /apppool.name:"%POOL_NAME%" /processModel.idleTimeout:"%IDLE_TIMEOUT%" >nul 2>&1
if !errorlevel! neq 0 (
echo [WARNING] Could not set idleTimeout.
set /a "CONFIG_ERRORS+=1"
)
"%APPCMD%" set apppool /apppool.name:"%POOL_NAME%" /startMode:"%START_MODE%" >nul 2>&1
if !errorlevel! neq 0 (
echo [WARNING] Could not set startMode. This requires IIS 8.0 or later.
set /a "CONFIG_ERRORS+=1"
)
if !CONFIG_ERRORS! gtr 0 (
echo.
echo [WARNING] !CONFIG_ERRORS! setting(s^) could not be applied.
) else (
echo [OK] All settings applied.
)
:: Assign to the website if it exists
echo.
"%APPCMD%" list site /name:"%SITE_NAME%" >nul 2>&1
if !errorlevel! equ 0 (
"%APPCMD%" set site /site.name:"%SITE_NAME%" /[path='/'].applicationPool:"%POOL_NAME%"
if !errorlevel! equ 0 (
echo [OK] Pool assigned to site "%SITE_NAME%".
) else (
echo [WARNING] Could not assign pool to site "%SITE_NAME%".
)
) else (
echo [INFO] Site "%SITE_NAME%" not found. Pool created but not assigned to a site.
)
:: Display final configuration summary
echo.
echo =============================================
echo POOL CONFIGURATION SUMMARY
echo =============================================
"%APPCMD%" list apppool /name:"%POOL_NAME%" /text:*
endlocal
exit /b 0
Common Mistakes
Sharing a Pool Across Unrelated Sites
:: WRONG - Both sites use the same pool
"%APPCMD%" set site /site.name:"SiteA" /[path='/'].applicationPool:"SharedPool"
"%APPCMD%" set site /site.name:"SiteB" /[path='/'].applicationPool:"SharedPool"
If SiteA experiences a crash or memory leak, the shared worker process recycles, taking SiteB offline momentarily as well. Always create a dedicated pool per production site to ensure process isolation.
Using the Wrong .NET Version
:: WRONG - A .NET 4.x app assigned to a v2.0 pool will not load
"%APPCMD%" add apppool /name:"MyPool" /managedRuntimeVersion:"v2.0"
If your application targets .NET Framework 4.x, assigning it to a v2.0 pool produces HTTP 500 errors because the CLR version is incompatible. Always match the pool's runtime version to the application's target framework.
Creating Duplicate Pools Without Checking
:: WRONG - Does not check if the pool already exists
"%APPCMD%" add apppool /name:"MyPool"
:: Running this script a second time produces an error
If a pool with the same name already exists, appcmd add apppool fails with an error. Always check for existing pools with appcmd list apppool /name:"..." before creation to make scripts idempotent and safe to re-run.
Using Both Periodic and Scheduled Recycling Unintentionally
:: WRONG - Both periodic (every 4 hours) AND scheduled (3 AM) recycling apply
"%APPCMD%" set apppool /apppool.name:"MyPool" /recycling.periodicRestart.time:"04:00:00"
"%APPCMD%" set apppool /apppool.name:"MyPool" /+recycling.periodicRestart.schedule.[value='03:00:00']
When both a periodic interval and scheduled times are configured, the pool recycles at whichever trigger fires first, leading to unpredictable recycling behavior. If you are using scheduled times, set the periodic interval to "00:00:00" to disable it. If you are using a periodic interval, do not add scheduled times.
Best Practices
- One pool per site. Process isolation is the primary purpose of application pools. Never share pools between unrelated applications.
- Set
AlwaysRunningfor critical applications. This eliminates the cold-start delay on the first request after idle timeout. - Configure memory-based recycling. Set
privateMemorylimits to automatically recycle leaky applications before they consume all server RAM. - Use
ApplicationPoolIdentity. It is the most secure identity option, creating a unique virtual account per pool with minimal system permissions. - Check for existing pools before creation. Always verify a pool does not already exist before attempting to create one, making scripts idempotent and safe to re-run.
- Verify
appcmd.exeexists. Check for the tool at the start of every script to provide a clear error message on systems where IIS is not installed. - Display configuration after applying settings. Use
appcmd list apppool /text:*to confirm all settings were applied correctly, especially when targeting different IIS versions that may not support all properties.
Conclusion
Creating application pools in IIS from a Batch Script is handled by appcmd add apppool, with subsequent appcmd set apppool commands for detailed configuration. By specifying the .NET runtime version, pipeline mode, identity, idle timeout, and recycling rules at provisioning time, administrators ensure that every pool is correctly configured from the first request. Integrating pool creation with website assignment in a single script establishes a repeatable, professional provisioning workflow.undefined