0

私は Microsoft System Center Configuration Manager の管理者です。私は、Win7 と XP の組み合わせで構成される約 4,000 台の Windows ワークステーションを管理しています。私は、これらのワークステーションでソフトウェアの更新を維持し、定期的にソフトウェアを展開する責任があります。

残念ながら、これらのクライアントの構成には実際の標準セットが存在しないため、ソフトウェアを 1 つのインスタンスにプッシュできないという問題が発生した場合、通常は 1 つのインスタンスになります。これらのワークステーションを常に手動で修正することにうんざりしていたので、すべての小さな問題を修正するモンスター Powershell スクリプトを作成することにしました。

現在、スクリプトは中央の場所から実行され、これらすべてのワークステーションに同期的にヒットします (Powershell ジョブが来ています)。この一連の機能とロジックは制御不能になっています。私は、それを管理不能にしている別の問題を見つけるたびに、それに追加し続けています.

まず、問題に名前を付けます。たとえば、「壊れた WMI」としましょう。次に、Test-BrokenWmi、Get-BrokenWmi、Fix-BrokenWmi 関数などを作成します。これらの関数は、私が持っているモジュールの 1 つに入り、メイン スクリプトから呼び出されます。

メイン スクリプトには、渡されたパラメーターに応じて、問題のみを検出するか、問題を修正するオプションがあります。ここにスニペットがあります。これらのチェックを簡単に追加できるように、これを行うより良い方法はありますか? さらに困難なことに、一部のチェックには依存関係があり、実際に機能していなければ 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;
          }
     }
}

}

4

1 に答える 1

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"

これは、オブジェクトにメンバーを追加するよりもはるかに簡単です。

次に、オブジェクト全体をパイプラインに渡します。

依存関係があるテストの場合、ハッシュ テーブルに依存関係のキーと "Passed" の値があるかどうかを確認します。

最後にハッシュ テーブルをオブジェクトに変換するために使用する関数を作成して、書式設定やエクスポートに使いやすいものを用意します。繰り返しますが、V3 では次のことができます。

new-object -property $oPc

順序付きハッシュテーブルで動作します。結果のオブジェクトでテストが実行された順序のままになるように、順序付けられたハッシュ テーブルを使用する必要があります。

次に、テスト スタックは次のようになります。

'Computer1' | New-Test | 
 Test-BrokenWmi | Get-BrokenWmi | Fix-BrokenWmi |
 Test-ServiceNotStarted | TestServiceStart |
 | New-TestResult
于 2012-03-21T23:39:04.203 に答える