1

I'm trying to import IIS Bindings from a json file into IIS using PowerShell. But whenever I run the following command:

New-IISSiteBinding -Name "IIS Site Name" -BindingInformation *:443:actualwebsite.com -CertificateThumbPrint *actualthumbprint* -CertStoreLocation My -Protocol https

It returns:

New-IISSiteBinding : Web site binding '*:443:actualwebsite.com' already exists.
At line:1 char:1
+ New-IISSiteBinding -Name "IIS Site Name" -BindingInformation *:4 ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-IISSiteBinding], ArgumentException
    + FullyQualifiedErrorId : InvalidArgument,Microsoft.IIS.Powershell.Commands.NewIISSiteBindingCommand

When I do the Remove-IISSiteBinding command it says

WARNING: Web site binding 'https *:443:actualwebsite.com' does not exist.

It also doesn't show up in IIS management console, restarting IIS using iisreset doesn't change anything. When I execute the complete PowerShell script, I get errors returned:

New-IISSiteBinding : Filename: \\?\C:\Windows\system32\inetsrv\config\applicationHost.config Error: Cannot commit configuration changes because the file has changed on disk

The complete PowerShell script:

$backupfilepath = "C:\Backup\IISBindings.json"
$Sites = Get-Content -Raw $backupfilepath | ConvertFrom-Json 
$Sites | ForEach-Object {
$siteName = $_.Site;
$_.Bindings | ForEach-Object {
    $certStoreName = "Cert:\LocalMachine\" + $_.CertificateStoreName;
    $bindingInformation = $_.BindingInformation
    $certificateHash = $_.CertificateHash
  
    if (-not ([string]::IsNullOrEmpty($certificateHash))) {
        if ($null -ne (get-iissitebinding -Name $siteName | Where-Object { $_.bindinginformation -eq $bindingInformation })) {  
            Write-Host "This is a current binding, removing existing"  
            Remove-IISSiteBinding -Name $siteName -Protocol https -BindingInformation $bindingInformation

            Write-Host "Creating a new binding"
            New-IISSiteBinding -Name $siteName -BindingInformation $bindingInformation -CertificateThumbPrint $certificateHash -CertStoreLocation $certStoreName -Protocol https -Force
        }  
        else {  
            Write-Host "This is not a current binding"  
            New-IISSiteBinding -Name $siteName -BindingInformation $bindingInformation -CertificateThumbPrint $certificateHash -CertStoreLocation $certStoreName -Protocol https -Force
        }
    }
    else {
        if ($null -ne (get-iissitebinding -Name $siteName | Where-Object { $_.bindinginformation -eq $bindingInformation })) {  
            Write-Host "This is a current binding, removing existing"  
            Remove-IISSiteBinding -Name $siteName -Protocol http -BindingInformation $bindingInformation
            
            Write-Host "Creating a new binding"
            New-IISSiteBinding -Name $siteName -BindingInformation $bindingInformation -Protocol http -Force
        }  
        else {  
            Write-Host "This is not a current binding"  
            New-IISSiteBinding -Name $siteName -BindingInformation $bindingInformation -Protocol http -Force
        }
    } 
   

}

}

How do I solve this?

  • does `Get-IISSiteBinding` show an existing binding configuration? Also try with `Get/New-WebBinding`, or even the old `appcmd list sites`. The error from `Remove-IISSiteBinding` makes it look like you could have included "https" in `-BindingInformation` instead of with `-Protocol` – Cpt.Whale Jan 26 '23 at 15:29
  • Yes, `Get-IISSiteBinding` returns the binding with protocol `https` and then the binding info behind it. sslFlags is shown as `None`. However, `Get-WebBinding` only returns the port 80 binding information. (which matches the IIS management console) – Koen van der Borght Jan 27 '23 at 14:05
  • I've added the complete powershell script to the post. – Koen van der Borght Jan 27 '23 at 14:20
  • yeah it looks like the applicationHost.config is locked or powershell needs to be refreshed - seems like it can be temperamental: https://stackoverflow.com/a/45337496/7411885. That file is also where the bindings get stored, so you can check it to see what the actual state of things is too – Cpt.Whale Jan 27 '23 at 14:30

1 Answers1

0

Thanks to @Cpt.Whale I found a blogpost from Chris Meagher where he explains that he uses IISServerManager. After switching to this my script is working!

Using the blogpost I could replace my for each loop with the following:

$Sites | ForEach-Object {
$siteName = $_.Site;
$_.Bindings | ForEach-Object {
    $certStoreName = $_.CertificateStoreName;
    $bindingInformation = $_.BindingInformation
    $certificateHash = $_.CertificateHash
    $thumbprintBytes = HexToBytes $certificateHash
    
    $site = $manager.Sites[$siteName]
    if (-not ([string]::IsNullOrEmpty($certificateHash))) {
        $site.Bindings.Add($bindingInformation, $thumbprintBytes, $certificateStoreName, 0) | Out-Null
    } else {
        $site.Bindings.Add($bindingInformation, "http") | Out-Null
    }
}
}

$manager.CommitChanges()