2

I'm struggling to have two conditions met, somehow it seems only one of them works. I'm trying to do :

If a user is connected AND NOT at the lock screen, ask for permission. The commands themselves have been verified and work individually but I must be missing something. Here is what i have:

if (Get-WmiObject –ComputerName $poste –Class Win32_ComputerSystem | Select-Object -expandproperty UserName -and -not (get-process -ComputerName $poste -name logonui)) {

"ask for permission"

}

Right now it just doesn't go in this code, it skips to the lower part where something else is happening.

What is wrong with my syntax ?

I can work around it and make it work this old fashioned way from my CMD days:

Clear-Variable -name statut_user
$statut_user -eq 0
if (Get-WmiObject –ComputerName $poste –Class Win32_ComputerSystem | Select-Object -expandproperty UserName) {$statut_user +=1}
if (-not (get-process -ComputerName $poste -name logonui)) {$statut_user += 1}


if ($statut_user -eq 2)  { 
"ask for permission"
}

It works, but not as clean as a proper one liner with the two conditions. Thank you for your help!

ANSWER EDIT: Thanks to vonPryz's answer below i ended up using :

$utilisateur = Get-WmiObject –ComputerName $poste –Class Win32_ComputerSystem | Select-Object -expandproperty UserName
$ecran_verr = get-process -ComputerName $poste -name logonui

if( -not ($ecran_verr) -and ($utilisateur)) { 

"ask for permission"

}
3
  • 2
    When I'm working with complex if statements, I always work out what the simple conditions are, parenthesize them, and then join them with -and or -or, and/or prefix them with -not or !. Then, and only then, do I wrap it with if(...). Have you tried that technique? You might find your own error if you do. Commented Feb 27, 2018 at 13:03
  • Good tip let me try it out ;) Would take make more sense? : if ( (Get-WmiObject –ComputerName $poste –Class Win32_ComputerSystem | Select-Object -expandproperty UserName) -and (-not (get-process -ComputerName $poste -name logonui)) ) { Commented Feb 27, 2018 at 13:04
  • Still not working Commented Feb 27, 2018 at 13:20

2 Answers 2

3

Aim for clarity, not small codebase size. Instead of making WMI calls in the if statement and piping the results, consider something more readable. Like so,

$cs = gwmi -computername $p Win32_ComputerSystem
$uname = $cs | select-object -expandproperty UserName
$logonui = get-process -ComputerName $p -name logonui

if( -not ($logonui) -and ($uname )) { 
  # Stuff
}

This approach makes it easy to check that the WMI objects contain sensible values, whatever those may be. Then it should be easier to write a concise conditional statement.

Sign up to request clarification or add additional context in comments.

1 Comment

Ended up using : $utilisateur = Get-WmiObject –ComputerName $poste –Class Win32_ComputerSystem | Select-Object -expandproperty UserName $ecran_verr = get-process -ComputerName $poste -name logonui if( -not ($ecran_verr) -and ($utilisateur)) { "ask permission" }
2

While breaking an expression down into multiple steps is always a good idea for debugging, as demonstrated in vonPryz's helpful answer, sometimes you do want the concision of a single expression without auxiliary variables.

What is wrong with my syntax?

You're missing (...) around the Get-WmiObject ... | Select-Object ... pipeline.

To use a command or pipeline as part of a larger expression, you must always enclose it in (...) A command in PowerShell is a call to an executable - be it a cmdlet, function, alias, or external program.

A simple example:

# !! BROKEN: tokens `-eq 'jdoe'` are interpreted as *arguments for Select-Object*
# !! rather than as operator -eq and RHS 'jdoe'
if (Get-WmiObject Win32_ComputerSystem | Select-Object -Expand UserName -ne 'jdoe') {
  'not jdoe'
}

# OK: (...) around the pipeline properly embeds it in the overall expression:
if ((Get-WmiObject Win32_ComputerSystem | Select-Object -Expand UserName) -ne 'jdoe') {
  'not jdoe'
}

Here's a fixed version of your original command that fixes that improves other aspects too:

if (
  (Get-WmiObject –ComputerName $poste –Class Win32_ComputerSystem).UserName `
  -and -not `
  (Get-Process -ErrorAction SilentlyContinue -ComputerName $poste -name logonui)
) {
  "ask for permission"
}
  • Given that your Get-WmiObject call only ever outputs 1 object, you can access the .UserName property directly, which is also more efficient than piping to Select-Object -ExpandProperty.

  • Get-Process outputs a non-terminating error if a process by the given name cannot be found, so -ErrorAction SilentlyContinue suppresses that.

  • Note the use of ` as a line-continuation character, which allows spreading the conditional across multiple lines, making it much more readable.
    Note that the ` must be at the very end of the line.

2 Comments

That ` for line-continuation is so nice, I will use it more often! Makes it much more clear.
@Rakha: Yes, though it can be tricky, because not even whitespace is allowed after it (also, it throws off SO's syntax highlighting). Note that there are situations where you don't even need it, such as after a | or {.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.