我是Microsoft System Center Configuration Manager管理员。我管理着大约4,000个Windows工作站,包括Win7和XP的组合。我负责在这些工作站上保留软件更新并定期进行软件部署。
不幸的是,对于这些客户端的配置没有真正的标准设置,因此当弹出的问题阻止我将软件推送到一个客户端时,它通常是单个实例。我厌倦了一直手动修复这些工作站,所以我决定创建一个怪兽Powershell脚本来修复所有小问题。
目前,该脚本从一个中心位置运行,并同步访问所有这些工作站(Powershell作业即将到来)。这套功能和逻辑正在失去控制。每当我发现另一个让它变得无法管理的问题时,我就会不断添加它。
首先,我说出一个问题,让我们说“破WMI”。然后,我创建了一个Test-BrokenWmi,Get-BrokenWmi和Fix-BrokenWmi函数。这些函数进入我拥有的一个模块,并从主脚本调用。
然后主脚本可以选择只根据传递给它的参数找到问题或解决问题。这是一个片段。有没有更好的方法来做到这一点,所以我可以轻松添加这些检查?为了使事情变得更加困难,一些检查具有依赖性,例如除非它实际工作,否则你无法从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;
}
}
}
}
答案 0 :(得分: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