我正在研究域控制器的验证脚本。我有一个帐户,有4件事我需要验证。我所使用的代码,但如果其中一个条件不满足,我不希望它破坏,这就是它现在正在做的事情。所以,基本上我需要检查所有4个标准,无论条件是否满足。
这是我的代码:
static int cmp_int(const void *ap, const void *bp)
{
const int a = *(const int *) ap, b = *(const int *) bp;
return a < b ? -1 : a > b;
}
static bool in_sprawling_set(int data)
{
static const int values[] = { 125, 500, 750 };
return bsearch(&data, values, sizeof values / sizeof *values, sizeof *values, cmp_int) != 0;
}
如果不满足任何条件,它会破坏else语句,但我需要它继续检查每个条件。
我知道我可以打破这个并单独检查每个条件,但我更喜欢尽可能压缩它,因为它已经超过一千行。
我想真正的问题是,如果可以在不制作4个独立的IF / ELSE语句的情况下完成。
我不确定它是否存在结构问题(嵌套IF)或命令问题(当我应该使用IF和ELSEIF时使用IF和ELSE)。
有人能指出我正确的方向吗?提前谢谢。
答案 0 :(得分: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 :(得分: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.这就是将结果转换为适当颜色和消息的方式。
写这个的另一个合理方法是将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.
输出如下:
哪个是好的 - 它将你的20行代码降低到~10,并且没有嵌套,并运行所有测试。
但是真的感觉你正在重新发明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
这给了我类似的东西:
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"
}
}
其中输出如下:
我对第二个代码的看法是: