How to export value output without '#{}' after string replacement? - string

I'm trying to export forward list from Exchange 365 and remove "smtp:" string from output.
Here is PS code for Exchange 365 forwards list:
$forwards = Get-Mailbox –ResultSize Unlimited |
where {($_.ForwardingSmtpAddress –ne $null)} |
select identity, *forward*
$result = $forwards -replace "smtp:",""
$result
My $forwards value has format:
PS> $forwards
Identity DeliverToMailboxAndForward ForwardingAddress ForwardingSmtpAddress
-------- -------------------------- ----------------- ---------------------
name.surname1 True smtp:name.surname1#domain.com
name.surname2 True smtp:name.surname2#domain.com
name.surname3 True smtp:name.surname3#domain.com
I managed to remove that smtp: text with command:
$result = $forwards -replace "smtp:",""
But I get such ugly output for that variable:
PS> $result
#{Identity=name.surname1; DeliverToMailboxAndForward=True; ForwardingAddress=; ForwardingSmtpAddress=name.surname1#domain.com}
#{Identity=name.surname2; DeliverToMailboxAndForward=True; ForwardingAddress=; ForwardingSmtpAddress=name.surname2#domain.com}
#{Identity=name.surname3; DeliverToMailboxAndForward=True; ForwardingAddress=; ForwardingSmtpAddress=name.surname3#domain.com}
How to get rid of that #{} and present it right way as it was in $forwards variable? Maybe there is better way to remove smtp: from first value $forwards?

You should also be able to use calculated properties:
$forwards = Get-Mailbox –resultSize unlimited |
where { $_.ForwardingSmtpAddress –ne $null } |
select #{Name="Identity";Expression={$_.Identity}},
DeliverToMailboxAndForward, ForwardingAddress,
#{Name="ForwardingSmtpAddress";Expression={$_.ForwardingSmtpAddress -replace "smtp:",""}}
I don't have the means to test this right now, though.

Instead of creating a new variable it might be easier to modify the existing objects in your array. You need to do the replacement on each ForwardingSmtpAddress property:
$forwards | Foreach-Object {
$_.ForwardingSmtpAddress = $_.ForwardingSmtpAddress -replace "smtp:", ""
}
After this, just echoing $forwards to the screen should show you the updated values.

What would be the result when you use this snippet?
$forwards = Get-Mailbox –resultSize unlimited |
where {$_.ForwardingSmtpAddress –ne $null} |
select Identity, DeliverToMailboxAndForward, ForwardingAddress,
#{Name='ForwardingSmtpAddress';Expression={$_.ForwardingSmtpAddress.ToString().Replace('smtp:', $null)}}
If you don't wan't the #{} maybe you could convert or export it to a CSV format.
Export-Csv -Delimiter ';'
ConvertTo-Csv -Delimiter ';'

Related

Get-AzureADAuditDirectoryLogs format issue

I have this below script
Get-AzureADAuditDirectoryLogs | more
It will provide the output as below as expected;
enter image description here
But when we try to export this to a .csv I am not getting the output properly
Get-AzureADAuditDirectoryLogs | more | Export-Csv C:\temp\securitylogs.csv -NoType
If you see TargetResources or Additionaldetails columns its capturing something else which is not in the actual output. Can someone please tell us what we are missing here in Export-csv command?
enter image description here
Those properties cannot be accessed directly. I have given a reference code to display those properties.
$users = #()
$logs = Get-AzureADAuditDirectoryLogs
foreach ($log in $logs) {
$obj = [PSCustomObject]#{
ActivityDateTime = $log.ActivityDateTime
UserPrincipalName = $log.TargetResources.UserPrincipalName
Category = $log.Category
}
$users += $obj
}
$users | Export-Csv C:\Output\SomeFilename.csv -Force -NoTypeInformation
And also, you have to filter the logs using unique properties or matching some condition(like date), otherwise your output file will have multiple varieties of data.
sample:
Get-AzureADAuditDirectoryLogs -All $true -Filter "activityDateTime le 2021-11-29 and Category eq 'UserManagement' and OperationType eq 'Update' and ActivityDisplayName eq 'Update user'"
Hi both properties TargetResources and Additionaldetails have multiple values, so you need to be specific when extracting multiple values for the property. I'm not sure what the delimiter for those fields are.. try the following.
Get-AzureADAuditDirectoryLogs | more | Select activityDateTime, LoggedByService, `
OperationType, InitiatedBy,`
#{name="TargetResources";expression={$_.TargetResources -join ";"}},`
#{name="Additionaldetails";expression={$_.Additionaldetails -join ";"}} |`
Export-csv -NoTypeInformation C:\temp\securitylogs.csv -NoType

Export-CSV showing System.Collections.Generic.Dictionary`2[System.String,System.String] for Azure Tags?

My script using Get-AzDisk https://learn.microsoft.com/en-us/powershell/module/az.compute/get-azdisk?view=azps-5.9.0 like below
Get-AzDisk -ResourceGroupName $ResourceGroupName|Where-Object{$_.ManagedBy.Length -lt 1} | Select-Object Name, OsType, DiskSizeGB, ResourceGroupName, Location, Tags, Tier, ProvisioningState, TimeCreated | ogv
Cannot export the actual Tags values like in the Out-GridView does:
This is the .CSV column for Tags:
How to modify it so it can show the same data as in the OGV?
You could use a calculated property to format the object (which is a hashtable) to the desired output. Here is an example that uses an calculated property to serialize the tags as JSON:
Get-AzDisk -ResourceGroupName $ResourceGroupName
| Where-Object { $_.ManagedBy.Length -lt 1 }
| Select-Object Name, OsType, DiskSizeGB, ResourceGroupName, Location, #{e = {$_.Tags | ConvertTo-Json | Out-String}; l='Tags'} , Tier, ProvisioningState, TimeCreated
And here the corresponding output as CSV (after I pipe it to ConvertTo-CSV cmdlet):
Tags are a Hash.
$myTags = $vm.Tags
if($myTags) {
foreach ($key in $myTags.Keys) {
$curVal = $myTags[$key]
}
}
You can grab all the Keys and Values and write them to a string in the column.
Be aware the $curVal could itself be a multi-value system.collections.generic.dictionary and might require further manipulation.

Powershell odd behaviour when outputting to csv

I'm having a problem when outputting my foreach loop to a csv file.
My Groups are set like this:
$Groups = "Group1", "Group2", "Group3"
My code is:
$results = ForEach ($Group in $Groups) {
$memberof = get-adgroup $Group | select -expandproperty distinguishedname
Write-Output $Group
Get-ADObject -Filter 'memberof -eq $memberof -and (ObjectClass -eq "user" -or ObjectClass -eq "contact")' -properties * | select name, Objectclass, mail
Write-Output ""
Write-Output ""
}
$results | Export-csv Contacts.csv -NoTypeInformation
The problem seems to be coming from the Write-Output lines but I have no clue why. When I run my code without writing to a csv file, I get the expected result, something like:
NameOfGroup1
name Objectclass mail
---- ----------- ----
User1 user User1#mail.com
User2 user User2#mail.com
#Spaces caused by write-output ""
NameOfGroup2
User1 user User1#mail.com
Contact1 contact Contact1#externalmail.com
Then again when I run my code to write to csv file and have the write-output $Group commented out I get a similar result.
But if I run my full code from the top of this page including the write-output $Group, it comes out like this:
I've figured out what these results represent but I haven't got clue why they do print out like this.
Eseentially the numbers refer to the length of the group name, so the first 17 would be a 17 character group name, and then the number of lines below is equal to the number of contacts and users that are inside that group. The 2 zeros at the end of each group are the length of the write-output "" lines.
What is causing this behavior?
The following code will closely output what you are attempting.
$results = ForEach ($Group in $Groups) {
$memberof = get-adgroup $Group | select -expandproperty distinguishedname
Get-ADUser -Filter "memberof -eq '$memberof' -and (ObjectClass -eq 'user' -or ObjectClass -eq 'contact')" -properties name,ObjectClass,Mail | Select-Object #{n='Group';e={$Group}},name, Objectclass, mail
[pscustomobject]"" | Select-Object Group,Name,ObjectClass,Mail
[pscustomobject]"" | Select-Object Group,Name,ObjectClass,Mail
}
$results | Export-csv Contacts.csv -NoTypeInformation
Explanation:
Export-Csv converts an object or array of objects with properties into a CSV file. You can see the same result in the console with ConvertTo-Csv. Properties are converted into columns and property values are placed under their associated columns. When you output a string as in Write-Output $Group, it has a property of Length. To fix this, you need to add $Group as a calculated property in your Select-Object. If you want to do blank lines in your CSV, then you should output another object with all of the property values as ''.
When you mix objects in your PowerShell outputs, you can see unexpected results. Your Get-ADObject outputs a custom object. Your Write-Output lines output a string. Those two object types do not share properties. So you only see the properties for the first object in your array, which is a string. If you put all of the Write-Output statements at the end of your loop, you will see more properties in your CSV. See below for an example that just by reversing the order of processed objects, you get a different result.
$str = "string"
$obj = [pscustomobject]#{property1 = "value1"; property2 = "value2"}
$str,$obj | convertto-csv -notype
"Length"
"6"
$obj,$str | convertto-csv -notype
"property1","property2"
"value1","value2"
,
Notice the properties available to the custom object $obj and the string $str.
$obj | get-member -Type Properties
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
property1 NoteProperty string property1=value1
property2 NoteProperty string property2=value2
$str | get-member -Type Properties
TypeName: System.String
Name MemberType Definition
---- ---------- ----------
Length Property int Length {get;}

Search for a unknown property in an object based on its value

I am not sure how to do this with the usual suspects, namely Where-Object or Select-Object.
Suppose I want to find the string "needle" in PSCustomObject $Object, and that object can have several Note properties, such as $Object.Haystack1, $Object.Haystack2 and so on ..
In my case the number of note properties is known and fixed, but I'd like to know what to do for the harder case when you don't know how many properties your object has.
I poked around with Select/Where-Object and the operator -in but hadn't managed to make an easy, elegant one liner that does the job.
$obj = [pscustomobject]#{'Haystack1'='test';'Haystack2'='needle'}
$noteProperties = $obj|get-member -MemberType NoteProperty | select -ExpandProperty name
$noteProperties | Where {$obj."$_" -match 'needle'}
and you can one-liner it with
$obj|gm -M NoteProperty|?{$obj."$($_.Name)"-match'needle'}
One possibility:
$obj = [pscustomobject]#{'Haystack1'='test';'Haystack2'='needle'}
#($obj | Format-List *| Out-String).split("`n") -like '*needle*'
Haystack2 : needle
$obj = [PSCustomObject]#{"Haystack1" = "test"; "Haystack2" = "needle"}
$obj.PSObject.Properties | ? { $_.Value -eq "needle" }

How to append strings to other strings in a data set?

I want to append several strings in a data set with custom strings.
Example
Content of Dataset:
Test1
Test2
Test3
Result after appending:
Test1.com
Test2.com
Test3.com
Would I have to use regex to parse to the end of each Test[n] to be able to append it with a custom string (.com)? Has anyone got an example that describes exactly how to do it?
I am reading from a SQL-Table and writing values into a DataSet which is exported to CSV the following way:
$DataSet.Tables[0] | ConvertTO-Csv -Delimiter ',' -NotypeInformation |`% { $_ -replace '"','' } | out-file $outfile -Encoding "unicode"
The DataSet contains of Strings such as:
Banana01
Banana02
Apple01
Cherry01
Cherry02
Cherry03
The thing I want to do is append .com to only Cherry01, Cherry02, and Cherry03, and after appending .com, export it as a CSV file.
There are many ways. Here are a few:
# Using string concatenation
'Test1','Test2','Test3' | Foreach-Object{ $_ + '.com' }
# Using string expansion
'Test1','Test2','Test3' | Foreach-Object{ "$_.com" }
# Using string format
'Test1','Test2','Test3' | Foreach-Object{ "{0}{1}" -f $_,'.com' }
You could use something like this:
Example 1
$t = "test"
$t = $t + ".com"
Example 2
$test = #("test1","test2")
$test | ForEach-Object {
$t = $_ + ".com"
Write-Host $t}
With your added code I did this. I don't have a database to test it on, so I made the data set manually, so you might just have to change the $DataSet[0] in my code to $DataSet.Tables[0].
$DataSet[0] | ConvertTO-Csv -Delimiter ',' -NotypeInformation | Foreach-Object{$T=$_
IF($T -match "(Cherry\d\d)"){$T = $T -replace "(Cherry\d\d)(.+)",'$1.com$2'};$T } | out-file $outfile -Encoding "unicode"
$array | %{if($_ -match "^Cherry\d\d"){$_ += ".com"};$_}

Resources