2012-10-26 48 views
8

我正在編寫一些自動化腳本以使用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"))    
     } 
    } 
} 

else子句將導致$on.ProcessModel.IdentityType = $properties.IdentityType執行(屬性在每個循環中的對象創建的scriptblock是最後發現的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

代替'設置Item',你嘗試'設置ItemProperty'的?我知道這並不能解釋這種不一致,但它可能會幫助你解除封鎖。 – latkin

+0

謝謝,是的,我現在用'Set-ItemProperty'實現了它。我承認我認爲這不會讓我用點符號來表示屬性,但會考慮它。我假設它與底層提供商有關,並希望在v3中進行測試以查看事情是否發生了變化 – Kieranties

+1

感謝@latkin,這讓我再次看到了這個問題(爲什麼我在嘗試之前不嘗試點符號不知道...)。 我已經更新了我的工作細節,但原始問題仍然是 – Kieranties

回答

1

這似乎是工作

(gi IIS:\sites\site1).physicalpath 
(gi IIS:\sites\site1).physicalpath = "C:\sites\anothersite" 
(gi IIS:\sites\site1).physicalpath 
+0

使用Powershell V3.0 –