我们正在使用Windows 2012 Server R2。
我们正在尝试自动创建LetsEncrypt证书。我们正在使用LetsEncrypt-Win-Simple(https://github.com/Lone-Coder/letsencrypt-win-simple)。
一旦创建了证书(通过LetsEncrypt.exe),我们就会调用一个.bat脚本(使用--script和--scriptparameters标志)。这将运行powershell.exe并尝试创建必要的IIS绑定。 .bat文件中的行是:
powershell.exe -file c:\temp\SSLIISBinding.ps1 %1 %2 %3 %4
%1-4是LetsEncrypt传入的args。在powershell脚本中,我们尝试运行的命令是:
$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
args传入.bat罚款,因为我们输出它们并且它们正确显示。
如果我们自己运行.bat文件,它会完美运行。如果它被LetsEncrypt.exe调用则失败,报告以下问题:
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
我用Google搜索过,有些人提到了32位与64位PowerShell的内容,但我尝试使用所有不同的powershell.exe。
任何人遇到此问题,或知道要解决。
如果我们直接从命令行调用.bat它可以正常工作,就像通过LetsEncrypt.exe调用一样。许可问题? powershell.exe错在?
答案 0 :(得分:10)
你的问题的一部分:
我用Google搜索,有些人提到了32位与64位PowerShell的相关内容
已经是答案的一半了。如果PowerShell进程的位数与操作系统的位数不匹配,则某些命令无法正常运行。因此,您需要运行位于此powershell.exe
目录中的%windir%\System32\WindowsPowerShell\v1.0\
。但是this documentation topic中描述了一个小问题:
在大多数情况下,只要32位应用程序尝试访问%windir%\ System32,就会将访问权限重定向到%windir%\ SysWOW64。
因此,如果64位操作系统上的32位程序调用{{1}},它实际上将从此处%windir%\System32\WindowsPowerShell\v1.0\powershell.exe
而不是64位调用PowerShell的32位版本。要从32位应用程序实际调用64位PowerShell,您需要使用此技巧:
32位应用程序可以通过将%windir%\ Sysnative替换为%windir%\ System32来访问本机系统目录。 WOW64将Sysnative识别为一个特殊别名,用于指示文件系统不应重定向访问。
答案 1 :(得分:0)
运行以下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
原因是因为我在Windows 10 x64计算机上使用Windows PowerShell(x86)来运行它。
当我尝试相同的操作但使用Windows PowerShell(64位版本)时,效果很好。
答案 2 :(得分:0)
我认为您的$ guid是问题。 GUID必须是将证书绑定到的程序的GUID。对于您的示例,端口443仅绑定到随机GUID,而不绑定到程序的GUID。 IIS和其他应用程序具有您要使用的静态GUID。如果Powershell脚本的GUID,则Get-host是执行代码的Powershell主机,因此这就是您需要的GUID。对于每个Powershell会话,它都会更改,并且netsh绑定也需要更改。
$ appid =“ appid = {” +(get-host).InstanceId.guid +“}”
$ certhash = ls证书:\ LocalMachine \ my |其中{$ .EnhancedKeyUsageList-匹配'Server'-和$ .subject -match(hostname)} |排序对象$ _。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
调用表达式$ cmdline
答案 3 :(得分:0)
谷歌搜索“无法获取cmdlet的动态参数”将我带到这里,但是我的问题是从命令行使用Powershell,答案是在命令中转义双引号 ...
答案 4 :(得分:0)
我也遇到了同样的错误。当我尝试同时使用来自不同代理计算机的Invoke-Command远程将WebBinding添加到IIS站点时,会发生这种情况。
这对我有用,也许对某人也有帮助:
$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()