Author Posts

November 17, 2016 at 11:50 am

I have a basic script for creating shared mailboxes in exchange that I modify each time to reflect if the mailbox is room, shared or equipment. I have not found a way for the script to accept that information in a variable. Script below. The -room (-shared, -equipment) is what I am trying to use a variable for.

New-Mailbox -Name $i.Name -Alias $i.Alias -OrganizationalUnit $i.OrganizationalUnit -FirstName $i.FirstName -LastName $i.LastName -Database $i.Database -Room

November 17, 2016 at 1:25 pm

Splatting could be one way to solve this problem:

$Parms = @{
    Name = $i.Name 
    Alias = $i.Alias 
    OrganizationalUnit = $i.OrganizationalUnit
    FirstName = $i.FirstName 
    LastName = $i.LastName 
    Database = $i.Database
}
If($RoomParam){
    $Parms.Room = $true
}

New-Mailbox @Parms

If you make 'RoomParam' and the others your script parameters you can set them from outside the script.

November 17, 2016 at 5:05 pm

I am not quite sure how that applies to the -room, -shared -equipment qualifier though. I don't have a problem with any of the other variables, they work well. It's only that one qualifier to the new-mailbox xxxxx -room.

So I am not sure how I would incorporate that into the splatting technique.

November 17, 2016 at 6:46 pm

Of course you don't need to splat the other parameter but it would make your script even a little easier to read.

Param
    (
        [Switch]
        $Room,
        [Switch]
        $Shared,
        [Switch]
        $Equipment
    ) 

$Parms = @{
    Name = $i.Name 
    Alias = $i.Alias 
    OrganizationalUnit = $i.OrganizationalUnit
    FirstName = $i.FirstName 
    LastName = $i.LastName 
    Database = $i.Database
}

If($Room){
    $Parms.Room = $true
}
If($Shared){
    $Parms.Shared = $true
}
If($Equipment){
    $Parms.Equipment = $true
}

New-Mailbox @Parms

November 17, 2016 at 7:20 pm

The only problem with doing it that way is that you have to duplicate the actual commands new-mailbox etc for each switch value. I am trying to avoid that.

When I create rooms and use Powershell, it's because I am creating multiples and I use a csv file for the information. So the hope was that a value in the csv (room, shared, equipment) could be used instead of -room, it would be -$_.type with type being the value room, shared, equipment.

This way the script is a foreach that recognizes for each row whether its a room mailbox, shared mailbox or equipment mailbox.

November 17, 2016 at 7:24 pm

Hmmm ... I'm a little confused now. You just would have to make a function of it and pass whatever you need as a parameter to it. Or that even would work with script parameters. Just make them available 'from outside'. Or do I get something wrong?

November 18, 2016 at 2:15 pm

I think he may be confused by how the switch parameters work. These 2 statements should be the same.

New-mailbox -Room

New-mailbox -Room:$true

So Olaf is only adding the one that's relevant, and he's setting the value to $true. I haven't used splatting a lot, so I don't know if setting Room to $null would accomplish the same thing as the first statement above or not.

November 18, 2016 at 2:36 pm

Hmmm ... but -Room is not set to $Null in my example. Either it is $true or not existing, what means $false – just like a any other switch parameter you use. You might just give it a try. It won't hurt you. 😉

November 18, 2016 at 2:47 pm

-Room 
    The Room parameter specifies that the type of resource is a room, if this mailbox is a resource mailbox. This parameter is required only if you're creating a resource mailbox.

    Required?                    true
    Position?                    Named
    Default value
    Accept pipeline input?       False
    Accept wildcard characters?  false

It's required to create a room mailbox but has no default value. I haven't tested it, but that implies to me that the value is irrelevant, it just needs to be specified.

November 18, 2016 at 3:00 pm

Function Show-SwitchValue {
    param(
        [switch]
        $Room
    )
    "'$($Room)'"
}

Show-SwitchValue

Show-SwitchValue -Room

try it

November 18, 2016 at 3:18 pm

Right, but I'm think it's more likely being used this way.

Function Show-SwitchValue {
    param(
        [switch]
        $Room
    )
    "'$($Room.ispresent)'"
}

Show-SwitchValue

Show-SwitchValue -Room

But more interesting:

Show-SwitchValue -Room:$false
'False'
Show-SwitchValue -Room $false
'True'

You really need to understand how the parameter is being used in order to splat it properly.

November 18, 2016 at 3:37 pm

Your first code example produces the same result as mine.

In my opinion in your second example will the '$false' not be the value for the switch parameter it will be taken as another/next parameter. If you like to explicitly assign '$false' to a switch parameter you have to use the way you alraedy showed -switch:$false

this will fail more obviously ... 😉

Get-ChildItem -File $false

November 18, 2016 at 3:59 pm

Exactly. It is the value in and of itself. I think that both of you are misunderstanding my request though. Let me try this again. First there are 3 options when creating a resource mailbox, -room, -shared or -equipment. These options give you specific things, like an auto booking attendant in the room and equipment mailboxes. It is necessary to specify what TYPE of resource mailbox it is and these are how you do that.

If I am creating a single resource mailbox, I do it in the console. If I am creating multiple mailboxes, I specify all the params in a csv file, import it and use a foreach to create the mailboxes. I want to be able to specify the resource type -room (-equipment, -shared) in the csv file.

So my csv file would look something like this:

Mailboxname alias database type
Sales Calendar scalendar xxxdb1 room
Scale Tester stester xxxxdb2 equipment
Atlanta Candy acandy atlxxxdb2 shared

This way all I need is a foreach loop that creates each mailbox using the values from the csv. I don't want to have to use any if, if else or switch functions to do this as it would defeat the entire purpose of not having to duplicate the command line 3 times.

If I was only creating room mailboxes it would look something like this:

$mail = import=csv xxxfilepath\name.csv
foreach($i in $mail)
{new-mailbox -name $i.mailboxname -database $i.database -alias $i.alias -room}

So to create multiple resource mailboxes with different types, it would look something like this, where -$i.type is the resource type room, shared or equipment. I have tried it this way using the variable value and it doesn't see it properly.

$mailboxes = import=csv xxxfilepath\name.csv
foreach($i in $mailboxes)
{new-mailbox -name $i.mailboxname -alias $i.alias -database $i.database -$i.type}

I have used splatting before and can't see where it would be of any benefit in this situation.

November 18, 2016 at 4:14 pm

I see what happened. When I saw your first response, it wasn't showing me the whole thing for some reason. I do see what you are explaining now.

I will try that.

November 18, 2016 at 4:57 pm

Feel free to ignore this, I'm just working out my own misunderstandings. 🙂

My inexperience with advance parameter processing is showing. I assumed an intuitive function for IsPreset, when its actually the same as the value, and only used for switch parameters. Here is what I thought I was demonstrating...

Function Show-SwitchValue {
    param(
        [switch]
        $Room
    )
    "Switch:Present: '" + $PSBoundParameters.ContainsKey('Room') +"'  Value:  '$($Room)'"
}

Function Show-VariantValue {
    param(
        $Room = ""
    )
    "Variant:Present: '" + $PSBoundParameters.ContainsKey('Room') +"'  Value:  '$($Room)'"
}

$s={Show-SwitchValue
Show-SwitchValue -Room
Show-SwitchValue -Room:$false
Show-SwitchValue -Room:$true $false
Show-SwitchValue -Room $false
$args = @{Room = $null}
Show-SwitchValue @args
$args = @{Room = $false}
Show-SwitchValue @args
$args = @{Room = $true}
Show-SwitchValue @args


Show-VariantValue
Show-VariantValue -Room
Show-VariantValue -Room:$false
Show-VariantValue -Room:$true $false
Show-VariantValue -Room $false
$args = @{Room = $null}
Show-VariantValue @args
$args = @{Room = $false}
Show-VariantValue @args
$args = @{Room = $true}
Show-VariantValue @args
}

invoke-command $s

Switch:Present: 'False'  Value:  'False'
Switch:Present: 'True'  Value:  'True'
Switch:Present: 'True'  Value:  'False'
Switch:Present: 'True'  Value:  'True'
Switch:Present: 'True'  Value:  'True'
Switch:Present: 'True'  Value:  'False'
Switch:Present: 'True'  Value:  'False'
Switch:Present: 'True'  Value:  'True'


Variant:Present: 'False'  Value:  ''
Show-VariantValue : Missing an argument for parameter 'Room'. Specify a parameter of type 'System.Object' and try again.
At line:13 char:23
+ Show-VariantValue -Room < <<<
    + CategoryInfo          : InvalidArgument: (:) [Show-VariantValue], ParameterBindingException
    + FullyQualifiedErrorId : MissingArgument,Show-VariantValue

Variant:Present: 'True'  Value:  'False'
Variant:Present: 'True'  Value:  'True'
Variant:Present: 'True'  Value:  'False'
Variant:Present: 'True'  Value:  ''
Variant:Present: 'True'  Value:  'False'
Variant:Present: 'True'  Value:  'True'

The last 3 splatted switch tests are the ones relevant to the original problem. Parameter existence and value can be determined separately, and if no value is specified and no default is defined, it evaluates to false.

November 18, 2016 at 5:06 pm

Olaf's original sample is want you want.

Create a hash of the standard parameters.

$Parms = @{
    Name = $i.Name 
    Alias = $i.Alias 
    OrganizationalUnit = $i.OrganizationalUnit
    FirstName = $i.FirstName 
    LastName = $i.LastName 
    Database = $i.Database
}

Add an additional key if you want to create it as a room.

If($RoomParam){
    $Parms.Room = $true
}

If you don't add that additional key, it's the same as calling new-mailbox without -room. So you need to determine which single additional key to add, Room, Equipment or Shared.

November 18, 2016 at 5:18 pm

This should make it clearer.

$Parms = @{
    Name = $i.Name 
    Alias = $i.Alias 
    OrganizationalUnit = $i.OrganizationalUnit
    FirstName = $i.FirstName 
    LastName = $i.LastName 
    Database = $i.Database
}

# $i.$mailboxtype = "Room"

switch ($i.mailboxtype) 
    { 
        "Room"      {$Parms.Room = $true} 
        "Shared"    {$Parms.Shared = $true} 
        "Equipment" {$Parms.Equipment = $true} 
    }

New-mailbox @Parms

November 18, 2016 at 5:28 pm

Late to the discussion but essentially if I understand you correctly the problem is that you need -room, -shared or -equipment at the end?

As far as I know you can't use variables as the paramter.
E.g.

$param = "-Class"
$value = "Win32_OperatingSystem"

Get-WmiObject $param $value

Will produce an error because it will try to interpret the "$param" as paramenter value, not a parameter.
One workaround would be to create the command line and then use Invoke-Expression, but Invoke-Expression is not really considered best practice to use 🙂

E.g.

$param = "-Class"
$value = "Win32_OperatingSystem"
$cmd = "Get-WmiObject $param $value"

Invoke-Expression $cmd

Should work.

November 18, 2016 at 5:29 pm

Ok, I was wrong, I still don't understand what is going on here. I am good up to this point:

If($Room){
    $Parms.Room = $true

So you have defined $Room, $Shared and $Equipment as switches which I presume is what will add the -room, -equipment etc to the command line. But how is it determining if $room is true? Where is it getting the value from to say that this particular set of parameters is for a room, shared or equipment mailbox?

Also how does this work in a foreach?

November 18, 2016 at 5:37 pm

Ron's example is a better one as it doesn't use invoke-expression.

November 18, 2016 at 5:56 pm

Yes, this is much clearer, thank you

November 21, 2016 at 7:44 am

Another option example

PS C:\> $csv_like = [PSCustomObject]@{ type ='room'; name='objname' }
PS C:\> $splat = @{ name=$csv_like.Name; $csv_like.Type=$true }
PS C:\> $splat

Name                           Value
----                           -----
name                           objname
room                           True