Powershell won't use parameter value from a variable - powershell

The following command works perfectly:
Set-Mailbox $mailbox -EmailAddresses SMTP:am#foo.com,asmo#bar.org,toke#foobar.net
Trying to run the same command with the email addresses in a variable crashes.
$SMTPAddresses = "SMTP:am#foo.com,asmo#bar.org,toke#foobar.net”
Set-Mailbox $mailbox -EmailAddresses $SMTPAddress
Error:
Set-Mailbox : Cannot convert 'SMTP:am#foo.com,asmo#bar.org,toke#foobar.net' to the type 'Microsoft.Exchange.Data.ProxyAddressCollection' required by parameter 'EmailAddresses'. The address 'SMTP:am#foo.com,asmo#bar.org,toke#foobar.net' is invalid: The address 'am#klestrup.dk,asmo#bdk.dk,toke#bdk.dk' is not a valid SMTP address.
At line:1 char:39
+ Set-Mailbox $mailbox -EmailAddresses $SMTPAddresses
+ ~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-Mailbox], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,Microsoft.Exchange.Management.RecipientTasks.SetMailbox
The variable is a string btw.
$SMTPAddresses.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
Any ideas what is causing this?

The error message is rather self-explanatory. am#foo.com,asmo#bar.org,toke#foobar.net is not an e-mail address. Try it like this:
$SMTPAddresses = 'SMTP:am#foo.com','SMTP:asmo#bar.org','SMTP:toke#foobar.net'
Set-Mailbox $mailbox -EmailAddresses $SMTPAddresses

This is an array of two email address strings:
$SMTPAddresses = "SMTP:am#foo.com","asmo#bar.org,toke#foobar.net”
This is one string of two email addresses joined with a comma:
$SMTPAddresses = "SMTP:am#foo.com,asmo#bar.org,toke#foobar.net”

A peculiarity on Office 365 powershell using the xxx-UnifiedGroups command
If you're constructing the command like this:
$emails = #()
$emails += "SMTP:primary.address#domain.com"
$emails += "smtp:email2#domain.com"
# I'm splatting here but you can use whatever approach you prefer
$params = #{}
$params += #{"EmailAddresses" = $emails}
And you're getting this error, try making sure you include a tenant address like so:
$emails = #()
$emails += "SMTP:primary.address#domain.com"
$emails += "smtp:email2#domain.com"
$emails += "smtp:email#YourTenant.onmicrosoft.com"
$params = #{}
$params += #{"EmailAddresses" = $emails}
Note: Originally I got past the error using escaping, but that was a red herring. After getting full end to end working example it turns out you need a "MOERA" address (one that matches your 365 tenant) but the command gives a false error message about not being able to convert to the type 'Microsoft.Exchange.Data.ProxyAddressCollection'.

Related

PowerShell hashtable question - office 365

I need to set OOF message for around 80 users in O365.
I found a cmdlet Set-MailboxAutoReplyConfiguration which I can use to automate the procedure,
and it's looks fine but I'am probably missing something.
Here is the code:
$usersfile = import-csv "C:\Users\Out Of office bulk\Users.csv"
$setmailbox = #{
'Identity' = $usersfile.UserPrincipalName
'AutoReplyState' = 'Scheduled'
'externalaudience' = 'all'
'InternalMessage' = 'I am not here'
'ExternalMessage' = 'I am not here'
'StartTime' = '01/02/2020 01:00:00'
'EndTime' = '02/02/2020 23:00:00'
}
Set-MailboxAutoReplyConfiguration #setmailbox
my issue is with the Identity parameter,
when I run the $setmailbox
I can see that it showing the right UPN from the csv file:
Name Value
---- -----
AutoReplyState Scheduled
externalaudience all
Identity {blah#blah.com, blah2#blah.com}
StartTime 01/02/2020 01:00:00
EndTime 02/02/2020 23:00:00
InternalMessage I am not here
ExternalMessage I am not here
But when I run the script, i'am getting this error:
Cannot process argument transformation on parameter 'Identity'. Cannot convert the "System.Collections.ArrayList" value of type "System.Collections.ArrayList" to type "Microsoft.Exchange.Configuration.Tasks.MailboxLocationIdParameter".
+ CategoryInfo : InvalidData: (:) [Set-MailboxAutoReplyConfiguration], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Set-MailboxAutoReplyConfiguration
+ PSComputerName : outlook.office365.com
I've tried to change this:
'Identity' = $usersfile.UserPrincipalName
to almost any thing, and it didn't work.
Thanks a lot for your help.
PS:
I know that I can do something like that:
Import-Csv 'C:\Users.csv' | ForEach-Object {
$user = $_."UserPrincipalName"
Set-MailboxAutoReplyConfiguration `
-Identity $user -AutoReplyState Scheduled -StartTime "07/10/2018 01:00:00" `
-EndTime "7/15/2018 23:00:00" -InternalMessage "I am not here" -ExternalMessage "I am not here."
}
but for practice purposes I prefer to do it with the hash table in order to understand it better.
Solution:
thanks to #Lee_Dailey, I didn't noticed that the identity parameter accepts only one user each time, so the solution for multi user is to use the foreach-object.

Use modified property of object as parameter in Powershell for Set-MailPublicFolder

When we create a public folder and mail enable in Exchange Online, the default email address is #domain.onmicrosoft.com
Our folder names are "NNNNN_Folder name" where NNNNN is a 5 digit number.
I would like to set the primary email address of the public folder to NNNNN#domain.com
I have tried many variations of this:
Get-PublicFolder -Recurse -Identity "\X\Y\Z"|
Sort-Object Identity –Descending|
Select-Object -first 4|
Set-MailPublicFolder -PrimarySmtpAddress {$_.name.substring(0,5)+"#domain.com"}
and receive errors about interpreting the resulting email address:
Cannot process argument transformation on parameter 'PrimarySmtpAddress'. Cannot convert value
"$_.name.substring(0,5)+"#domain.com"" to type "Microsoft.Exchange.Data.SmtpAddress". Error: "The email
address "$_.name.substring(0,5)+"#domain.com"" isn't correct. Please use this format: user name, the # sign,
followed by the domain name. For example, tonysmith#contoso.com or tony.smith#contoso.com."
+ CategoryInfo : InvalidData: (:) [Set-MailPublicFolder], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Set-MailPublicFolder
+ PSComputerName : outlook.office365.com
I also tried setting the EmailAddress of the PublicFolder to NNNNN#domain.com in the same operation.
-EmailAddresses #{$_.name.substring(0,5)+"#domain.com"}
It doesn't seem to be evaluating the argument or I'm missing something else?
If I change Set-MailPublicFolder ... with
% {$_.name.substring(0,5) + "#domain.com"}
I do see the email addresses I am expecting.
Thanks,
Craig.
See this version.
From Microsoft command documentation, the identity parameter is required (see this)
I am also not sure it can take the array and process each individual without specifying a foreach.
See this modified versions.
$PublicFolders = Get-PublicFolder -Recurse -Identity "\X\Y\Z"| Sort-Object Identity –Descending | Select-Object -first 4
$PublicFolders | foreach {
$NewEmail = "$($_.name.substring(0,5))#domain.com"
Write-Host "Settings MailPublicFolder with name $($_.Identity) to $NewEmail" -ForegroundColor Cyan
Set-MailPublicFolder -Identity $_.Identity -PrimarySmtpAddress $NewEmail
}

Powershell Script not recognising ForEach-Object as a valid cmdlet

I have writen a powershell script to make ammendments to Active Directory.
I am Getting a funny error.
Here is the script.
#imports the module active directory if it isn't there.
function add-ADmodule()
{
$modules = Get-Module | Where-Object{$_.Name -like "*ActiveDirectory*"}
if($modules -eq $null)
{
Import-Module ActiveDirectory
}
}
#import the data file
$user_csv = import-csv C:\temp\users.csv
#makes the ammendments to the AD object
function ammend-ADUsers($user_csv)
{#this is the loop to make ammendments to each object
$users_csv|ForEach-Object`
{
#assigns each user's AD object to a variable
$user_object = get-aduser -filter * `
-Properties mail |`
Where-Object{$_.mail -like $_."Email Address"}
#ammends the ad object in the above variable
set-aduser -Identity $user_object `
-OfficePhone $_."Office Number" `
-MobilePhone $_."Mobile Number" `
-StreetAddress $_."Street" `
-City $_."City" `
-PostalCode $_."PostCode"
}
}
#this is the main part of the code where it gets executed
add-ADmodule
Write-Verbose "Active Directory Module Added"
ammend-ADUsers($user_csv)
This is the error I am getting.
PS C:\Users\admin> C:\Scripts\ammend-aduser.ps1
ForEach-Object : The term 'ForEach-Object' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and try again.
At C:\Scripts\ammend-aduser.ps1:18 char:20
+ $users_csv|ForEach-Object`
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (ForEach-Object:String) [], Com
mandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
I am not not sure what could be causing this error or why it is happening.
Your issue is because you have not put a space between the cmdlet and the backtick character, but it would be better to not use a backtick and instead just keep the opening curly brace { on the same line:
$users_csv|ForEach-Object {
You also don't need a backtick after a pipe character. You might want to also consider using splatting instead of backticks to improve your formatting (backticks are generally discouraged as they can be hard to see and easy to use improperly). I suggest the following revision:
$users_csv | ForEach-Object {
#assigns each user's AD object to a variable
$user_object = Get-ADUser -filter * -Properties mail |
Where-Object{$_.mail -like $_."Email Address"}
$Props = #{
Identity = $user_object
OfficePhone = $_."Office Number"
MobilePhone = $_."Mobile Number"
StreetAddress = $_."Street"
City = $_."City"
PostalCode = $_."PostCode"
}
#ammends the ad object in the above variable
Set-ADUser #Props
}

PowerShell - Return value of AD User's First and Last name

I am attempting to pull a users first and last name from AD using PowerShell.
The commands:
$GivenName = Get-ADUser -Identity $User | select GivenName
Write-Host $GivenName
returns a value of: #{GivenName=Bruce}
I then tried to reduce the string down to just the part i need with the following commands:
$First = $GivenName.Replace("#{GivenName=","")
$First = $First.Replace("}","")
This should strip away all except for the string 'Bruce'
Instead I get this following error:
Method invocation failed because [Selected.Microsoft.ActiveDirectory.Management.ADUser] does not contain a method named 'Replace'.
At C:\Users\john.ring\Documents\Scripts\UpdateADUsers.ps1:10 char:5
+ $First = $GivenName.Replace("#{GivenName=","")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (Replace:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
My Google-fu has failed to find a solution. Any suggestion on how to correct the error or a better way to pull the users first name would be greatly appreciated.
When you pipe objects to Select-Object [propertyname(s)], the Select-Object cmdlet creates a new object for you, with the properties from the input object that you specified. This object in turn ends up being rendered as #{PropertyName1=PropertyValue1[;PropertyNameN=PropertyValue2]} when converted to a string.
To grab the value of a single property, and nothing else, use the -ExpandProperty parameter:
$GivenName = Get-ADUser -Identity $user |Select-Object -ExpandProperty GivenName
Since you need multiple properties from the same user, better store the the user in a variable and use the . dereference operator to access the GivenName and Surname properties:
$UserObject = Get-ADUser -Identity $user
$GivenName = $UserObject.GivenName
$Surname = $UserObject.Surname
GivenName is a user object attribute in Active Directory. You're storing the results of your query in a PowerShell object called $GivenName, however the two are not the same. To reference the user's given name, you need to reference the GivenName property of the PowerShell object. $GivenName.GivenName is what you are looking for.
It might be less confusing if you store the results of your AD query in an object named $User instead, so $User.GivenName is how you would reference the given name property.

Powershell: How to pass variable correctly to command

I apologize if I butchered the terminology for this, and understand I'm very new to PowerShell. I have read over some of the guides and this concept is clearly not getting through to me.
Concept:
I want to remove a mobile device from a user in Exchange 2010
Identify user from input
Create variable from input of the PhoneID
Remove the Phone using phoneID variable
I believe my problem is in how I'm passing this data to the next command. I know the appended "#[Identity " that get's added should be removed and I remember reading something about how when you pass data like this Powershell has no context? Here is my very simple script.
Script
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
. $env:ExchangeInstallPath\bin\RemoteExchange.ps1
Connect-ExchangeServer -auto
$PU = Read-Host "Enter Username"
$did = get-activesyncdevice -mailbox $PU | Select-Object identity
Remove-ActiveSyncDevice -Identity $did
Error
My error is as follows, and I've tried to research what I'm doing wrong but I'm just not getting it :-( , I replaced the actual output for the account with XX.
Remove-ActiveSyncDevice : Cannot bind parameter 'Identity'. Cannot convert value "#{Identity=XX" to type
"Microsoft.Exchange.Configuration.Tasks.ActiveSyncDeviceIdParameter". Error: "Cannot convert the "#{Identity=XX}" value of type
"Selected.Microsoft.Exchange.Data.Directory.SystemConfiguration.ActiveSyncDevice" to type "Microsoft.Exchange.Configuration.Tasks.ActiveSyncDeviceIdParameter"."
At line:1 char:35
+ Remove-ActiveSyncDevice -Identity $did
+ ~~~~
+ CategoryInfo : InvalidArgument: (:) [Remove-ActiveSyncDevice], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.Exchange.Management.Tasks.RemoveMobileDevice
Any help or advice on this would be amazing!
When you use Select-Object and give it just one property name, you get and object with just one property. But even though it only has one property, you still have to reference that one property by name:
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
. $env:ExchangeInstallPath\bin\RemoteExchange.ps1
Connect-ExchangeServer -auto
$PU = Read-Host "Enter Username"
$did = get-activesyncdevice -mailbox $PU | Select-Object identity
Remove-ActiveSyncDevice -Identity $did.identity