A virtual directory in IIS maps a URL path to a physical folder on the file system that may exist outside the website's root directory. This allows you to serve content from multiple disk locations under a single website URL structure without duplicating files or restructuring your storage layout.
In this guide, we will explore how to create, configure, and manage IIS virtual directories from a Batch Script using the appcmd.exe command-line tool.
Understanding Virtual Directories
A virtual directory creates an alias in the URL namespace that points to any physical folder on the server (or a network share). For example:
| URL Path | Physical Path | Type |
|---|---|---|
http://site.com/ |
C:\inetpub\wwwroot |
Website root |
http://site.com/downloads |
D:\SharedFiles\Downloads |
Virtual directory |
http://site.com/reports |
\\FileServer\Reports |
Virtual directory (UNC path) |
Without virtual directories, all content must reside within the website's root folder tree. Virtual directories break this limitation, allowing flexible content organization across drives, partitions, and network shares.
Method 1: Creating a Basic Virtual Directory
@echo off
setlocal
set "appcmd=%SystemRoot%\System32\inetsrv\appcmd.exe"
set "site_name=CompanyIntranet"
set "vdir_alias=downloads"
set "vdir_path=D:\SharedFiles\Downloads"
:: Verify Admin
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Administrator privileges required.
pause
exit /b 1
)
:: Verify appcmd exists
if not exist "%appcmd%" (
echo [ERROR] appcmd.exe not found at: %appcmd%
echo IIS may not be installed or Management Tools are missing.
pause
exit /b 1
)
:: Verify the site exists
"%appcmd%" list site /name:"%site_name%" >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Website "%site_name%" not found in IIS.
pause
exit /b 1
)
:: Ensure the physical directory exists
if not exist "%vdir_path%" (
echo [ERROR] Physical path does not exist: %vdir_path%
echo Create the directory first or verify the path.
pause
exit /b 1
)
:: Check if the virtual directory already exists
"%appcmd%" list vdir /vdir.name:"%site_name%/%vdir_alias%" >nul 2>&1
if %errorlevel% equ 0 (
echo [INFO] Virtual directory "/%vdir_alias%" already exists on "%site_name%".
pause
exit /b 0
)
echo Creating virtual directory "/%vdir_alias%" on "%site_name%"...
"%appcmd%" add vdir /app.name:"%site_name%/" /path:"/%vdir_alias%" /physicalPath:"%vdir_path%"
if %errorlevel% equ 0 (
echo [SUCCESS] Virtual directory created.
echo URL path: /%vdir_alias%/
echo Maps to: %vdir_path%
) else (
echo [ERROR] Failed to create virtual directory.
echo Check that the app name "%site_name%/" is correct.
)
pauseThe /app.name Parameter
The /app.name must include the trailing slash. For the root application of a site named "CompanyIntranet", the app name is CompanyIntranet/. For a sub-application, it would be CompanyIntranet/subapp/.
Method 2: Creating a Virtual Directory Pointing to a Network Share
Virtual directories can point to UNC paths, allowing IIS to serve files stored on remote file servers.
@echo off
setlocal
set "appcmd=%SystemRoot%\System32\inetsrv\appcmd.exe"
set "site_name=CompanyPortal"
set "vdir_alias=shared-docs"
set "vdir_path=\\FileServer\Documents\Public"
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
)
:: Verify the site exists
"%appcmd%" list site /name:"%site_name%" >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Site "%site_name%" not found in IIS.
pause
exit /b 1
)
:: Check if the UNC path is reachable
if not exist "%vdir_path%" (
echo [WARNING] UNC path is not currently reachable: %vdir_path%
echo The virtual directory will be created, but IIS will return
echo errors until the path becomes accessible.
echo.
set /p "proceed=Continue anyway? (Y/N): "
if /i not "!proceed!"=="Y" (
echo [CANCELLED]
pause
exit /b 0
)
)
:: Check for existing virtual directory
"%appcmd%" list vdir /vdir.name:"%site_name%/%vdir_alias%" >nul 2>&1
if %errorlevel% equ 0 (
echo [INFO] Virtual directory "/%vdir_alias%" already exists.
pause
exit /b 0
)
echo Creating virtual directory for UNC path...
"%appcmd%" add vdir /app.name:"%site_name%/" /path:"/%vdir_alias%" /physicalPath:"%vdir_path%"
if %errorlevel% equ 0 (
echo [SUCCESS] Virtual directory "/%vdir_alias%" created.
echo Points to: %vdir_path%
) else (
echo [ERROR] Failed to create virtual directory.
)
pauseSetting Connect-As Credentials
To provide explicit credentials for accessing a network share:
@echo off
setlocal enabledelayedexpansion
set "appcmd=%SystemRoot%\System32\inetsrv\appcmd.exe"
set "site_name=CompanyPortal"
set "vdir_alias=shared-docs"
set "username=DOMAIN\ServiceAccount"
set "password=SecureP@ssw0rd"
:: Verify the virtual directory exists before setting credentials
"%appcmd%" list vdir /vdir.name:"%site_name%/%vdir_alias%" >nul 2>&1
if !errorlevel! neq 0 (
echo [ERROR] Virtual directory "%site_name%/%vdir_alias%" not found.
pause
exit /b 1
)
"%appcmd%" set vdir /vdir.name:"%site_name%/%vdir_alias%" /userName:"%username%" /password:"%password%"
if !errorlevel! equ 0 (
echo [OK] Credentials configured for UNC access.
) else (
echo [ERROR] Failed to set credentials.
)
pauseMethod 3: Creating Multiple Virtual Directories from a Configuration List
For provisioning a site with several virtual directories at once:
@echo off
setlocal enabledelayedexpansion
set "appcmd=%SystemRoot%\System32\inetsrv\appcmd.exe"
set "site_name=DepartmentSite"
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
)
:: Verify the site exists
"%appcmd%" list site /name:"%site_name%" >nul 2>&1
if !errorlevel! neq 0 (
echo [ERROR] Site "%site_name%" not found in IIS.
pause
exit /b 1
)
echo Provisioning virtual directories for "%site_name%"...
echo.
set "success=0"
set "skipped=0"
set "failed=0"
:: Define virtual directories: alias|physical_path
for %%D in (
"downloads|D:\PublicFiles\Downloads"
"uploads|D:\PublicFiles\Uploads"
"reports|D:\Reports\Monthly"
"images|E:\MediaLibrary\Images"
) do (
for /f "tokens=1,2 delims=|" %%A in (%%D) do (
set "alias=%%A"
set "path=%%B"
:: Check if already exists
"%appcmd%" list vdir /vdir.name:"%site_name%/!alias!" >nul 2>&1
if !errorlevel! equ 0 (
echo [SKIP] /!alias! - already exists.
set /a "skipped+=1"
) else (
if not exist "!path!" mkdir "!path!"
"%appcmd%" add vdir /app.name:"%site_name%/" /path:"/!alias!" /physicalPath:"!path!" >nul 2>&1
if !errorlevel! equ 0 (
echo [OK] /!alias! -^> !path!
set /a "success+=1"
) else (
echo [FAIL] /!alias! - could not create.
set /a "failed+=1"
)
)
)
)
echo.
echo Results: !success! created, !skipped! skipped, !failed! failed.
echo.
echo Current virtual directories:
"%appcmd%" list vdir /app.name:"%site_name%/"
pauseMethod 4: Listing Existing Virtual Directories
@echo off
setlocal enabledelayedexpansion
set "appcmd=%SystemRoot%\System32\inetsrv\appcmd.exe"
set "site_name=CompanyIntranet"
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
)
:: Verify the site exists
"%appcmd%" list site /name:"%site_name%" >nul 2>&1
if !errorlevel! neq 0 (
echo [ERROR] Site "%site_name%" not found in IIS.
pause
exit /b 1
)
echo Virtual directories for "%site_name%":
echo =======================================
echo.
set "count=0"
for /f "delims=" %%V in ('"%appcmd%" list vdir /app.name:"%site_name%/" /text:path 2^>nul') do (
set "vpath=%%V"
set "physpath="
for /f "delims=" %%P in ('"%appcmd%" list vdir /vdir.name:"%site_name%!vpath!" /text:physicalPath 2^>nul') do set "physpath=%%P"
echo !vpath! -^> !physpath!
set /a "count+=1"
)
if !count! equ 0 (
echo [No virtual directories found]
)
echo.
echo Total: !count! virtual directories
pauseMethod 5: Deleting a Virtual Directory
@echo off
setlocal
set "appcmd=%SystemRoot%\System32\inetsrv\appcmd.exe"
set "site_name=CompanyIntranet"
set "vdir_alias=old-reports"
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
)
:: Check if the virtual directory exists
"%appcmd%" list vdir /vdir.name:"%site_name%/%vdir_alias%" >nul 2>&1
if %errorlevel% neq 0 (
echo [INFO] Virtual directory "/%vdir_alias%" does not exist on "%site_name%".
echo Nothing to delete.
pause
exit /b 0
)
echo Removing virtual directory "/%vdir_alias%" from "%site_name%"...
"%appcmd%" delete vdir /vdir.name:"%site_name%/%vdir_alias%"
if %errorlevel% equ 0 (
echo [SUCCESS] Virtual directory removed from IIS configuration.
echo The physical files at the target path are NOT deleted.
) else (
echo [ERROR] Failed to delete virtual directory.
)
pauseWhat Gets Deleted?
Like site deletion, removing a virtual directory only removes the IIS configuration mapping. The physical files at the target path are not touched.
Virtual Directory vs. Application
IIS distinguishes between virtual directories and applications:
| Feature | Virtual Directory | Application |
|---|---|---|
| Has its own app pool? | No (inherits parent) | Yes (can have its own) |
Has its own web.config? |
Yes (inherited settings) | Yes (independent) |
| Runs own .NET runtime? | No (shares parent) | Yes (isolated) |
| Created with | appcmd add vdir |
appcmd add app |
Use a virtual directory when you just need a path alias to a different folder. Use an application when you need process isolation or a different .NET framework version.
Common Mistakes
The Wrong Way: Forgetting the App Name Trailing Slash
:: WRONG - Missing trailing slash in app name
"%appcmd%" add vdir /app.name:"MySite" /path:"/files" /physicalPath:"D:\Files"The Wrong Way: Assuming Permissions Are Inherited
:: WRONG assumption - The VDIR physical path may have different ACLs
"%appcmd%" add vdir /app.name:"MySite/" /path:"/secure" /physicalPath:"E:\RestrictedData"The physical folder's NTFS permissions are independent of IIS configuration. If the IIS worker process identity does not have read access to E:\RestrictedData, visitors will receive a 401 - Unauthorized or 500.19 error even though the virtual directory is correctly configured in IIS.
The Wrong Way: Creating a Virtual Directory Without Checking for Duplicates
:: WRONG - Running this twice produces an error
"%appcmd%" add vdir /app.name:"MySite/" /path:"/files" /physicalPath:"D:\Files"Best Practices
- Verify the physical path exists: Always validate that the target directory exists before configuring the virtual directory. For UNC paths, warn the user if the path is unreachable but allow creation since the share may become available later.
- Check NTFS permissions: Ensure the IIS worker process identity has at least Read access to the physical folder.
- Use domain accounts for UNC paths: When pointing to network shares, configure the pool identity or "Connect As" credentials appropriately. Never hardcode passwords in script files.
- Choose virtual directories over applications: For simple path aliasing, virtual directories are lighter weight and simpler to manage. Use applications only when you need process isolation or a different .NET runtime.
- Check for existing virtual directories: Always verify a virtual directory does not already exist before attempting to create one, making scripts idempotent and safe to re-run.
- Verify
appcmd.exeand the target site exist: Check for both the tool and the target site at the start of every script to provide clear error messages. - Use
for /f "delims="with/text:for property queries: When querying virtual directory properties, use the/text:flag for clean output anddelims=to capture values including spaces.
Conclusion
Creating virtual directories in IIS from a Batch Script is a single appcmd add vdir command that maps a URL path alias to any physical folder on the server or network. This powerful feature enables flexible content organization across multiple storage locations without restructuring the website's directory hierarchy. By combining virtual directories with proper NTFS permissions and credential configuration, administrators can build sophisticated content-serving architectures that cleanly separate storage concerns from URL design.