64

I am documenting all the sites and binding related to the site from the IIS. Is there an easy way to get this list through a PowerShell script rather than manually typing looking at IIS?

I want the output to be something like this:

Site                          Bindings
TestSite                     www.hello.com
                             www.test.com
JonDoeSite                   www.johndoe.site
halfer
  • 19,824
  • 17
  • 99
  • 186
sanjeev40084
  • 9,227
  • 18
  • 67
  • 99
  • 2
    what version of Windows/IIS do you have? With IIS on Windows Server 2012 you can simply use `Get-WebBinding` if I remember correctly. – Frode F. Mar 20 '13 at 16:07
  • 1
    Yes it is Server 2012. Running Get-Webbinding returns protocal, bindinginformaiton, sslFlags. not in same format as i want my output. – sanjeev40084 Mar 20 '13 at 16:09

9 Answers9

106

Try this:

Import-Module Webadministration
Get-ChildItem -Path IIS:\Sites

It should return something that looks like this:

Name             ID   State      Physical Path                  Bindings
----             --   -----      -------------                  --------
ChristophersWeb 22   Started    C:\temp             http *:8080:ChristophersWebsite.ChDom.com

From here you can refine results, but be careful. A pipe to the select statement will not give you what you need. Based on your requirements I would build a custom object or hashtable.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Christopher Douglas
  • 1,519
  • 2
  • 9
  • 16
  • how does it work? I mean it works but no matter where i have my files located? the IIS:\Sites will always pick items from IIS? or is that bound to a spec. path ? – RayofCommand Jun 23 '14 at 10:56
  • 1
    @RayofCommand - this works by parsing out the location defined in the IIS web configuration files, the ones that replaced the IIS 5/6 Metabase. These are xml files by nature and are found in C:\Windows\System32\inetsrv\config – Christopher Douglas Jul 26 '14 at 02:58
  • 1
    At least in Windows 2008 R2 SP1 you must first call `Set-ExecutionPolicy RemoteSigned` or the _Import-Module_ will not work. And you need to put the argument in quotes, like this: `Get-ChildItem -Path "IIS:\Sites"`, or you'll receive a syntax error. – Abel Jun 16 '16 at 09:50
  • That should not occur, the module is signed. I'll research that. @Abel – Christopher Douglas Jun 30 '16 at 06:27
  • I get an error that says `Cannot find drive. A drive with the name 'IIS' does not exist.` when I try to run the above command. Do you know why this might be happening? – Ryan Gates Jan 30 '17 at 21:35
  • @RyanGates When you run Import-Module WebAdministration does it throw an error? This module should add the IIS PS provider to your session. Ensure you're running as an administrator as well. – Christopher Douglas Jan 31 '17 at 20:04
  • 2
    `Get-Website` does essentially the same thing and is a bit shorter. – Raman Apr 19 '17 at 15:59
  • Just want to add a note that this does not work with older version of powershell. command "Get-Host | Select-Object Version" returns "1.0.0.0" Running the PS C:\Windows\System32> Import-Module Webadmininstration The term 'Import-Module' is not recognized as a cmdlet, function, operable prog ram, or script file. Verify the term and try again. At line:1 char:14 + Import-Module <<<< Webadmininstrationimport command fails right away is a good indicator. – g5thomas Apr 12 '19 at 15:56
73

Try something like this to get the format you wanted:

Get-WebBinding | % {
    $name = $_.ItemXPath -replace '(?:.*?)name=''([^'']*)(?:.*)', '$1'
    New-Object psobject -Property @{
        Name = $name
        Binding = $_.bindinginformation.Split(":")[-1]
    }
} | Group-Object -Property Name | 
Format-Table Name, @{n="Bindings";e={$_.Group.Binding -join "`n"}} -Wrap
Frode F.
  • 52,376
  • 9
  • 98
  • 114
  • 3
    Very nice. I would not have thought to add regex to evaluate the objects, but that's very good use of the New\Group-Object cmdlets. I will have to update some code in light of that. – Christopher Douglas Mar 20 '13 at 16:41
  • Using powershell.exe to call myscript.ps1, Format-Table not working to display (output) – Kiquenet Oct 17 '14 at 08:30
  • 1
    In Windows 2008 R2 SP1, this throws error _"The term 'Get-WebBinding' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again."_ (the second answer below works if mildly changed). – Abel Jun 16 '16 at 09:40
  • It's already mentioned in the first comment on the question :) – Frode F. Jun 17 '16 at 21:09
  • Awesome Script only one thing have to do. We have to run powershell as administrator – Sourabh Somani Jan 19 '18 at 05:07
31

If you just want to list all the sites (ie. to find a binding)

Change the working directory to "C:\Windows\system32\inetsrv"

cd c:\Windows\system32\inetsrv

Next run "appcmd list sites" (plural) and output to a file. e.g c:\IISSiteBindings.txt

appcmd list sites > c:\IISSiteBindings.txt

Now open with notepad from your command prompt.

notepad c:\IISSiteBindings.txt

AndrewRalon
  • 496
  • 1
  • 9
  • 24
Armand G.
  • 1,817
  • 14
  • 8
  • 1
    Not a PS answer; but short and sweet and also lists ID numbers which can be useful for scanning IIS logs. – Donny McCoy Nov 30 '16 at 14:22
  • This is the best answer for those running a very old version of Windows Server. Windows server 6.0 (Build 6003: Service Pack 2). Keep in mind that you might need to start command prompt with Administration access. – g5thomas Apr 12 '19 at 15:53
  • 1
    As a one liner: `c:\Windows\system32\inetsrv\appcmd list sites` – JohnLBevan Oct 22 '21 at 10:22
28

The most easy way as I saw:

Foreach ($Site in get-website) { Foreach ($Bind in $Site.bindings.collection) {[pscustomobject]@{name=$Site.name;Protocol=$Bind.Protocol;Bindings=$Bind.BindingInformation}}}
Alexander Shapkin
  • 1,126
  • 1
  • 13
  • 11
  • 1
    Great solution, Alexander!, I just added physicalPath: `Foreach ($Site in get-website) { Foreach ($Bind in $Site.bindings.collection) { [pscustomobject]@{name=$Site.name;Protocol=$Bind.Protocol;Bindings=$Bind.BindingInformation; path=$Site.physicalPath }}}` – Andrew Apr 14 '18 at 08:12
  • This worked for me. Thank you so much. You may need to **Run Powershell as Administrator** for this script to execute, else you might get an error that **you should have elevated status to access IIS configuration data**. – Promise Preston Aug 24 '20 at 15:07
2

Try this

function DisplayLocalSites
{

try{

Set-ExecutionPolicy unrestricted

$list = @()
foreach ($webapp in get-childitem IIS:\Sites\)
{
    $name = "IIS:\Sites\" + $webapp.name
    $item = @{}

$item.WebAppName = $webapp.name

foreach($Bind in $webapp.Bindings.collection)
{
    $item.SiteUrl = $Bind.Protocol +'://'+         $Bind.BindingInformation.Split(":")[-1]
}


$obj = New-Object PSObject -Property $item
$list += $obj
}

$list | Format-Table -a -Property "WebAppName","SiteUrl"

$list | Out-File -filepath C:\websites.txt

Set-ExecutionPolicy restricted

}
catch
{
$ExceptionMessage = "Error in Line: " + $_.Exception.Line + ". " +     $_.Exception.GetType().FullName + ": " + $_.Exception.Message + " Stacktrace: "    + $_.Exception.StackTrace
$ExceptionMessage
}
}
snimakom
  • 101
  • 2
  • this one only shows my first domain in each IIS:\Sites\ and not all other domain name bindings i configured within the same site. – Paul Fijma Dec 28 '16 at 19:15
2
function Get-ADDWebBindings {
param([string]$Name="*",[switch]$http,[switch]$https)
    try {
    if (-not (Get-Module WebAdministration)) { Import-Module WebAdministration }
    Get-WebBinding | ForEach-Object { $_.ItemXPath -replace '(?:.*?)name=''([^'']*)(?:.*)', '$1' } | Sort | Get-Unique | Where-Object {$_ -like $Name} | ForEach-Object {
        $n=$_
        Get-WebBinding | Where-Object { ($_.ItemXPath -replace '(?:.*?)name=''([^'']*)(?:.*)', '$1') -like $n } | ForEach-Object {
            if ($http -or $https) {
                if ( ($http -and ($_.protocol -like "http")) -or ($https -and ($_.protocol -like "https")) ) {
                    New-Object psobject -Property @{Name = $n;Protocol=$_.protocol;Binding = $_.bindinginformation}
                }
            } else {
                New-Object psobject -Property @{Name = $n;Protocol=$_.protocol;Binding = $_.bindinginformation}
            }
        }
    }
    }
    catch {
       $false
    }
}
Biswas
  • 598
  • 2
  • 16
  • 34
2

I found this page because I needed to migrate a site with many many bindings to a new server. I used some of the code here to generate the powershell script below to add the bindings to the new server. Sharing in case it is useful to someone else:

Import-Module WebAdministration
$Websites = Get-ChildItem IIS:\Sites
$site = $Websites | Where-object { $_.Name -eq 'site-name-in-iis-here' }

$Binding = $Site.bindings
[string]$BindingInfo = $Binding.Collection
[string[]]$Bindings = $BindingInfo.Split(" ")
$i = 0
$header = ""
Do{
    [string[]]$Bindings2 = $Bindings[($i+1)].Split(":")

    Write-Output ("New-WebBinding -Name `"site-name-in-iis-here`" -IPAddress " + $Bindings2[0] + " -Port " + $Bindings2[1] + " -HostHeader `"" + $Bindings2[2] + "`"")

    $i=$i+2
} while ($i -lt ($bindings.count))

It generates records that look like this:

New-WebBinding -Name "site-name-in-iis-here" -IPAddress "*" -Port 80 -HostHeader www.aaa.com
user230910
  • 2,353
  • 2
  • 28
  • 50
1

Update IIS 10.0+ (2017+)

You can use the newer IISAdministration module with the Get-IISSite cmdlet like this:

PS> Import-Module IISAdministration
PS> Get-IISSite

Name             ID   State      Physical Path                  Bindings
----             --   -----      -------------                  --------
Default Web Site 1    Started    %SystemDrive%\inetpub\wwwroot  http *:80: 
PattiFul         2    Stopped    C:\inetpub\PattiFul            http *:8080: 
                                                                http *:8033: 
FTPSite          3               C:\inetpub\ftproot             ftp *:21: 
DavidChe         4    Started    c:\                            http *:8088: 
MyNewSite        6555 Started    C:\inetpub\wwwroot             http *:8099: 
                                                                http *:8022:
KyleMit
  • 30,350
  • 66
  • 462
  • 664
0

I found this question because I wanted to generate a web page with links to all the websites running on my IIS instance. I used Alexander Shapkin's answer to come up with the following to generate a bunch of links.

$hostname = "localhost"

Foreach ($Site in get-website) {
    Foreach ($Bind in $Site.bindings.collection) {
        $data = [PSCustomObject]@{
            name=$Site.name;
            Protocol=$Bind.Protocol;
            Bindings=$Bind.BindingInformation
        }
        $data.Bindings = $data.Bindings -replace '(:$)', ''
        $html = "<a href=""" + $data.Protocol + "://" + $data.Bindings + """>" + $data.name + "</a>"
        $html.Replace("*", $hostname);
    }
}

Then I paste the results into this hastily written HTML:

<html>
<style>
    a { display: block; }
</style>
{paste PowerShell results here}
</body>
</html>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Walter Stabosz
  • 7,447
  • 5
  • 43
  • 75