我正在使用PowerShell编写一些自动脚本来在服务器上创建/更新IIS站点。
目标是拥有一个配置对象,然后可以通过一个脚本来处理所有繁重的工作。
我的配置HashTable
如下所示:
$config = @{
AppPools = (
@{
Name="AppPool1"
Properties = @{
Enable32BitAppOnWin64=$true
ManagedRuntimeVersion="v4.0"
ProcessModel = @{
IdentityType = "NetworkService"
}
}
}
)
Websites = (
@{
Name="Site1"
Properties = @{
PhysicalPath = "C:\sites\site1"
ApplicationPool = "AppPool1"
}
}
)
}
我的脚本然后使用配置来处理每个应用程序池和网站:
Import-Module WebAdministration
$config.AppPools |
% {
$poolPath = "IIS:\AppPools\$($_.Name)"
# Create if not exists
if(-not(Test-Path $poolPath)){ New-WebAppPool $_.Name }
# Update the properties from the config
$pool = Get-Item $poolPath
Set-PropertiesFromHash $pool $_.Properties
$pool | Set-Item
}
$config.Websites |
%{
$sitePath = "IIS:\Sites\$($_.Name)"
# Create if not exists
if(-not(Test-Path $sitePath)){ New-WebSite $_.Name -HostHeader $_.Name }
# Update the properties from the config
$site = Get-Item $sitePath
Set-PropertiesFromHash $site $_.Properties
$site | Set-Item
}
正如您所看到的,该过程实际上是相同的(除了项目路径和正在创建的类型)。如果我开始工作,这当然会被重构!
我写了一个名为Set-PropertiesFromHash
的函数。这基本上将哈希表展平为属性路径:
Function Set-PropertiesFromHash{
Param(
[Parameter(Mandatory=$true, HelpMessage="The object to set properties on")]
$on,
[Parameter(Mandatory=$true, HelpMessage="The HashTable of properties")]
[HashTable]$properties,
[Parameter(HelpMessage="The property path built up")]
$path
)
foreach($key in $properties.Keys){
if($properties.$key -is [HashTable]){
Set-PropertiesFromHash $on $properties.$key ($path,$key -join '.')
} else {
& ([scriptblock]::Create( "`$on$path.$key = `$properties.$key"))
}
}
}
scriptblock
子句中创建的else
将导致执行$on.ProcessModel.IdentityType = $properties.IdentityType
(每个循环中的属性对象是最后找到的HashTable值,因此这会分配正确的值)
还在吗?谢谢!
以上所有内容与应用程序池的预期效果相同,但对网站完全失败。 为什么仅针对网站失败?
我知道我可以使用Set-ItemProperty
,但这里的目的是允许配置对象驱动正在设置的属性。
下面详细介绍一个更简单的例子:
# Setting an app pool property this way works as expected
$ap = gi IIS:\apppools\apppool1
$ap.enable32BitAppOnWin64 # returns False
$ap.enable32BitAppOnWin64 = $true
$ap | Set-Item
$ap = gi IIS:\apppools\apppool1
$ap.enable32BitAppOnWin64 # returns True
# Setting a website property this way fails silently
$site = gi IIS:\sites\site1
$site.physicalpath # returns "C:\sites\site1"
$site.physicalpath = "C:\sites\anothersite"
$site | Set-Item
$site = gi IIS:\sites\site1
$site.physicalpath # returns "C:\sites\site1"
调用Set-Item
后再次检索项目$ap
具有更新后的值,但$site
不包含更新后的值。
我正在使用PowerShell v2和IIS7
我已将Set-PropertiesFromHash
更改为如下工作:
Function Set-PropertiesFromHash{
Param(
[Parameter(Mandatory=$true, HelpMessage="The object to set properties on")]
$on,
[Parameter(Mandatory=$true, HelpMessage="The HashTable of properties")]
[HashTable]$properties,
[Parameter(HelpMessage="The property path built up")]
$pathParts = @()
)
foreach($key in $properties.Keys){
if($properties.$key -is [HashTable]){
Set-PropertiesFromHash $on $properties.$key ($pathParts + $key)
} else {
$path = ($pathParts + $key) -join "."
Set-ItemProperty $on $path $properties.$key
}
}
}
这让我现在继续。但是我原来的问题仍然存在。
为什么$site | Set-Item
网站失败?
答案 0 :(得分:1)
这似乎有效
(gi IIS:\sites\site1).physicalpath
(gi IIS:\sites\site1).physicalpath = "C:\sites\anothersite"
(gi IIS:\sites\site1).physicalpath