PowerShell を使用してサーバー上で IIS サイトを作成/更新するための自動化されたスクリプトを作成中です。
目的は、構成オブジェクトを 1 つのスクリプトで処理してすべての面倒な作業を実行できるようにすることです。
私の設定HashTable
は次のようになります:
$config = @{
AppPools = (
@{
Name="AppPool1"
Properties = @{
Enable32BitAppOnWin64=$true
ManagedRuntimeVersion="v4.0"
ProcessModel = @{
IdentityType = "NetworkService"
}
}
}
)
Websites = (
@{
Name="Site1"
Properties = @{
PhysicalPath = "C:\sites\site1"
ApplicationPool = "AppPool1"
}
}
)
}
次に、スクリプトは構成を使用して、各アプリケーション プールと Web サイトを処理します。
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
れた結果は実行されます(各ループのプロパティオブジェクトは最後に見つかった HashTable 値であるため、これにより正しい値が割り当てられます)else
$on.ProcessModel.IdentityType = $properties.IdentityType
質問
まだここ?ありがとう!
上記のすべては、アプリケーション プールでは期待どおりに機能しますが、Web サイトでは完全に失敗します。これが Web サイトでのみ失敗するのはなぜですか?
使用できることはわかっています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"
AfterSet-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
がサイトで失敗するのはなぜですか?