I'm in the process of writing some automated scripts to create/update IIS sites on a server using PowerShell.
The aim is to have a configuration object that can then be handled by a single script to do all the heavy lifting.
My config HashTable
looks like this:
$config = @{
AppPools = (
@{
Name="AppPool1"
Properties = @{
Enable32BitAppOnWin64=$true
ManagedRuntimeVersion="v4.0"
ProcessModel = @{
IdentityType = "NetworkService"
}
}
}
)
Websites = (
@{
Name="Site1"
Properties = @{
PhysicalPath = "C:\sites\site1"
ApplicationPool = "AppPool1"
}
}
)
}
My script then uses the config to process each application pool and web site:
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
}
As you can see the process is virtually identical (apart from the item paths and type being created). This will of course be refactored if I get things working!
I've written a function called Set-PropertiesFromHash
. This basically flattens the hash table to a property path:
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"))
}
}
}
The created scriptblock
in the else
clause will result in the execution of $on.ProcessModel.IdentityType = $properties.IdentityType
(the properties object in each loop is the last found HashTable value so this does assign the correct value)
Still here? Thanks!
All of the above works just as expected for application pools but fails completely for websites. Why is this failing only for websites?
I know I can use Set-ItemProperty
but the aim here is to allow the config object to drive the properties that are being set.
A simpler example is detailed below:
# 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"
After Set-Item
is called and then the items are retrieved again $ap
has the updated value but $site
does not contain the updated value.
I'm using PowerShell v2 and IIS7
I've changed Set-PropertiesFromHash
to work as follows:
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
}
}
}
Which has allowed me to continue for now. However my original question still stands.
Why does $site | Set-Item
fail for sites?
This seems to work
(gi IIS:\sites\site1).physicalpath
(gi IIS:\sites\site1).physicalpath = "C:\sites\anothersite"
(gi IIS:\sites\site1).physicalpath
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With