phuzi
phuzi

Reputation: 13079

Remove-WebBindings removing binding from all IIS sites

I am creating a Powershell script using the WebAdministration module to create a couple of sites and automatically add bindings

Import-Module WebAdministration

$config = @{
    Sites = @( 
        @{
            Name = "Site1";
            Path = "Path1";
            Bindings = @(
                @{ Protocol = "http"; Port = 80;},
                @{ Protocol = "https"; Port = 443;}
            );
        },
        @{
            Name = "Site2";
            Path = "Path2";
            Bindings = @(
                @{ Protocol = "http"; Port = 3009;}
            );
        }
    )
}

foreach($site in $config.Sites){
    $physicalPath = Get-Item "$($site.Path)"
    # Create the current site
    New-WebSite -Name "$($site.Name)" -PhysicalPath $physicalPath.FullName

    ## Trying to remove default port 80 binding for the current site
    Remove-WebBinding -Name $site.Name -Port 80 -Protocol "http"

    ## Add the desired bindings
    foreach ($binding in $site.Bindings){
        New-WebBinding -Name "$($site.Name)" -Protocol $binding.Protocol -Port $binding.Port
    }
}

When I do this though, I'm left without a binding on port 80 Site1. It looks like Remove-WebBinding -Name $site.Name -Port 80 -Protocol "http" is removing bindings for both sites.

PS > Get-ChildItem IIS:\Sites

Name             ID   State      Physical Path                  Bindings
----             --   -----      -------------                  --------
Site1            1    Started    Path1                          https *:443: sslFlags=0
Site2            2    Stopped    Path2                          http *:3009:

If I do this without attempting to modify any bindings

foreach($site in $config.Sites){
    $physicalPath = Get-Item "$($site.Path)"
    # Create the current site
    New-WebSite -Name "$($site.Name)" -PhysicalPath $physicalPath.FullName
}

I end up with both sites bound to port 80

PS > Get-ChildItem IIS:\Sites

Name             ID   State      Physical Path                  Bindings
----             --   -----      -------------                  --------
Site1            1    Started    Path1                          http *:80:
Site2            2    Stopped    Path2                          http *:80:

What am I doing wrong? Is there a better way? Is this a bug?

Upvotes: 1

Views: 3123

Answers (3)

Krzysztof Jabłoński
Krzysztof Jabłoński

Reputation: 1941

I just experienced this erroneous behavior of Remove-WebBinding. There is definitely a bug in the tool or at least implementation does not follow specification outlined in documentation as of version 1.0.0 in May 2024. Syntax variant #1 allows specifying target binding by site name, IP address and port, protocol and hostreader name. If you happen to omit IP address or port, default values of * are inferred (consult the output with -WhatIf).

PS C:\> Remove-WebBinding -WhatIf -Name Site2
What if: Performing the operation "Remove-WebBinding" on target "-Site Site2 -IPAddress * -Port *".

It correctly describes what it should (and is expected to) do if executed, but for whatever reason the site name is ignored during the actual execution.

Following the code you originally posted in the question, on 2nd iteration of outer loop the tool is called with -port 80 which counts and -name Site2 which is ignored, that's when it removes port 80 bindings from all sites. If you happen to omit both IP address and port, it effectively wipes out all binding-website associations from IIS. Uncool.

Syntax variant #2 (the one with -InputObject passed) behaves correctly. That's the one featured in the only example on the page and also the one Brandon recommended in the answer above.

Upvotes: 0

Brandon
Brandon

Reputation: 51

I have seen similar behavior. Rather than attempting to explicitly find and remove a binding entry, I have found more success using the pipeline to reference an already identified object.

For example:

Get-Website -Name "$($site.Name)" | Get-WebBinding -Protocol "http" -Port 80 | Remove-WebBinding

Upvotes: 5

phuzi
phuzi

Reputation: 13079

Managed to get around Remove-WebBinding by using the first binding when creating the site and then iterating through any remaining bindings.

foreach($site in $config.Sites){
    $physicalPath = Get-Item "$($site.Path)"

    $defaultBinding = ($site.Bindings | Select-Object -First 1)

    # Use Splatting
    $newWebSiteParams = @{
        Name = $site.Name;
        PhysicalPath = $physicalPath.FullName;
        ApplicationPool = $site.ApplicationPool
        Port = $defaultBinding.Port
        SSL = $defaultBinding.Protocol -eq 'https'
    }

    # Create the current site with command splatting
    New-WebSite @newWebSiteParams

    ## Add the remaining bindings
    foreach ($binding in ($site.Bindings | Select-Object -Skip 1)){
        New-WebBinding -Name "$($site.Name)" -Protocol $binding.Protocol -Port $binding.Port
    }
}

Still not sure why Remove-WebBinding appeared to be removing the binding from both sites.

Upvotes: 0

Related Questions