2016-06-29 3 views
1

私はドメインコントローラの検証スクリプトを作成中です。私は確認する必要がある4つのことがあるアカウントを持っています。私が働いているコードは、条件の1つが満たされず、それが今やっていることであれば、それが壊れないようにしたくありません。ですから、条件が満たされているかどうかにかかわらず、基本的に4つの基準すべてをチェックする必要があります。ここでPowershellで中断のない複数の条件を確認する

は私のコードです:

if(net user "user.dadm") { 
    Write-Host "[√] User.dadm was created successfully" -fore GREEN 
    if((((uACADA "user.dadm") -band 65536) -ne 0) -eq $true) { 
     Write-Host "[√] Password for user.dadm is set to never expire" -fore GREEN 
     if((Get-ADGroupMember -Identity "Domain Admins").Name -contains "user.dadm") { 
      Write-Host "[√] User.dadm was added to Domain Admins" -fore GREEN 
      if((((uACADA "user.dadm") -band 1048576) -ne 0) -eq $true) { 
       Write-Host "[√] Account Delegation Authority was removed" -fore GREEN 
       } else { 
        Write-Host "[X] Account Delegation was not removed" -fore RED 
        } 
      } else { 
       Write-Host "[X] User.dadm was not added to Domain Admins" -fore RED 
       } 
     } else { 
      Write-Host "[X] Password for user.dadm has been set to expire" -fore RED 
      } 
    } else { 
     Write-Host "[X] User.adam was not created" -fore RED 
     } 

これは何のいずれかの条件が満たさが、私はそれがそれぞれの条件をチェックし続ける必要がされていない場合には、elseステートメントに壊れるです。

私はこれを分解して各条件を個別にチェックすることができますが、すでに1000行以上になるため、できるだけ圧縮しておくことをお勧めします。

私は4つの別々のIF/ELSEステートメントを作成せずにこれを行うことができるのかどうかは疑問だと思います。

構造化の問題(ネストされたIF)またはコマンドの問題(IFとELSEIFを使用する必要がある場合はIFとELSEを使用するかどうかはわかりません)。

誰かが正しい方向に向けるでしょうか?前もって感謝します。

+1

私の質問があり、うまく以上のテストに拡張う

  • )スペースを追加さらに、私の経験では、ifステートメントの読み込みが非常に難しく、したがって保守が非常に難しくなっています。 –

  • +0

    それを維持するのは自分自身です。 – Rincewind

    +2

    あなたは永遠にそれを維持していますか?あなたが去った後でさえ?それと同時に、スクリプトを読んだ5年後の意味を正確に知ることができるでしょうか?もう一度、私の経験は、2年以上前から私自身のコードを読むことは、他人のコードを読むこととあまり変わらないということです。 –

    答えて

    4

    はテストされていませんが、複数のif文の単純さを選択することもできますが、これが出発点になります。

    $user = 'user.dadm' 
    
    $info = [ordered]@{ 
        created = "[X] $user was not created" 
        neverexp = "[X] Password for $user has been set to expire" 
        admin = "[X] $user was not added to Domain Admins" 
        delegation = "[X] Account Delegation for $user was not removed" 
    } 
    
    switch ($true) { 
        {net user $user} { 
         $info.created = "[√] $user was created successfully" 
        } 
    
        {((uACADA $user) -band 65536) -ne 0} { 
         $info.neverexp = "[√] Password for $user is set to never expire" 
        } 
    
        {(Get-ADGroupMember -Identity 'Domain Admins').Name -contains $user} { 
         $info.admin = "[√] $user was added to Domain Admins" 
        } 
    
        {((uACADA $user) -band 1048576) -ne 0} { 
         $info.delegation = "[√] Account Delegation Authority for $user was removed" 
        } 
    
        default {Write-Host 'all are false'} 
    } 
    
    $info.Keys | % { 
        if ($info.$_.startswith('[X]')) { 
         Write-Host $($info.$_) -ForegroundColor Red 
        } else { 
         Write-Host $($info.$_) -ForegroundColor Green 
        } 
    } 
    
    +1

    うわー。とても素敵で美しく書かれています。申し訳ありませんが、私はよく書かれたユニークなコードに感謝します。私はスプラットのアイデアが好きで、別のスクリプトでそれを使っていましたが、変数をインスタンス化してSWITCH/CASEブロックを使って項目を変更することは考えていませんでした。あなたが気にしないなら、私はこれを使うかもしれないと思います。助けてくれてありがとう!あなたは間違いなく緑の√を獲得しました。 – Rincewind

    +1

    'Write-Host'ではなく' Write-Warning'コマンドレットを使うことをお勧めします。 'Write-Host'は、別のスクリプトによって消費されるような方法で書かれません。例:警告パイプラインに何かが書き込まれているかどうかをテストで確認できます – Eris

    +0

    @Eris別のスクリプトで何かを消費してしまったと思います。 – Rincewind

    3

    はい、ifテストなしで書けます。

    $colors = @('Red', 'Green') 
    $messages = @('[X] Failed -', '[√] Succeeded -') 
    
    $username = "user.adm" 
    
    $result = [bool](net user "$username") 
    Write-Host "$($messages[$result]) Check user account exists" -ForegroundColor $colors[$result] 
    
    $result = [bool]((uACADA "$username") -band 65536) 
    Write-Host "$($messages[$result]) Check password never expires" -ForegroundColor $colors[$result] 
    
    $result = [bool]((Get-ADGroupMember -Identity "Domain Admins").Name -contains "$username") 
    Write-Host "$($messages[$result]) Check account is a domain admin" -ForegroundColor $colors[$result] 
    
    $result = [bool]((uACADA "$username") -band 1048576) 
    Write-Host "$($messages[$result]) Check Delegation Authority removed" -ForegroundColor $colors[$result] 
    

    NB。 if/elseを使用していない場合は、真偽テストを行うには別の方法が必要です。結果を[bool]にキャストし、2要素配列を使用しています。 $array[$false]$false -> 0をキャストし、要素0を取得すると、$array[$true]キャスト$true -> 1が取得され、要素1が取得されます。結果が適切な色とメッセージに変換されます。

    これを書くもう1つの妥当な方法は、Write-Hostsを関数に移動することです。

    Function Report-Result { 
        param($Result, $Text) 
        if ($Result) { 
         Write-Host "Success - $Text" -Fore Green 
        } else { 
         Write-Host "Failure - $text" -Fore Red 
        } 
    } 
    
    $result = [bool](...) 
    report-result $result "Check password never expires" 
    
    ... etc. 
    

    出力は次のようになります。

    okayyyyある

    Screenshot of first example code's output

    - それはダウン〜10までのコードのあなたの20行を取得し、何のネスティングを持っていない、とすべてのテストを実行します。


    しかし、それは本当にあなたがしているように再発明しPowerShellのDSC(「私の望ましい状態が終わりの.admを持つアカウントが自分のパスワードが期限切れにならないように設定されていることである」)またはPester感じている - のPowerShellのテストフレームワークを、 ( "すべての.admアカウントにパスワードが期限切れにならないように設定されていることをテストする")。

    あなたのユースケースにPesterを正確に合わせることができないのかどうかはわかりませんが、スクリプトについてのあらゆることを出力メッセージに変更して、Pesterのように見せたり感じたりすると思います。特に、テスト定義と印刷出力の明確な分離が望まれます。:

    1. Here are my tests, with self-explanatory names 
    2. Here is a loop which runs all tests, and reports on them 
    

    、それは私のような何か与える:私の第二のコードの私の見解は、そのある

    Screenshot of second example code's output

      のような出力を提供します

      Function Validate-DCUserAccountShouldExist { 
          param($Username) [bool](net user "$UserName") 
      } 
      
      Function Validate-DCUserAccountPasswordNeverExpireShouldBeSet { 
          param($Username) [bool]((uACADA "$username") -band 65536) 
      } 
      
      Function Validate-DCUserAccountShouldBeADomainAdmin { 
          param($Username) [bool]((Get-ADGroupMember -Identity "Domain Admins").Name -contains "$username") 
      } 
      
      Function Validate-DCUserAccountShouldHaveDelegationAuthorityRemoved { 
          param($Username) [bool]((uACADA "$Username") -band 1048576) 
      } 
      
      # Search for all Validation functions and run them 
      $tests = (gci function: |Where Name -Like 'Validate-DCUserAccount*').Name 
      
      foreach ($test in $tests) { 
          $result = try { 
            & $test "user.adm" 
           } catch { 
            $false 
           } 
      
          if ($result) { 
           Write-Host -ForegroundColor Green "[√] $test - succeeded" 
          } else { 
           Write-Host -ForegroundColor Red "[X] $test - Failed" 
          } 
      } 
      

    • もう少しですテスト定義の分離と出力
    • 書き込みホストのはるかに少ない重複
    • は、より構造化され従うことにくく、
    • 、より複雑な関数名は状態なりますどの、どうあるべきかを説明します出力メッセージは成功/失敗のために働く
    • 出力メッセージはコードのほうが淡いですが、出力を読むのが醜いです(ただし調整可能です。なぜ4ネストされた場合/ else文未満の圧縮4別々のif/else文を作成している?それらを印刷するときにちょうどより多くのテストを追加することによって、
    +1

    洞察力に感謝します - ここにたくさんの良い情報があります。 –

    +0

    これは素晴らしい答えです!私はPesterやDSCに精通していませんが、これは非常に参考になりました。私は整数値を持つブール値の二重の性質の使用が好きでした。これは発明的なものでした。書き込む関数は、あまりにもずっと前に構築したモジュールの1つに使用したものです(統合時のフットプリントを大幅に削減します)。私はその繰り返しがあるときに関数を使う傾向があります。しかし、私は最後の部分でかなり失われました。私はそれが何をしたのか理解していますが、私はそれが意味することとそれがペスターのようなものに従っていない。 – Rincewind

    +0

    Pesterのようなものではなく、巨大な変更ではありません。コードの焦点を「ここでは英語の2つの結果を説明する2つの文字列で表しています」から、どちらの場合にも意味をなさない名前で合格または不合格のテストが行​​われます(「説明的な文字列はありません」)。私はそれが少しPesterのようだと思うが、私は間違っている可能性がある、私は非常に自分自身でそれを使用していない。 – TessellatingHeckler

    関連する問題