0

I'm writing a PowerShell script to set up several websites on developers' machines in IIS (not IIS Express).

I understand that the current recommendation (as at 2025) is to create IIS websites using the IISAdministration module, rather than the old WebAdministration module, and Microsoft.Web.Administration.ServerManager via the Get-ServerManager cmdlet.

There are several overloads of ServerManager.Sites.Add(). I would prefer to use one of the overloads which doesn't include certificate information, so I can reuse the code to set up multiple sites, some of which do not have HTTPS bindings. I would like to add the certificate information as a separate optional step for those sites which do have HTTPS bindings.

However, I find that if I do add certificate information to a binding after the site is added, when I call ServerManager.CommitChanges() the certificate information disappears.

Is there any way to add a site as a two step process via ServerManager, adding the site first, then the certificate information to the binding if required?

Here is my proof of concept code:

#Requires -RunAsAdministrator
#Requires -Version 5.1
#Requires -Modules @{ ModuleName='IISAdministration'; ModuleVersion='1.1.0.0' }

$physicalPath = 'C:\Working\Test'
$websiteName = 'Test'
# ASSUMPTION: App pool already exists.
$appPoolName = 'Test'
$bindingInfo = @{ Protocol = 'https'; BindingInformation = '*:4000:' }
[byte[]]$certificateHash = 204,219,71,236,31,111,36,12,228,97,184,227,116,172,225,48,123,184,38,197
$certificateInfo = @{ 
    Name = 'IIS Express Development Certificate'
    StoreName = 'My'
    Hash = $certificateHash
    Thumbprint = 'CCDB47EC1F6F240CE461B8E374ACE1307BB826C5'
}

$addCertificateWithSite = $true

$iisServerManager = Get-IISServerManager

if ($addCertificateWithSite) 
{
    # Works.
    $webSite = $iisServerManager.Sites.Add(
        $websiteName, 
        $bindingInfo.BindingInformation, 
        $physicalPath,
        $certificateInfo.Hash,
        $certificateInfo.StoreName)
}
else
{
    # Doesn't work.
    $webSite = $iisServerManager.Sites.Add(
        $websiteName, 
        $bindingInfo.Protocol, 
        $bindingInfo.BindingInformation, 
        $physicalPath)

    $configuredBinding = $webSite.Bindings[0]
    $configuredBinding.CertificateHash = $certificateInfo.Hash
    $configuredBinding.CertificateStoreName = $certificateInfo.StoreName
}

$rootWebApp = $website.Applications['/']
$rootWebApp.ApplicationPoolName = $appPoolName

$iisServerManager.CommitChanges()

Write-Host 'End'

If I supply the certificate information in the Sites.Add(...) method the certificate is set up correctly. See the above code when $addCertificateWithSite = $true. However, if I add the certificate information after the site is added, the certificate information disappears when $iisServerManager.CommitChanges() is called. See the above code when $addCertificateWithSite = $false.

When $addCertificateWithSite = $false here is the binding information before CommitChanges() is called:

enter image description here

And here is the binding information after CommitChanges() is called:

enter image description here

1
  • When using HTTPS (secure) you need to have the certificate loaded on both client and server for the connection to complete. So what certificate do you plan to use to make the connection? You can't add a server without making a connection and you can't connect with HTTPS without a common certificate on both the client and server. Commented Aug 6 at 12:16

2 Answers 2

1

The API/cmdlets were designed along with IIS Manager, so you should use it in the same way as you use IIS Manager to create sites.

That is, when creating a site, you must start with either an HTTP binding, or an HTTPS binding. You can add or update bindings after creation. The sample code from the other answer shows the exact approach.

Sign up to request clarification or add additional context in comments.

1 Comment

While Doug Maurer's script works I'd prefer not to have to use the WebAdministration module in addition to the IISAdministration module. Eventually I figured out I could call ServerManager.CommitChanges() then Remove-IISSiteBinding before calling New-IISSiteBinding to recreate the HTTPS binding with certificate details. This seemed like a long-winded hack, though. So I'll follow your advise and create the site from the start with either an HTTP binding or an HTTPS binding which includes the certificate information.
1

You could simply commit the changes and then add the binding afterwards

$physicalPath = 'C:\Working\Test'
$websiteName = 'Test'
# ASSUMPTION: App pool already exists.
$appPoolName = 'Test'
$bindingInfo = @{ Protocol = 'https'; BindingInformation = '*:4000:' }
[byte[]]$certificateHash = 204,219,71,236,31,111,36,12,228,97,184,227,116,172,225,48,123,184,38,197
$certificateInfo = @{ 
    Name = 'IIS Express Development Certificate'
    StoreName = 'My'
    Hash = $certificateHash
    Thumbprint = 'CCDB47EC1F6F240CE461B8E374ACE1307BB826C5'
}

$addCertificateWithSite = $true

$iisServerManager = Get-IISServerManager

if ($addCertificateWithSite) 
{
    # Works.
    $webSite = $iisServerManager.Sites.Add(
        $websiteName, 
        $bindingInfo.BindingInformation, 
        $physicalPath,
        $certificateInfo.Hash,
        $certificateInfo.StoreName)
}
else
{
    $webSite = $iisServerManager.Sites.Add(
        $websiteName, 
        $bindingInfo.Protocol, 
        $bindingInfo.BindingInformation, 
        $physicalPath
    )

    $rootWebApp = $website.Applications['/']
    $rootWebApp.ApplicationPoolName = $appPoolName

    $iisServerManager.CommitChanges()

    $binding =  $website | Get-WebBinding -Protocol 'https'
    $binding.AddSslCertificate($certificateInfo.Thumbprint, $certificateInfo.StoreName)
}

Write-Host 'End'

1 Comment

Thanks. It looks from your modified code we'd need to use the WebAdministration module as well as the IISAdministration module. Is that correct?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.