2012-03-21 97 views
0

我是Microsoft系統中心配置管理器管理員。我管理大約4,000個由Win7和XP組合組成的Windows工作站。我負責在這些工作站上保留軟件更新並定期進行軟件部署。Powershell腳本流程所需的建議

不幸的是,對於這些客戶端的配置沒有真正的標準設置,因此當彈出的問題阻止我將軟件推送到某個客戶端時,它通常是單個實例。我厭倦了所有時間手動修復這些工作站,所以我決定創建一個怪獸Powershell腳本來解決所有的小問題。

目前,腳本從中央位置運行並同步點擊所有這些工作站(Powershell作業即將到來)。這套功能和邏輯正在失去控制。每當我發現另一個讓它變得難以管理的問題時,我就不斷加入它。

首先,我說出一個問題,讓我們說「破碎的WMI」。然後,我創建一個Test-BrokenWmi,Get-BrokenWmi和Fix-BrokenWmi函數。這些函數進入我有的一個模塊,並從主腳本中調用。

然後,主腳本可以選擇僅查找問題或根據傳遞給它的參數來修復問題。這是一個片段。有沒有更好的方法來做到這一點,所以我可以輕鬆地添加這些檢查?爲了使事情變得更加困難,一些檢查具有依賴性,例如,除非WMI實際工作,否則無法從WMI獲取任何內容。

param($ComputerName,[bool]$Remediate) 

Write-Debug 'Starting script...' 
$oPc = New-Object System.Object; 
$oPc | Add-Member -Type NoteProperty -Name Name -Value $ComputerName; 

try { 
    if (!(Test-BrokenWmi $ComputerName)) { 
     throw 'WMI is broken'; 
    } elseif (!(Test-ServiceNotStarted $ComputerName)) { 
     throw 'Service not started'; 
    } elseif (............) { 
     .....continue more elseifs 
    ## Client looks to be OK since it didn't catch any health checks 
    } else { 
     $oPc | Add-Member -Type NoteProperty -Name TestResult -Value 'Healthy'; 
     $oPc | Add-Member -Type NoteProperty -Name RemediationAttempt -Value 'N/A'; 
    $oPc | Add-Member -Type NoteProperty -Name RemediationResult -Value 'N/A'; 
    return $oPc 
    } 
} catch [system.exception] { 
    $problemfound = $_.Exception.Message; 
    $oPc | Add-Member -type NoteProperty -Name TestResult -Value $problemfound; 
    if (!$Remediate) { 
     $oPc | Add-Member -Type NoteProperty -Name RemediationAttempt -Value 'TestOnlyMode'; 
    $oPc | Add-Member -Type NoteProperty -Name RemediationResult -Value 'TestOnlyMode'; 
    return $oPc; 
    } else { 
     try { 
      switch ($problemfound) { 
        'WMI is broken' { 
         $oPc | Add-Member -Type NoteProperty -Name RemediationAttempt -Value 'Fix WMI'; 
         throw Fix-Wmi $ComputerName 
        } 'Service is stopped' { 
         $oPc | Add-Member -Type NoteProperty -Name RemediationAttempt -Value 'Start service'; 
         throw Fix-Service $ComputerName 
        } 
       } 
      } catch [system.exception] { 
       if ($_.Exception.Message -eq $false) { 
        $oPc | Add-Member -Type NoteProperty -Name RemediationResult -Value 'Failed'; 
       } elseif ($_.Exception.Message -eq $true) { 
      $oPc | Add-Member -Type NoteProperty -Name RemediationResult -Value 'Succeeded'; 
     } else { 
     $oPc | Add-Member -Type NoteProperty -Name RemediationResult -Value $_.Exception.Message; 
     }##endif 
     return $oPc; 
      } 
    } 
} 

}

回答

1

這裏是我拿,FWIW。首先,將該對象交換爲有序散列表直到結束。

function new-test {($computername) 
$oPc = new-object collections.specialized.ordereddictionary 
$oPc.computername = $computername 
} 

這是V2版本。在V3,你就可以做

$opc = [ordered]@{} 
$oPc.computername = $computername 

然後改變你的功能,採取從管道。在每次測試中,已經將它添加它的名字,以表與結果一起:

$oPc.TestBrokeWMI = "Fail" 

這比做一個附加成員爲對象容易得多。

然後將整個對象傳遞給管道。

對於具有依賴性的測試,請檢查哈希表是否具有依賴項的鍵和值「通過」。

創建一個函數在最後使用將哈希錶轉換爲一個對象,以便您可以使用格式或導出的東西。再次,在V3中,您將可以做到

new-object -property $oPc 

它將與有序的哈希表一起工作。您需要使用有序的哈希表,以便測試保持其在結果對象中的運行順序。

然後測試堆棧開始是這樣的:

'Computer1' | New-Test | 
Test-BrokenWmi | Get-BrokenWmi | Fix-BrokenWmi | 
Test-ServiceNotStarted | TestServiceStart | 
| New-TestResult 
+0

我很喜歡你使用管道這樣的想法。我一定會看看我能不能做那樣的事情。 – 2012-03-22 13:43:44

+0

很酷。讓我知道它是如何運作的。 – mjolinor 2012-03-22 13:47:20

+0

它花了我一段時間,我做了一些其他的變化,但幾個小時後,我能夠改變所有的功能。我打算明天讓它試運行。 – 2012-03-23 00:09:48