2

Summary of issue

I have two variables with the same content, the only difference is how the variable was populated, when i try to use it in exchange management shell i get for one variable an error while the other one works as it should be.

Long explanation - With examples

I created a transport rule to block emails from specific senders, I'm trying to use one line in powershell to add users the the block list.

  1. I tried first the regular way to manipulate an array using set-transportrule -identity "whatever" -from @{add="whoever"} But this doesn't work, i researched it and saw that it's by design, so i gave up on this.
  2. So I tried something else set-transportrule -identity "whatever" -from (get-transportrule -identity "whatever").from,"whoever2" But i again hit a road block.
  3. So tried set-transportrule -identity "whatever" -from "whoever1","whoever2" and it worked beautifully. But this is not what i want I'm trying to add to the existing values.

This got me thinking, so i started testing to find the differences between the two arrays

  1. First I created a variable variable1 = "whoever1","whoever2" and used it like this set-transportrule -identity "whatever" -from $variable1 and it worked as it should be.
  2. So I went ahead and created another variable variable2 = (get-transportrule -identity "whatever").from,"whoever2" and tried using it set-transportrule -identity "whatever" -from $variable2, but this didn't work.

I compared the variable types and they are identical. Whats going on here? What am i missing

Thanks in advance for any help!

mklement0
  • 382,024
  • 64
  • 607
  • 775
Yeahish
  • 69
  • 1
  • 7
  • 1
    did you compare the array item types or the arrays? `$Collection.GetType()` is not going to give you the same result as `$Collection[0].GetType()`. – Lee_Dailey Jan 22 '19 at 00:36

1 Answers1

2

In order to concatenate two arrays flatly, you must use +:

set-transportrule -identity "whatever" `
                  -from ((get-transportrule -identity "whatever").from + "whoever2")

Note: Since operator + can only be used in an expression, the entire -from argument must be enclosed in (...).

By contrast, <array>, <scalar> creates a 2-element array whose 1st element is <array>, and whose 2nd element is <scalar>, which is not your intent.

,, which is PowerShell's array-construction operator, creates an array with each operand becoming an array element as-is, whether a given operand is a scalar or an array.

By contrast, with an array-valued LHS, + concatenates the LHS and RHS, by appending the RHS element(s) as additional elements to the LHS (which implicitly creates a new array, given that arrays are fixed-size).


A simplified example:

$arr = 1, 2   # input array
$scalar = 3   # scalar to append

# INCORRECT: Creates *nested* array.
($arr, $scalar).Count # -> 2(!); [0] of the new array contains $arr, [1] $scalar
# Same as: (1, 2), 3

# CORRECT: Creates *flat* array.
($arr + $scalar).Count # -> 3
# Same as: (1, 2) + 3 == 1, 2, 3

Note that you can't tell the difference between $arr, $scalar and $arr + $scalar by how they print to the screen, because the implicit output formatting implicitly enumerates an array received as a single input object.

You can make the difference visible by piping to Format-Table with -Expand CoreOnly, which suppresses the implicit enumeration and instead prints the properties of any array element itself:

# Flat array: prints as expected.
PS> $arr + $scalar | Format-Table -Expand CoreOnly
1
2
3

# Array with sub-arrays: output reveals the presence of subarrays
PS> $arr, $scalar | Format-Table -Expand CoreOnly

Length LongLength Rank SyncRoot IsReadOnly IsFixedSize IsSynchronized Count
------ ---------- ---- -------- ---------- ----------- -------------- -----
     2          2    1 {1, 2}        False        True          False     2
3

For additional information, see the bottom section of this answer.

mklement0
  • 382,024
  • 64
  • 607
  • 775