Update AddresBookPolicy AddressLists based on variable input - powershell

I am trying to update an Address Book Policy on Exchange Online.
Idea is that I parse some Address Lists and save these into a variable.
These could be passed into the Set-AddresBookPolicy.
So I start off with parsing these adresses:
$AddressLists = (Get-AddressList).Id | ? {$_ -like "*Company_1*"}
This results an array like \Company_1_Users, \Company_1_Contacts, \Company_1_DLs as expected.
I apply these with
Set-AddressBookPolicy -Identity "Company1" -AddressLists $AddressLists `
-RoomList "C1_Rooms" -GlobalAddressList "C1_GAL" -OfflineAddressBook "C1_OAB"
Result is an error:
WARNING: An unexpected error has occurred and a Watson dump is being generated: The operation can't be performed on this object because its status isn't valid.
The operation can't be performed on this object because its status isn't valid.
+ CategoryInfo : NotSpecified: (:) [Set-AddressBookPolicy], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.Exchange.Management.SystemConfigurationTasks.SetAddressBookPolicy
+ PSComputerName : outlook.office365.com
I've tried converting it to a string (with -join ',') and have tried casting it, but I can't get further then an error (which then is of another kind).
If I copy the output and then type it into the command, it works. So that part is correct. However, I would like to automate this.
Does anyone know how I can correctly provide an input into the below cmdlet and have it running as expected?
EDIT: added full script below:
$AddressLists = #()
$AddressLists = (Get-AddressList).Id | ? {$_ -like "*Company_1*"}
$AddressLists = $AddressLists -join ',' #Adding this line just results in another error...
Set-AddressBookPolicy -Identity "Company1" -AddressLists $AddressLists `
-RoomList "C1_Rooms" -GlobalAddressList "C1_GAL" -OfflineAddressBook "C1_OAB"
The result of $AddressLists is an array (System.Array) with contents:
\Company_1
\Company_1Country1
\Company_1Country2
\Company_1Department1
\Company_1Department2

If your variable produces what you are saying...
$AddressLists = (Get-AddressList).Id | {$_ -like "*Company_1*"}
\Company_1_Users,
\Company_1_Contacts,
\Company_1_DLs
Then In Theory When You Add It Into a ForEach Loop It Should Work Accordingly. I Don't Have Exchange To Test It (by removing $updatecommand and leaving the execution command :o)
Change the settings of an address book policy in Exchange Online
<https://learn.microsoft.com/en-us/exchange/address-books/address-book-policies/change-the-settings-of-an-address-book-policy>
$AddressLists = ("\Company_1_Users", "\Company_1_Contacts", "\Company_1_DLs")
$iD = "Company1"
$rL = "C1_Rooms"
$gAL = "C1_GAL"
$oAB = "C1_OAB"
ForEach($AddressList in $AddressLists){
Write-Host "Without an Exchange Server, I'm Just Demonstating The Update Process"
Write-Host "The AddressList Being Updated Is -- $AddressList"
$updatecommand = "Set-AddressBookPolicy -Identity $iD -AddressLists $AddressList -RoomList $rL -GlobalAddressList $gAL -OfflineAddressBook $oAB"
Write-Host $updatecommand
}

Related

Value type error during changing of email addresses and aliases via PowerShell ISE

I trying to do bulk change of distribution lists, using Powershell script, but didn't made it far.
I importing new addresses and aliases from a .CSV file and seems like this is the issue. Because when I assigning an address and an alias to an exact DL, then it all fine. Or maybe the script written bad.
Error message:
Cannot process argument transformation on parameter 'EmailAddresses'. Cannot convert value "System.Collections.ArrayList" to type "Microsoft.Exchange.Data.ProxyAddressCollection". Error: "The address
'SMTP:#{DisplayName=TEAM_A; PrimarySmtpAddress=a_dl#company.com; Alias=a_dl#company.org}.PrimarySmtpAddress' is invalid: The address '#{DisplayName=TEAM_A; PrimarySmtpAddress=a_dl#company.com;
Alias=a_dl#company.org}.PrimarySmtpAddress' is not a valid SMTP address.
Parameter name: address
Actual value was #{DisplayName=TEAM_A; PrimarySmtpAddress=a_dl#company.com; Alias=a_dl#company.org}.PrimarySmtpAddress."
+ CategoryInfo : InvalidData: (:) [Set-DistributionGroup], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Set-DistributionGroup
+ PSComputerName : outlook.office365.com*
The script:
Connect-ExchangeOnline
$psmtpa = Import-Csv C:\_temp\Excange\PrimarySMTPAddress.csv
ForEach ($name in $psmtpa){
ForEach ($email in $psmtpa){
ForEach ($alias in $psmtpa){
Set-DistributionGroup "$name.DisplayName" -EmailAddresses SMTP:$email.PrimarySmtpAddress,$alias.Alias
}
}
}
And the .CSV look like this:
PS And yeah, I trying to perform it, using PowerShell ISE, instead of writing a one-liner in PowerShell app. Also, I tried WindowsEmailAddress, but powershell don't understand it what is it.
There are a few things to note, first, the double quotes on "$name.DisplayName" are stringifying the object $name and appending .DisplayName to it. Remove them.
$object = [pscustomobject]#{
foo = 'var'
}
"$object.foo" # => #{foo=var}.foo
$object.foo # => 'var'
Second thing to note, on:
-EmailAddresses SMTP:$email.PrimarySmtpAddress,$alias.Alias
If you're looking to add a Primary and Secondary SMTP address, as Mathias pointed out, you should be using:
-EmailAddresses "SMTP:$($email.PrimarySmtpAddress)", "smtp:$($email.Alias)"
If instead, $email.Alias is actually an Alias, then you should be using:
-EmailAddresses "SMTP:$($email.PrimarySmtpAddress)" -Alias $email.Alias
See Subexpression operator $( ) for more info.
Lastly, you don't need 3 loops, 1 should be enough to loop over your CSV:
$psmtpa = Import-Csv C:\_temp\Excange\PrimarySMTPAddress.csv
foreach ($object in $psmtpa) {
Set-DistributionGroup $object.DisplayName -EmailAddresses "SMTP:$($object.PrimarySmtpAddress)", "smtp:$($object.Alias)"
}

How to automate removing Exchange Contacts in Office365

I am writing a powershell script that:
Compares two CSV files
Output files for: Changes, added, removed contacts
Update and add contacts
Remove contacts
The problem is when I try and removed contacts. Which is done by:
#Check for Removed Contacts
foreach($row in $File1_Data )
{
$data_found=0
foreach($id in $emails_id)
{
if ($row.ExternalEmailAddress -eq $id)
{
$data_found=1
}
}
if($data_found -eq 0 ) #Email Not Found
{ $row|Select-Object -Property ExternalEmailAddress|Export-Csv -Path $Removed_Contact -Append -NoTypeInformation}
}
Now I have a file with only the email addresses. The error comes when I try and run the command connected on the exchange server.
$RemoveContacts = Import-CSV ".\Removed Contacts_$((Get-Date).ToString('MMddyyyy')).csv"
$RemoveContacts | ForEach { Remove-MailContact -identity $_ -confirm:$false}
But I get the following error:
Cannot process argument transformation on parameter 'Identity'. Cannot convert the
"#{ExternalEmailAddress=testuser#testcompany.com}" value of type "Deserialized.System.Management.Automation.PSCustomObject"
to type "Microsoft.Exchange.Configuration.Tasks.MailContactIdParameter".
+ CategoryInfo : InvalidData: (:) [Remove-MailContact], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Remove-MailContact
+ PSComputerName : outlook.office365.com
$File_Data structure is in the format Microsoft requires.
and
$emails_id is the function that compares the two csv files. But that's not where the script breaks, that's just how i create the file.
What am I missing?
The error message is telling you that it can't convert the value of $_ to what it needs for -Identity parameter. Generally the -Identity parameter for most PS commandlets is going to be the human readable unique name of something. In this case, it would be an email address. With that said the error message is telling you that instead of $_ containing the string version of an email address, it contains a hash or dictionary object that contains a single property, ExternalEmailAddress.
So to make this work, change your $_ to $_.ExternalEmailAddress and now the call to Remove-MailContact will use the value of the ExternalEmailAddress property of the object in your ForEach loop.

Powershell Like operator invokes REST error

I am working on a custom PoweShell module picked up from the internet for our BI application.
My question is rather simple, the code below does not work:
Get-QlikDataConnection -filter "name -like 'Data*'"
And throws an error like:
Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
At C:\Program Files\WindowsPowerShell\Modules\Qlik-Cli\1.13\functions\core.ps1:32 char:15
+ ... $result = Invoke-RestMethod -Method $method -Uri $path #params -Web ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc
eption
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
However the code below works fine and shows me the correct output:
Get-QlikDataConnection -filter "name eq 'DataPrepAppCache'"
Am I doing something wrong or do some modules not understand a few operators?
After having a look at the source of the module you're using, Qlik-Admin-Utils, I would not use the -filter param, as the input you specify there gets processed by this block within the Invoke-QlikGet cmdlet:
If( $filter ) {
If( $path.contains("?") ) {
$path += "&filter=$filter"
} else {
$path += "?filter=$filter"
}
}
This script appends your filter as a query parameter in the URL, and it doesn't support regular PowerShell formatting, but sends the filter over to qLik's REST API.
If I were writing this, I'd ignore their filtering and do the following:
$Connections = Get-QlikDataConnection
$DataConnection = $Connections | Where name -like "Data*"
This is more likely to just work with less fiddling.
However, if you want to use Qlik's Filter support, I found this so you can read up on the syntax of it here.
It looks like they do offer a filter of their own which might help, it's the Starts With filter, defined as SW, for a syntax of Name sw 'Data'. You might try this and see if it works instead.
Get-QlikDataConnection -filter "name sw 'Data'"

Getting the error while inserting rows into azure table

I am trying to upload azure table row using PowerShell and I am receiving the below error. Could this be due to wrong Azure Storage powershell modules? I am using Azure.Storage 4.0.2 module.
Below is the Code:
# Getting all the resource group
$resource_group_list = Get-AzureRmResourceGroup
# Iterating through the resource group
foreach($resource_group_list_iterator in $resource_group_list){
# Since the solution applies for virtual machines,
# obtain the list of virtual machines for the resource group
$virtual_machine_list = get-azurermvm -ResourceGroupName $resource_group_list_iterator.ResourceGroupName
# Proceed only when resource group contains virtual machines
if(!($virtual_machine_list -eq $null)){
# Iterate through the virtual machine list
foreach($virtual_machine_list_iterator in $virtual_machine_list){
# Creat an unique ID by concatinating 'Resource Group name' and 'Virtual Machine name'
$unique_id = $resource_group_list_iterator.ResourceGroupName + $virtual_machine_list_iterator.name
#Write-Host $unique_id
$tag_list = $virtual_machine_list_iterator.Tags
$tag_list.GetEnumerator() | foreach {
#write-host $_.key
#Write-Host $_.value
#write-host ""
$partitionKey1 = $unique_id
if($_.key -eq 'owner' -and $_.value -eq 'ibm') {
#write-host "true"
$virtual_machine_name = $virtual_machine_list_iterator.Name.ToString()
$virtual_machine_resource_group_name = $resource_group_list_iterator.ResourceGroupName.ToString()
$virtual_machine_location = $virtual_machine_list_iterator.Location.ToString()
$virtual_machine_size = $virtual_machine_list_iterator.HardwareProfile.VmSize.ToString()
$virtual_machine_operating_system = $virtual_machine_list_iterator.StorageProfile.ImageReference.Offer.ToString()
$hash = #{}
#$hash.add('currentDate', $current_date)
$hash.Add('VM Name','VM')
$hash.Add('Resource Group',$virtual_machine_resource_group_name)
$hash.add('Location',$virtual_machine_location)
$hash.add('VM Size',$virtual_machine_size)
$hash.add('Operating System',$virtual_machine_operating_system)
Add-StorageTableRow -table $azure_table_object -partitionKey ("CA") -rowKey $unique_id -property $hash
}
}
}
}
}
Below is the exception that I received:
Exception calling "Execute" with "1" argument(s): "The remote server returned an error: (400)
Bad Request."
At C:\Program Files\WindowsPowerShell\Modules\AzureRmStorageTable\1.0.0.21\AzureRmStorageTableCor
eHelper.psm1:267 char:16
+ ... return ($table.CloudTable.Execute((invoke-expression "[Microsoft ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : StorageException
I have gone thru few online resources on how to troubleshoot, but I did not get any solution.
I use the fiddler to catch adding entity request on my side with your code. Then I could get the detail information that property name is invalid.
So please have a try to change the property name with following code.
$hash.Add('VM_Name','VM') #VM Name is invalid
$hash.Add('Resource_Group',$virtual_machine_resource_group_name) #Resource Group is invalid
$hash.add('Location',$virtual_machine_location)
$hash.add('VM_Size',$virtual_machine_size) #VM size is invalid
$hash.add('Operating_System',"windows")
Add-StorageTableRow -table $table -partitionKey ("CA") -rowKey $unique_id -property $hash
For more information about azure table property name please refer to this document.
poperty names are case-sensitive strings up to 255 characters in size. Property names should follow naming rules for C# identifiers.
Test Result:

pull text between characters

How do I pull text between two words? I know regex can do this and I have been looking around but the code I try just does not work for me at all...as clueless as a brick with regex...so probably am doing it totally wrong...
I have a text file and want to query whatever is displayed between these text strings:
[Problem Devices]
Device PNP Device ID Error Code
[USB]
I tried doing this but getting no where!
$devices = Get-Content c:\temp\dev.txt | out-string [regex]::match($devices,'(?<=\<Problem Devices\>).+(?=\<USB\>)',"singleline").value.trim()
You cannot call a method on a null-valued expression.
At line:1 char:141
+ $devices = Get-Content c:\temp\dev.txt | out-string [regex]::match($devices,'(?<=\<Problem Devices\>).+(?=\<USB\>)',"
singleline").value.trim <<<< ()
+ CategoryInfo : InvalidOperation: (trim:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Piping to out-string is not needed; get-content is sending each line of the file into the pipeline as a separate object. So you want to iterate through those objects with a foreach-object.
$devices = Get-Content c:\temp\dev.txt | foreach-object{[regex]::match($devices,'(?<=\<Problem Devices\>).+(?=\<USB\>)',"singleline").value.trim()}
However, you are still left with the problem of attempting to trim() a null object - if your regex match doesn't find a match, you can't call value.trim().
Your regex tries to match on <Problem Devices> when your input file has [Problem Devices].
Rather than try to do everything in a single set of pipeline steps, break your problem down:
For each line in the file, check for [Problem Devices]
For each subsequent line, if it is [USB], exit the loop. If it is not [USB], capturing each line into a variable (build an array of these lines)
After the loop, iterate over each element of the array you just built to parse each value out (creating a collection of PSObjects (one per device), or a collection of hashes (one per device), depending on your needs).
If you're not comfortable with regex, there are other ways:
$test = $false
$devices = get-content file.txt |
foreach {
if ($_.trim() -eq '[Problem Devices]'){$test = $true}
elseif ($_.trim() -eq '[USB]') {$test = $false}
elseif ($test){$_}
} | where {$_.trim()}