powershellscripting

How to output multiple variables in one line


I am attempting to determine if users in a CSV are active or not, additionally, I want to know if they are service accounts, user accounts, or machine accounts based on OU.

Everything is swell, until I try to output it... The output is on several lines (one for each var).

I would like the output to be on one line (with commas between so I will have a CSV when I am done)... I have tried this twenty different ways with forty different results O_o.

Bonus: add a message for any names that produce errors (i.e. user doesn't exist...) I am thinking of an if/else for that, but have not been able to get the basic output to behave.

I have tried enclosing in parenthesis, concatenating variables, nesting variables... beating my computer with a stick... quietly contemplating my life choices...

$Users = Get-Content C:\ActiveUsers.txt

ForEach ($User in $Users){
$properties = Get-ADUser -Identity $User | select SamAccountName,Enabled,DistinguishedName 
if (Select-String -Pattern "UserMgt" -InputObject $properties) { $base = "User" }
if (Select-String -Pattern "ApplSec" -InputObject $properties) { $base = "Service Account" }
if (Select-String -Pattern "WkstnMgt" -InputObject $properties) { $base = "Machine Account" }
write-output $properties.SamAccountName $properties.Enabled $base
#$Output = Write-Output $properties.SamAccountName $properties.Enabled $base 
#$Output #| out-file  C:\UserStatus-OU2.csv -append
}

Solution

  • To focus on the general title of your question (see the bottom for the optimal solution in your specific case):

    Given multiple variables, say $a, $b, $c, how can I output them as a single-line string, with a configurable separator, say ,?

    In the following examples, assume values 'foo', 'bar', 'baz' as the values of variables $a, $b, and $c, respectively, which you can create with the following (destructuring) assignment: $a, $b, $c = 'foo', 'bar', 'baz'.

    PS> $a, $b, $c -join ','
    foo,bar,baz
    

    This approach has the advantage of working with arrays of any size as the LHS.

    PS> "$a,$b,$c"
    foo,bar,baz
    
    PS> '{0},{1},{2}' -f $a, $b, $c
    foo,bar,baz
    

    As for what you tried:

    Write-Output $properties.SamAccountName $properties.Enabled $base

    Passing multiple arguments to Write-Output writes them to the pipeline one by one; if these arguments are strings, each string prints on its own line, which also applies if you send the output to Out-File / > or Set-Content.


    That said, since you're creating rows for a CSV file, it's much better to create custom objects to represent the rows and serialize them to a file with Export-Csv (based on the code in your question, not your answer:

    Get-Content C:\ActiveUsers.txt | 
      ForEach-Object {
        $properties = Get-ADUser -Identity $_ | Select-Object SamAccountName, Enabled, DistinguishedName 
    
        # Consider using `elseif` here, unless you really want to evaluate
        # all conditions every time.
        # Also, it's better to check a specific property value rather than
        # searching the string representation of the entire object, e.g.
        #   if ($properties.DistinguishedName -match 'UserMgmt') ...
        if (Select-String -Pattern "UserMgt" -InputObject $properties) { $base = "User" }
        if (Select-String -Pattern "ApplSec" -InputObject $properties) { $base = "Service Account" }
        if (Select-String -Pattern "WkstnMgt" -InputObject $properties) { $base = "Machine Account" }
    
        # For each user, output a custom object.
        # The custom objects' property names becomes the CSV column headers
        # when Export-Csv processes the outputs.
        [pscustomobject] @{
          SamAccountName = $properties.SamAccountName
          Enabled = $properties.SamAccountName
          Base = $base
        }
    
      } | Export-Csv -NoTypeInformation C:\UserStatus-OU2.csv
    

    Note the use of a single pipeline.