New-WebBinding: Cannot retrieve the dynamic parameters for the cmdlet

12

We're using Windows 2012 Server R2.

We're trying to automate the creation of LetsEncrypt certificates. We're using LetsEncrypt-Win-Simple (https://github.com/Lone-Coder/letsencrypt-win-simple).

Once the cert is created (via LetsEncrypt.exe) we have a .bat script that gets called (using the --script and --scriptparameters flags). This runs powershell.exe and tries to create the necessary IIS binding. The line in the .bat file is:

powershell.exe -file c:\temp\SSLIISBinding.ps1 %1 %2 %3 %4

The %1-4 are args passed in by LetsEncrypt. In the powershell script, the command we're trying to run is:

$iis_host_name = $args[0]
$iis_site_name = $args[1]
$certificate_hash = $args[2]
$certificate_store = $args[3]

"IIS Host Name: " + $iis_host_name
"IIS Site Name: " + $iis_site_name
"Certificate Hash: " + $certificate_hash
"Certificate Store: " + $certificate_store

$guid = [guid]::NewGuid().ToString("B")
netsh http add sslcert hostnameport="${iis_host_name}:443" certhash=$certificate_hash certstorename=$certificate_store appid="$guid"
New-WebBinding -name $iis_site_name -Protocol https  -HostHeader $iis_host_name -Port 443 -SslFlags 1

The args are passed into the .bat fine, as we output them and they are showing correctly.

If we run the .bat file on its own, it works perfectly. If it gets called by LetsEncrypt.exe it fails, reporting the following issue:

New-WebBinding : Cannot retrieve the dynamic parameters for the cmdlet.
Retrieving the COM class factory for component with CLSID
{688EEEE5-6A7E-422F-B2E1-6AF00DC944A6} failed due to the following error:
80040154 Class not registered (Exception from HRESULT: 0x80040154
(REGDB_E_CLASSNOTREG)).
At C:\temp\SSLIISBinding.ps1:13 char:1
+ New-WebBinding -name $iis_site_name -Protocol https  -HostHeader
$iis_host_name  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
    + CategoryInfo          : InvalidArgument: (:) [New-WebBinding], Parameter
   BindingException
    + FullyQualifiedErrorId : GetDynamicParametersException,Microsoft.IIs.Powe
   rShell.Provider.NewWebBindingCommand

I've googled, some mentioning something about 32bit vs 64bit powershell, but I've tried using all the different powershell.exe available.

Anyone hit this issue, or know to resolve.

If we call .bat directly from command line it works fine, just as part of being called via LetsEncrypt.exe. A permission problem? Wrong powershell.exe?

windows
powershell
batch-file
iis-8
lets-encrypt
asked on Stack Overflow Oct 13, 2016 by Dave Quested • edited Oct 16, 2016 by mklement0

5 Answers

17

That part of your question:

I've googled, some mentioning something about 32bit vs 64bit powershell

is already half of an answer. Some commands do not run properly if bitness of PowerShell process does not match bitness of operation system. So, you need to run powershell.exe, which located in this %windir%\System32\WindowsPowerShell\v1.0\ directory. But there is a little problem described in this documentation topic:

In most cases, whenever a 32-bit application attempts to access %windir%\System32, the access is redirected to %windir%\SysWOW64.

Thus, if 32-bit program on 64-bit OS invoke %windir%\System32\WindowsPowerShell\v1.0\powershell.exe, it will actually invoke 32-bit version of PowerShell from here %windir%\SysWOW64\WindowsPowerShell\v1.0\ instead of 64-bit one. To actually invoke 64-bit PowerShell from 32-bit application you need to use this trick:

32-bit applications can access the native system directory by substituting %windir%\Sysnative for %windir%\System32. WOW64 recognizes Sysnative as a special alias used to indicate that the file system should not redirect the access.

answered on Stack Overflow Oct 16, 2016 by user4003407
0

I've got the same error when running the following cmdlet:

PS> Remove-WebAppPool -Name 'Test'

Remove-WebAppPool : Cannot retrieve the dynamic parameters for the cmdlet. Retrieving the COM class factory for
component with CLSID {688EEEE5-6A7E-422F-B2E1-6AF00DC944A6} failed due to the following error: 80040154 Class not
registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).
At line:1 char:1
+ Remove-WebAppPool -Name 'Test'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Remove-WebAppPool], ParameterBindingException
    + FullyQualifiedErrorId : GetDynamicParametersException,Microsoft.IIs.PowerShell.Provider.RemoveAppPoolCommand

The reason was because I ran it using Windows PowerShell (x86) on my Windows 10 x64 machine.

When I tried the same but using Windows PowerShell, which is 64 bit version, it worked just fine.

answered on Stack Overflow Jun 27, 2019 by Oleg Burov
0

I think your $guid is the issue. The GUID needs to be the GUID of the program to bind the cert to. For your example port 443 is only bound to a random GUID, and not your program's GUID. IIS and other apps have a static GUID that you will want to use. If the GUID for a powershell script then Get-host is the powershell host executing code so that's the GUID you need. It changes for every powershell session and the netsh binding needs to as well.

$appid = "appid={"+(get-host).InstanceId.guid+"}"

$certhash = ls Cert:\LocalMachine\my | where {$.EnhancedKeyUsageList -Match 'Server' -and $.subject -match (hostname)}|sort-object $_.NotAfter|select -expand Thumbprint -last 1

$cmdline='netsh http add sslcert ipport=0.0.0.0:443 certhash=' + $certhash + ' "' + $appid + '"'

netsh http delete sslcert ipport=0.0.0.0:443

Invoke-Expression $cmdline

answered on Stack Overflow Jun 27, 2019 by Kirt Carson
0

A google search for "Cannot retrieve the dynamic parameters for the cmdlet" brought me here but my issue was using powershell from the command line, and the answer was to escape the double quotes on the command...

answered on Stack Overflow Apr 2, 2020 by Gerardo Grignoli
0

I've got a problem with the same error. This happens when i'm trying to Add-WebBinding to my IIS site remotely, using Invoke-Command from different agent machines at time.

It's worked for me, maybe it helps someone too:

$Mutex = New-Object -TypeName System.Threading.Mutex($false, "Global\Mutex")    
if ($Mutex.WaitOne(300000)) {
   #For example
   #$Command = {
        #New-WebBinding -name $iis_site_name -Protocol https -HostHeader             
           #$iis_host_name -Port 443 -SslFlags 1
   #}
   #Invoke-Command -Command $Command
} else {
   Write-Warning "Timed out acquiring mutex!"
}
    
$Mutex.Dispose()
answered on Stack Overflow Aug 5, 2020 by aggrosparrow • edited Aug 5, 2020 by aggrosparrow

User contributions licensed under CC BY-SA 3.0