Skip to content

How to Create a New Website in Internet Information Services (IIS) from Batch Script

Learn how to automate IIS website creation using Batch Script and appcmd.exe for consistent deployments, including bindings, paths, app pools, and host headers.

Provisioning new websites in IIS manually through the graphical IIS Manager works fine for one-off setups, but it quickly becomes unsustainable when you need to deploy dozens or hundreds of sites across multiple servers. Automating website creation via Batch Script ensures consistency, eliminates human error, and integrates cleanly into deployment pipelines.

In this guide, we will explore how to use the appcmd.exe command-line tool to create fully configured IIS websites from a Batch Script, including setting bindings, physical paths, application pools, and host headers.

Prerequisites

  • IIS must be installed: The appcmd.exe utility is only available when the IIS role is enabled.
  • Administrator privileges: Creating websites requires elevation.
  • appcmd.exe path: The tool is located at %SystemRoot%\System32\inetsrv\appcmd.exe and is not in the default system PATH.

Method 1: Creating a Basic HTTP Website

The simplest website requires just three things: a name, a physical path for the files, and an HTTP binding (IP, port, hostname).

@echo off
setlocal enabledelayedexpansion

:: -------------------------------------------------------
:: Verify Admin Privileges
:: -------------------------------------------------------
net session >nul 2>&1
if !errorlevel! neq 0 (
    echo.
    echo [ERROR] Administrator privileges required.
    echo         Right-click this script and select "Run as administrator".
    echo.
    pause
    exit /b 1
)

echo.
echo [INFO] Admin privileges confirmed.

:: -------------------------------------------------------
:: Configuration
:: -------------------------------------------------------
set "appcmd=%SystemRoot%\System32\inetsrv\appcmd.exe"
set "site_name=MyNewSite"
set "site_path=C:\inetpub\sites\mynewsite"
set "binding=http/*:8080:"

:: -------------------------------------------------------
:: Verify appcmd exists
:: -------------------------------------------------------
if not exist "%appcmd%" (
    echo.
    echo [ERROR] appcmd.exe not found at: %appcmd%
    echo         IIS may not be installed or Management Tools are missing.
    echo.
    pause
    exit /b 1
)

echo [INFO] appcmd.exe found.

:: -------------------------------------------------------
:: Check if the site already exists
:: -------------------------------------------------------
"%appcmd%" list site /name:"%site_name%" >nul 2>&1
if !errorlevel! equ 0 (
    echo.
    echo [INFO] Website "%site_name%" already exists. No changes made.
    echo.
    pause
    exit /b 0
)

:: -------------------------------------------------------
:: 1. Create the physical directory
:: -------------------------------------------------------
if not exist "%site_path%" (
    mkdir "%site_path%"
    if !errorlevel! neq 0 (
        echo [ERROR] Failed to create directory: %site_path%
        pause
        exit /b 1
    )
    echo [OK] Created directory: %site_path%
) else (
    echo [OK] Directory already exists: %site_path%
)

:: -------------------------------------------------------
:: 2. Create a default page
:: -------------------------------------------------------
> "%site_path%\index.html" echo ^<html^>^<body^>^<h1^>%site_name% is working!^</h1^>^</body^>^</html^>
echo [OK] Created default index.html

:: -------------------------------------------------------
:: 3. Create the website in IIS
:: -------------------------------------------------------
echo [INFO] Creating website "%site_name%" ...
echo.

"%appcmd%" add site /name:"%site_name%" /physicalPath:"%site_path%" /bindings:%binding%

if !errorlevel! equ 0 (
    echo.
    echo [SUCCESS] Website "%site_name%" created on port 8080.
    echo           Visit: http://localhost:8080
) else (
    echo.
    echo [ERROR] Failed to create website.
    echo         The binding may conflict with an existing site.
    echo         Try: %appcmd% list site
)

echo.
pause
exit /b 0

Understanding the Binding Format

The binding string follows the format: protocol/IPAddress:Port:HostHeader

Binding Example Meaning
http/*:80: HTTP, all IPs, port 80, no host header
http/*:8080: HTTP, all IPs, port 8080, no host header
http/*:80:www.example.com HTTP, all IPs, port 80, host header www.example.com
https/*:443: HTTPS, all IPs, port 443 (requires SSL cert)

The asterisk * means "listen on all available IP addresses."

Method 2: Creating a Website with a Specific Host Header

In production, multiple websites share port 80 by using different host headers (domain names). IIS routes incoming requests to the correct site based on the Host header sent by the browser.

@echo off
setlocal enabledelayedexpansion

set "appcmd=%SystemRoot%\System32\inetsrv\appcmd.exe"

:: -------------------------------------------------------
:: Site Configuration
:: -------------------------------------------------------
set "site_name=CompanyBlog"
set "site_path=C:\inetpub\sites\blog"
set "hostname=blog.company.com"
set "binding=http/*:80:%hostname%"

:: -------------------------------------------------------
:: Admin Check
:: -------------------------------------------------------
net session >nul 2>&1
if !errorlevel! neq 0 (
    echo.
    echo [ERROR] Admin required.
    echo         Right-click and select "Run as administrator".
    echo.
    pause
    exit /b 1
)

echo [OK] Admin privileges confirmed.

:: -------------------------------------------------------
:: Verify appcmd exists
:: -------------------------------------------------------
if not exist "%appcmd%" (
    echo.
    echo [ERROR] appcmd.exe not found at: %appcmd%
    echo         IIS may not be installed.
    echo.
    pause
    exit /b 1
)

echo [OK] appcmd.exe found.

:: -------------------------------------------------------
:: Check for duplicate site name
:: -------------------------------------------------------
"%appcmd%" list site /name:"%site_name%" >nul 2>&1
if !errorlevel! equ 0 (
    echo.
    echo [INFO] Website "%site_name%" already exists. No changes made.
    echo.
    pause
    exit /b 0
)

:: -------------------------------------------------------
:: Check for binding conflict (port 80 + same hostname)
:: -------------------------------------------------------
"%appcmd%" list site /bindings:"%binding%" >nul 2>&1
if !errorlevel! equ 0 (
    echo.
    echo [ERROR] Another site is already using binding: %binding%
    echo         Change the hostname or port to avoid conflict.
    echo.
    pause
    exit /b 1
)

:: -------------------------------------------------------
:: Create directory
:: -------------------------------------------------------
if not exist "%site_path%" (
    mkdir "%site_path%"
    if !errorlevel! neq 0 (
        echo [ERROR] Failed to create directory: %site_path%
        pause
        exit /b 1
    )
    echo [OK] Created directory: %site_path%
) else (
    echo [OK] Directory already exists: %site_path%
)

:: -------------------------------------------------------
:: Create default page
:: -------------------------------------------------------
> "%site_path%\index.html" echo ^<html^>^<body^>^<h1^>%site_name% is live!^</h1^>^</body^>^</html^>
echo [OK] Created default index.html

:: -------------------------------------------------------
:: Create the site with host header binding
:: -------------------------------------------------------
echo [INFO] Creating website "%site_name%"...
echo        Binding: %binding%
echo.

"%appcmd%" add site /name:"%site_name%" /physicalPath:"%site_path%" /bindings:%binding%

if !errorlevel! equ 0 (
    echo.
    echo [SUCCESS] Site "%site_name%" created successfully.
    echo           Accessible at: http://%hostname%
    echo.
    echo [REMINDER] Make sure DNS or hosts file resolves:
    echo            %hostname% -^> this server's IP
) else (
    echo.
    echo [ERROR] Failed to create website.
    echo         Run this to check existing bindings:
    echo         %appcmd% list site
)

echo.
pause
exit /b 0

Method 3: Creating a Website with a Dedicated Application Pool

By default, appcmd add site assigns the new site to the DefaultAppPool. In production, each site should have its own application pool for process isolation, independent recycling, and separate identity credentials.

@echo off
setlocal

set "appcmd=%SystemRoot%\System32\inetsrv\appcmd.exe"

set "site_name=ClientPortal"
set "pool_name=ClientPortalPool"
set "site_path=C:\inetpub\sites\clientportal"
set "hostname=portal.client.com"

net session >nul 2>&1
if %errorlevel% neq 0 (
    echo [ERROR] Admin required.
    pause
    exit /b 1
)

if not exist "%appcmd%" (
    echo [ERROR] appcmd.exe not found. IIS may not be installed.
    pause
    exit /b 1
)

:: 1. Create the directory
if not exist "%site_path%" mkdir "%site_path%"

:: 2. Create a dedicated Application Pool (skip if it already exists)
"%appcmd%" list apppool /name:"%pool_name%" >nul 2>&1
if %errorlevel% equ 0 (
    echo [INFO] App Pool "%pool_name%" already exists. Reusing it.
) else (
    "%appcmd%" add apppool /name:"%pool_name%" /managedRuntimeVersion:"v4.0" /managedPipelineMode:"Integrated"
    if %errorlevel% equ 0 (
        echo [OK] App Pool "%pool_name%" created.
    ) else (
        echo [ERROR] Failed to create App Pool "%pool_name%".
        pause
        exit /b 1
    )
)

:: 3. Create the website (skip if it already exists)
"%appcmd%" list site /name:"%site_name%" >nul 2>&1
if %errorlevel% equ 0 (
    echo [INFO] Website "%site_name%" already exists.
) else (
    "%appcmd%" add site /name:"%site_name%" /physicalPath:"%site_path%" /bindings:http/*:80:%hostname%
    if %errorlevel% equ 0 (
        echo [OK] Website "%site_name%" created.
    ) else (
        echo [ERROR] Failed to create website "%site_name%".
        pause
        exit /b 1
    )
)

:: 4. Assign the site to the dedicated pool
"%appcmd%" set site /site.name:"%site_name%" /[path='/'].applicationPool:"%pool_name%"
echo [OK] Site "%site_name%" assigned to pool "%pool_name%".

:: 5. Verify
echo.
echo Site Configuration:
"%appcmd%" list site /name:"%site_name%"
"%appcmd%" list apppool /name:"%pool_name%"

pause

Managed Runtime Versions

Value Framework
v2.0 .NET Framework 2.0/3.0/3.5
v4.0 .NET Framework 4.x
"" No managed code (static files, PHP)

For sites serving only static HTML/CSS/JS or PHP, set the managed runtime to empty:

"%appcmd%" add apppool /name:"%pool_name%" /managedRuntimeVersion:"" /managedPipelineMode:"Integrated"

Method 4: Bulk Site Creation from a Configuration File

For provisioning multiple sites at once, read the site definitions from a text file.

Create a file called sites.txt:

SiteA|C:\inetpub\sites\sitea|www.sitea.com
SiteB|C:\inetpub\sites\siteb|www.siteb.com
SiteC|C:\inetpub\sites\sitec|www.sitec.com

Then process it with a Batch Script:

@echo off
setlocal enabledelayedexpansion

set "appcmd=%SystemRoot%\System32\inetsrv\appcmd.exe"
set "config_file=%~dp0sites.txt"

net session >nul 2>&1
if %errorlevel% neq 0 (
    echo [ERROR] Admin required.
    pause
    exit /b 1
)

if not exist "%appcmd%" (
    echo [ERROR] appcmd.exe not found. IIS may not be installed.
    pause
    exit /b 1
)

if not exist "%config_file%" (
    echo [ERROR] Configuration file not found: %config_file%
    pause
    exit /b 1
)

echo Provisioning sites from %config_file%...
echo.

set "success_count=0"
set "skip_count=0"
set "fail_count=0"

for /f "usebackq tokens=1,2,3 delims=|" %%A in ("%config_file%") do (
    set "name=%%A"
    set "path=%%B"
    set "host=%%C"

    :: Validate that all three fields are present
    if not defined name (
        echo   [SKIP] Empty line or missing site name.
        set /a "skip_count+=1"
    ) else if not defined path (
        echo   [SKIP] !name!: Missing physical path.
        set /a "skip_count+=1"
    ) else if not defined host (
        echo   [SKIP] !name!: Missing hostname.
        set /a "skip_count+=1"
    ) else (
        :: Check if site already exists
        "%appcmd%" list site /name:"!name!" >nul 2>&1
        if !errorlevel! equ 0 (
            echo   [SKIP] !name!: Already exists.
            set /a "skip_count+=1"
        ) else (
            echo   Creating: !name! at !host!...

            if not exist "!path!" mkdir "!path!"

            "%appcmd%" add apppool /name:"!name!Pool" /managedRuntimeVersion:"v4.0" >nul 2>&1
            "%appcmd%" add site /name:"!name!" /physicalPath:"!path!" /bindings:http/*:80:!host! >nul 2>&1

            if !errorlevel! equ 0 (
                "%appcmd%" set site /site.name:"!name!" /[path='/'].applicationPool:"!name!Pool" >nul 2>&1
                echo   [OK] !name! provisioned.
                set /a "success_count+=1"
            ) else (
                echo   [FAIL] !name!: Could not create site. Binding may conflict.
                set /a "fail_count+=1"
            )
        )
    )
)

echo.
echo =============================================
echo Results: !success_count! created, !skip_count! skipped, !fail_count! failed.
echo =============================================
echo.
echo All registered sites:
"%appcmd%" list site

pause

Common Mistakes

The Wrong Way: Using a Port Already in Use

:: WRONG - Port 80 may already be used by "Default Web Site"
"%appcmd%" add site /name:"MySite" /physicalPath:"C:\web" /bindings:http/*:80:

The Wrong Way: Forgetting the Physical Path

:: WRONG - The directory does not exist yet
"%appcmd%" add site /name:"MySite" /physicalPath:"C:\web\newsite" /bindings:http/*:8080:

While IIS will create the site entry even if the directory does not exist, browsing to the site will return a 500.19 error because IIS cannot find the content root. Always create the directory first with mkdir.

The Wrong Way: Creating Duplicate Sites

:: WRONG - Does not check whether the site already exists
"%appcmd%" add site /name:"MySite" /physicalPath:"C:\web" /bindings:http/*:8080:
:: Running this script a second time produces an error

Best Practices

  1. One app pool per site: Never share application pools between production websites. An unhandled exception in one site should not crash another.
  2. Use host headers: Avoid binding multiple sites to unique ports. Host headers are the standard way to serve multiple domains from a single server on port 80/443.
  3. Create the directory first: Ensure the physical path exists before creating the IIS site to avoid 500.19 errors.
  4. Check for existing sites: Always verify that a site with the same name or binding does not already exist before attempting to create one. This makes scripts idempotent and safe to re-run.
  5. Verify after creation: Always run appcmd list site after provisioning to confirm the site was created with the correct bindings and pool assignment.
  6. Verify appcmd.exe exists: Check for the tool before running any commands to provide a clear error message on systems where IIS is not installed.

Conclusion

Creating new websites in IIS from a Batch Script is powered by the appcmd.exe command-line tool. By specifying the site name, physical path, and binding string, administrators can provision fully functional websites in seconds. Pairing each site with a dedicated application pool ensures process isolation, while bulk provisioning from a configuration file scales the approach to handle dozens of sites across server farms with consistent, repeatable results.

Navigation