Print (2) columns from powershell array - powershell

I created this array with:
$arecords = Get-DnsServerResourceRecord -ZoneName "mydomain.local" -RRType "A"
If I do $arecords.HostName I get a list of the hostnames. If I do $arecords.RecordData I get a list of the IP's. How can print both columns AWK style? Like $arecords.Hostname.RecordData?

The A records are CIM objects, and the default output formatting provided with the DnsServer module must know how to format them, but converting them to string just gets you the DnsServerResourceRecordA text.
You need to get the .RecordData.IPv4Address property out, with a calculated property, e.g.
$arecords| Select-Object -Property hostname, #{name='IP'; Expression={ $_.RecordData.IPv4Address }}
aka
$arecords| select hostname, #{n='IP';E={$_.RecordData.IPv4Address}}

Related

PowerShell pipe ExpandProperty to another Select-Object

I want to get the aliases for all email recipients in my O365 tenant.
If I were doing this one traditional Exchange, the easiest is to Get-Recipient and pull out the SMTPAddress property using Exchange Manangement Console. (Note the Select piped into another Select; works like a champ.)
Get-Recipient | Select Name,SamAccountName -ExpandProperty EmailAddresses | Select Name,SamAccountName,SmtpAddress
The issue is when I try to do the same thing in EXO, the "EmailAddresses" property is output as a flat string and so when I try to pipe it to a 2nd select, the only Property is the Length, not the actual value of the string.
The following kind of works, but I feel like there has to be a better way?
Get-EXORecipient | Select Name -ExpandProperty EmailAddresses | % {Write-Output "$($_.Name),$($_)"}
What -ExpandProperty EmailAddresses expands to are strings, as you state.
The additional properties that these strings are decorated with if you also pass (positionally implied) -Property arguments, such as Name in your example, are present, but will typically not surface unless you explicitly access them on the now-decorated output strings.
If you want output objects that contain each email address as a property, more work is needed.
Get-EXORecipient | ForEach-Object {
foreach ($emailAddress in $_.EmailAddresses) {
[pscustomobject] #{
EmailAddress = $emailAddress
Name = $_.Name
# ... add further properties of interest here
}
}
}

dnsserverresourcerecord - all expanded properties and zone

Get-DnsServerResourceRecord -ComputerName server -ZoneName zone.com
I want to run this command and get the HostName, RecordType, ZoneName and All RecordData sets.
I have something like so far:
Get-DnsServerResourceRecord zone.com -ComputerName server |
select hostname, recordType, name,
#{Name='ARecordData';Expression={$_.RecordData.IPv4Address}},
#{Name='CNameRecordData';Expression={$_.RecordData.HostnameAlias}}
My issue is two fold.
I need to know how to get the ZoneName into the record set so if I wanted to pass multiple zones I can keep that data separate.
The above example will create different columns for each RecordData. As a DNS record will only have one of these values is there a way to combine them into one column through PowerShell?
You can add the zone name as a calculated property just like you do with the record data.
foreach ($zone in $zone_list) {
Get-DnsServerResourceRecord -ZoneName $zone -ComputerName server |
Select-Object hostname, #{n='ZoneName';e={$zone}}, recordType, ...
}
Don't create individual properties, instead use a switch statement to select the relevant data depending on the record type in a single property.
... | Select-Object hostname ..., #{n='Data';e={
$rr = $_
switch ($rr.RecordType) {
'A' {$rr.RecordData.IPv4Address}
'CNAME' {$rr.RecordData.HostnameAlias}
...
}
}}

Parse string in Powershell

Learning powershell, trying to find out how to parse the first value from this resultset (10.60.50.40):
IPAddresses
-----------
{10.60.50.40, fe80::5ddf:a8f4:e29c:b66}
Normally I would just look it up, however, I don't know if {x, x} is a standard datatype of sorts in Powershell land.
Do I have to do rough string parsing, or is there some standard command to extract the first one, such as:
... | Select-Object IPAddresses | Select-String [0]
(I just made the select string part up. I'm lost.)
This is most likely the result of of the IPAddresses property of your object containing an array. The output you're seeing is stylized for display purposes, so it's not a string you would have to parse. Assuming your object is $obj, you should be able to do either of these:
$obj.IPAddresses[0]
$obj.IPAddresses | Select-Object -First 1
One solution is to use split function to convert the string into array and work with that like in the next steps:
Split the string into an array using the split function (comma is the item delimiter).
Grab the first item of the array (or whatever needed) and then also sanitize it (remove unnecessary curly bracket).
Example below:
$str = "{10.60.50.40, fe80::5ddf:a8f4:e29c:b66}"
$strArr = $str.Split(",")
Write-Host $strArr[0].Replace("{", "")
This is what I ended up doing:
$str = ... | Select-Object IPAddresses | ForEach {$_.IpAddresses}
Write-Host $str[0]
Depending on the source of your IPAddresses, this might not be optimal. You might get multiple IPAddresses per devices.
You might want to combine both approaches:
$str = ... | Select-Object -ExpandProperty IPAddresses | Select-Object -First 1
This will return the First IP address in your list per device.

Removing PowerCLI list truncation

I have the following snippet
Get-VM | select name, #{ Name = "IP Addresses"; Expression = { $_.Guest.IPAddress }} | Format-List
This outputs a fantastic list of servers and IP addresses however i notice some iPV6 addresses are truncated.
Name : eg.example.com
IP Addresses : {192.168.100.18, 2a03:2658:1068:0:250:56ff:feaf:593f, fe80::2504:56ff:feaf:593f, 192.168.100.1...}
How can I expand this to output all address space? I have tried using -ExpandProperty but this seems to fail.
Join the elements of the list to a string:
... | select name, #{n='IP Addresses';e={$_.Guest.IPAddress -join ', '}} | ...
The data is there but PowerShell has truncated it on screen by only showing you the first 4 elements in the IP Addresses property array. If you want to leave the property as an array you could change the preference variable for $FormatEnumerationLimit. By default it is 4.
$FormatEnumerationLimit = -1
That will force it to display the entire array on screen. It would be a good idea to save the value before you change it in case you need to reverse.
$savedValue = $FormatEnumerationLimit

Powershell - keep specific word in a string

I'm doing AD extract and I sort the field "distinguishedname" and I want to keep only a specific part of the value that represent the "parent OU" of the user itself.
I'm running this command to do an add extract of all users:
import-module activedirectory
get-aduser -filter * -properties *| Select-Object -Property SamAccountName,CN,co,ExtensionAttribute10,extensionAttribute11,extensionAttribute12,EmailAddress,whenCreated,Enabled,LastLogonDate,accountexpirationdate,distinguishedname |Sort-Object -Property Name | Export-Csv -Delimiter ";" -path "u:\theOutFile_NOFILTER_July.txt"
The column "distinguishedname" look like this:
distinguishedname
CN=familly\, user,OU=Remote Users,OU=New York,OU=My,DC=Company,DC=Local
CN=nameless\, cat,OU=Remote Users,OU=Ottawa,OU=My,DC=Company,DC=Local
CN=Cameron\, James,OU=Regular Users,OU=Hollywood,OU=My,DC=Company,DC=Local
CN=Bon\, Jean,OU=regular Users,OU=Springfield,OU=My,DC=Company,DC=Local
Note July 10
some time I will hit those line:
CN=Dog\, Cesar,OU=Special Accounts,OU=Regular Users,OU=Alma,OU=My,DC=Company,DC=Local
CN=keys\, Alicia,OU=Special Accounts,OU=Regular Users,OU=Paris,OU=My,DC=Company,DC=Local
CN=Clansy\, Door,OU=Map Drives,OU=Remote Users,OU=Rome,OU=My,DC=Company,DC=Local
In those case I am getting result such Remote Users an Regular Users instead of the City. I've tried some modification in your command you gave but in vain.
But I would like the first command to return this result instead:
distinguishedname
New York
Ottawa
Hollywood
Springfield
I can't effort to find how.
thanks in advance
Select-Object has a very versatile feature to create calculated properties using a hash in the place of a property name, where the key "Name" is set to the name of the calculated property (effectively, the column heading), and "Expression" is set to a code block that determines the value of the property, for each object in the pipeline. This will do what you want:
Get-Aduser -Filter * -Properties * | Select-Object -Property SamAccountName,CN,co,ExtensionAttribute10,extensionAttribute11,extensionAttribute12,EmailAddress,whenCreated,Enabled,LastLogonDate,accountexpirationdate,#{Name='distinguishedname'; Expression={[regex]::match($_.distinguishedname,'OU=.+?OU=(.+?),(OU|DC)=').Groups[1].Value}} | Sort-Object -Property Name | Export-Csv -Delimiter ";" -Path "u:\theOutFile_NOFILTER_July.txt"
Here's a breakdown what's going on:
Name='distinguishedname' tells it to create a new column called 'distinguishedname'. I used that name to match your example of the output you're looking for, but it doesn't have to be the name of an existing property. It would probably make more sense to change the name to something more descriptive of the values you're calculating, e.g. Name="parentOU".
[regex]::match is used to extract the desired portion from $_.distinguishedname using the regular expression OU=.+?OU=(.+?),(OU|DC)=, which isolates the name of the second OU in the list using a match group.
.Groups[1].Value returns the value of the first match group (the part matched by the contents of the first set of parentheses). .Value on its own without .Groups[1] would return the entire matched string, from the first OU= to the = following name of the parent OU. The following would work just as well, using zero-width assertions instead of a match group: [regex]::match($_.distinguishedname,'(?<=OU=.+?OU=).+?(?=,(OU|DC)=)').Value