PowerShell Script to List IIS Virtual Directories with Physical Path, App Pool, and Authentication Details


2 views
Import-Module WebAdministration

# Get all websites
$sites = Get-ChildItem IIS:\Sites

# Initialize results array
$results = @()

foreach ($site in $sites) {
    # Get all virtual directories for current site
    $vdirs = Get-WebVirtualDirectory -Site $site.Name
    
    foreach ($vdir in $vdirs) {
        # Get application pool information if applicable
        $appPool = ""
        $appPath = $vdir.Path
        if ($appPath -ne "/") {
            $app = Get-WebApplication -Site $site.Name | Where-Object {$_.path -eq $appPath}
            if ($app) {
                $appPool = $app.applicationPool
            }
        }
        
        # Get authentication settings
        $auth = Get-WebConfigurationProperty -Filter "system.webServer/security/authentication/*" -Location "$($site.Name)$($vdir.Path)" -Name "enabled" -ErrorAction SilentlyContinue | 
            Where-Object {$_.Value -eq $true} | 
            Select-Object -ExpandProperty ItemXPath -ErrorAction SilentlyContinue
        
        # Create custom object with all properties
        $result = [PSCustomObject]@{
            SiteName        = $site.Name
            VirtualPath     = $vdir.Path
            PhysicalPath    = $vdir.PhysicalPath
            ApplicationPool = $appPool
            Authentication  = if ($auth) { $auth.Split('/')[-1] } else { "Not Configured" }
            Credentials     = if ($vdir.userName) { $vdir.userName } else { "Pass-through" }
        }
        
        $results += $result
    }
}

# Output results
$results | Format-Table -AutoSize

This script uses the WebAdministration module to query IIS configuration. Here's the breakdown:

1. First we import the WebAdministration module
2. We retrieve all IIS sites
3. For each site, we get all virtual directories
4. For each virtual directory, we collect:
   - Site name
   - Virtual path
   - Physical path
   - Associated application pool (if any)
   - Authentication method
   - Credentials being used
5. Finally, we output the collected data in table format

For virtual directories that are actually applications (have application pools), we need additional logic:

$app = Get-WebApplication -Site $site.Name | Where-Object {$_.path -eq $appPath}
if ($app) {
    $appPool = $app.applicationPool
}

The authentication settings require querying the IIS configuration system:

Get-WebConfigurationProperty -Filter "system.webServer/security/authentication/*" 
    -Location "$($site.Name)$($vdir.Path)" 
    -Name "enabled" 
    -ErrorAction SilentlyContinue

If you prefer using appcmd.exe, here's a one-liner that outputs similar information:

appcmd list vdir /text:*

To parse this output in PowerShell:

appcmd list vdir /text:* | ForEach-Object {
    $parts = $_ -split '"'
    [PSCustomObject]@{
        SiteName = $parts[1]
        VirtualPath = $parts[3]
        PhysicalPath = $parts[5]
    }
}

To save the results for documentation or analysis:

$results | Export-Csv -Path "IIS_VirtualDirectories.csv" -NoTypeInformation

When working with IIS 8+, many administrators struggle to extract comprehensive virtual directory information through PowerShell. The common pitfalls include:

  • Mixing up Web Applications with Virtual Directories
  • Missing authentication configuration details
  • Incomplete property mapping between IIS Manager and PowerShell outputs

Here's a robust script that extracts all required virtual directory properties:

Import-Module WebAdministration
$output = @()

Get-ChildItem IIS:\Sites | ForEach-Object {
    $site = $_
    Get-WebVirtualDirectory -Site $site.Name | ForEach-Object {
        $vdir = $_
        
        # Get authentication settings
        $auth = Get-WebConfigurationProperty 
                -Filter "system.webServer/security/authentication/*" 
                -Name "enabled" 
                -PSPath "IIS:\Sites\$($site.Name)" 
                -Location $vdir.Path
        
        $output += [PSCustomObject]@{
            SiteName = $site.Name
            VDirName = $vdir.Path.Split('/')[-1]
            PhysicalPath = $vdir.PhysicalPath
            AppPool = (Get-ItemProperty "IIS:\Sites\$($site.Name)\$($vdir.Path)" -Name applicationPool).Value
            AnonymousAuth = ($auth | Where-Object { $_.ItemXPath -like "*anonymousAuthentication*" }).Value
            WindowsAuth = ($auth | Where-Object { $_.ItemXPath -like "*windowsAuthentication*" }).Value
            BasicAuth = ($auth | Where-Object { $_.ItemXPath -like "*basicAuthentication*" }).Value
        }
    }
}

$output | Format-Table -AutoSize

The script handles several technical nuances:

  1. Authentication Retrieval: Uses Get-WebConfigurationProperty to dig into security settings
  2. App Pool Association: Gets the actual application pool instead of just the containing site's pool
  3. Path Parsing: Properly handles nested virtual directory paths

For environments where WebAdministration module isn't available:

$namespace = "root\MicrosoftIISv2"
$sites = Get-CimInstance -Namespace $namespace -ClassName "IIsWebServerSetting"

foreach ($site in $sites) {
    $vdirs = Get-CimAssociatedInstance -InputObject $site 
            -ResultClassName "IIsWebVirtualDirSetting"
    
    foreach ($vdir in $vdirs) {
        [PSCustomObject]@{
            Server = $site.ServerComment
            VDir = $vdir.Name.Split(',')[-1]
            Path = $vdir.Path
            AppPool = $vdir.AppPoolId
        }
    }
}

For integration with monitoring systems:

$output | ConvertTo-Json -Depth 5 | Out-File "iis_vdirs.json"
  • Run PowerShell as Administrator when querying IIS
  • Check if WebAdministration module is properly installed (Add-WindowsFeature Web-Scripting-Tools)
  • For nested virtual directories, use Get-Item with full IIS provider path