Powershell脚本流程所需的建议

时间:2012-03-21 21:24:21

标签: powershell sccm

我是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;
          }
     }
}

}

1 个答案:

答案 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