3

I queried Office365 for a list of all users that match the displayName of Chris.

I'd like to prompt the user for which Chris they want to select. In doing so I have the following for..each code

$tmpUserOffice = Get-MsolUser -SearchString "*Chris*"
if ($tmpUserOffice -is [array])
{
    if ($tmpUserOffice.Count -lt 50) {
        Write-Host "Many matching users in MSOL. Choose which one you want to save"    
        for ($i = 0; $i -lt $tmpUserOffice.Count; $i++) {
            Write-Host $i " "  $($tmpUserOffice[$i].DisplayName) 
        }   
        Write-Host $tmpUserOffice.Count " None of the above" 
        $chosen = Read-Host

        if ($chosen -eq $tmpUserOffice.Count) {
            Write-Warning "Nothing found. Try searching with different criteria or use wildcards"
            Write-Output $null
        }

        Write-Host $tmpUserOffice[$chosen] " selected" 
        $tmpUserOffice = $tmpUserOffice[$chosen]
        exit
    }
    else {
        Write-Warning "More than 50 matches found. Try searching for more specific criteria"
    }
}

One of my problems is how to get the contents of the following line to complete

Write-Host $i " "  $($tmpUserOffice[$i].DisplayName) 

Currently the output is

Many matching users in MSOL. Choose which one you want to save 
0
1
2  None of the above

What changes do I need to make to ensure that this value actually writes a value?

Editor's note: The problem turned out to be unrelated to the code posted here, which does work in principle.

mklement0
  • 382,024
  • 64
  • 607
  • 775
Ran Dom
  • 315
  • 5
  • 13
  • 1
    I think it should work as-is; `$i=4; write-host $i " " $(@(10..20)[$i])` writes `4 14` as expected. Do the users have a DisplayName entered? Are you getting that back from Get-MsolUser? Are you using PowerShell v2 or v3? – TessellatingHeckler Aug 03 '18 at 20:51
  • 1
    I realized that (elsewhere) a select statement was omitting the data I was trying to display. Thank you @TessellatingHeckler – Ran Dom Aug 03 '18 at 20:59

2 Answers2

5

I think that you just need to enclose it in double quotes:

Write-Host "$i  $($tmpUserOffice[$i].DisplayName)"

The double quotes allow you to embed variables $i, and the $(...) allows the value to be evaluated before being displayed.

HAL9256
  • 12,384
  • 1
  • 34
  • 46
  • 2
    If this works, then so does the OP's own attempt. While there may be advantages to using a single, expandable string in general, it makes no difference here (and we've since learned that the OP's problem was unrelated to their use of `Write-Host`). As an aside: to fully emulate `Write-Host $i " " $($tmpUserOffice[$i].DisplayName)` with an expandable string, you need _3_ spaces between `$i ` and `$(...)` - though the OP probably only meant to have _1_, due to misconception of how the arguments are processed. – mklement0 Aug 03 '18 at 22:56
2

We now know that there was nothing wrong with your code per se; this answer focuses on your use of Write-Host.

Your Write-Host commands suggest that you seem to think that juxtaposing expressions (e.g., $i) and string literals (e.g, " selected") performs string concatenation the way that awk does, for instance (e.g., $i " selected" resulting in literal 1 selected if $i's value is 1).

This is not the case:

  • The whitespace-separated tokens are individual arguments, which Write-Host implicitly joins by separating them with a single space each.
    Note: this functionality is specific to the Write-Host cmdlet; other Write-* cmdlets behave differently.

  • Because they're individual arguments, you actually do not need to enclose more complex expressions such as $tmpUserOffice[$i].DisplayName in $(...)

Taking one of your commands as an example:

Write-Host $i " "  $($tmpUserOffice[$i].DisplayName)

While this works in principle, it:

  • ends up with 3 spaces between the expanded expression values, because Write-Host inserts a space on either side of the " " argument in the process of joining the 3 arguments with spaces.

  • is needlessly complicated: $(...) is not needed in this case.

What you probably meant to do:

Write-Host $i $tmpUserOffice[$i].DisplayName

Caveat: While the above syntax is convenient, it is not a general-purpose technique for composing strings.

HAL9256's answer shows how to use string expansion (interpolation) with a single double-quoted string ("...") to compose the output string up front.

Note that inside "..." you then do need $(...) in order to embed expressions that go beyond mere variable references (e.g., $var) - see this answer for more.

mklement0
  • 382,024
  • 64
  • 607
  • 775