0

I have the following which doesn't allow both variables to be enabled (boolean true value):

If (($Variable1) -and ($Variable2)) {
   Write-Warning "Both variables have been enabled. Modify script to enable just one."
   Pause
   Break
}

This works great, however, how would I ensure only one is ever enabled when 4 possible variables exist? I'm thinking a combination of -and & -or?

jshizzle
  • 467
  • 1
  • 11
  • 23
  • 3
    could you clarify, you are looking for a way to test if only 1 out of 4 variables exist or if only 1 of those are set to true (and it always doesnt matter which one)? – 4c74356b41 Nov 27 '17 at 09:29
  • All variables will exist but only one should be set to true. It won't matter which one as this is a manual choice. – jshizzle Nov 27 '17 at 09:48
  • I guess you referring to an [-xor](https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_logical_operators?view=powershell-5.1), for a truth table (also for [eqv](https://stackoverflow.com/questions/44701074/converting-vbscripts-eqv-operator/44701076#44701076) and [imp](https://stackoverflow.com/questions/44700816/converting-vbscripts-imp-operator/44700817#44700817)), see e.g.: https://stackoverflow.com/q/927119/1701026 (If this doesn't answer it, please consider to show a truth table in your question). – iRon Nov 27 '17 at 09:52
  • 1
    @jshizzle can you clarify whether **only one** or **at least one** should be set to true? – arco444 Nov 27 '17 at 10:07
  • @arco444 as per my comment above, only one should be set to true. – jshizzle Nov 27 '17 at 10:34

2 Answers2

3

You can add the boolean values and check their count:

If (([bool]$Variable1 + [bool]$Variable2 + [bool]$Variable3) -ne 1) {
    ...
}

but of course you have to make sure that these can actually be cast to boolean.

That's what "exclusive or" (xor) is for:

If ($Variable1 -xor $Variable2 -xor $Variable3) {
    ....
}

About logical operators in Powershell

whatever
  • 871
  • 4
  • 11
  • 1
    This looks good although still proceeds when all are set to true, two are true and two are false etc. If two of these are set to true then the script prompts the message but if three are set to true it doesn't.... – jshizzle Nov 27 '17 at 10:49
  • Could you show your code? When I try this it seems to work properly. Oh an what Powershell Version are you using? – whatever Nov 27 '17 at 10:54
  • Blast, I just understood why it doesn't work. In Powershell these operators are left associative. So if `$Variable1 -xor $Variable2` results in `false` (for example because both are `true` and `$Variable3" is `true` this will result in `true`. Either there is a clever way with brackets or this will need a lot more comparisons... – whatever Nov 27 '17 at 11:10
  • Ah great stuff whatever thanks. As it turns out these values are cast to boolean so spot on to what I have here. Only change I had to make was -eq to -gt so anything more than 1 is flagged. – jshizzle Nov 27 '17 at 15:22
  • Glad to help. But if you want to catch every case where not exatcly 1 is set, use `-ne 1` because otherwise all variables set to `$false` would trigger, too. – whatever Nov 27 '17 at 15:27
3

Cannot think of a way to do this that avoids using a counter. You have to check the value of each variable and keep count of how many are $true.

$trueCount = 0
($variable1, $variable2, $variable3, $variable4) | % { if ($_ ) { $trueCount++} } 

if ($trueCount -eq 1) {
  write-host "only one variable true"
}
else {
  write-host "condition not met"
}
arco444
  • 22,002
  • 12
  • 63
  • 67
  • Thanks arco444. This is along the same idea as whatever's above but gave him the answer vote due to simplicity. – jshizzle Nov 27 '17 at 15:27