Referencing variables that are not strings - powershell

I want to reference properties selected from a cmdlet and then use them later on in my script as $mailboxarray.totalitemsize and $mailboxarray.totalitemsize
This is breaking later on in my script as I assume it doesn't like the type of object it is. How can I make anything I pull into the references a string? At the moment I am getting "No mapping exists from object type System.Management.Automation.PsObject to a known managed provider type". My code at the moment: the first command works fine but I can't use expandproperty when there are multiple entries like line two?
$recipienttype = Get-mailbox -identity $recordset.PrimarySmtpAddress | Select -expandproperty RecipientTypeDetails
$mailboxarray = Get-Mailbox -identity $recordset.PrimarySmtpAddress | Get-MailboxStatistics | Select-object totalitemsize, lastlogontime

Related

Powershell Get-ADGroupMember does not return list

I am trying to utilize PowerShell to audit all of our security group members in AD. I have been trying to get Get-ADGroupMember to work but anytime I try it, it returns the message 'Cannot find an object with identity 'groupName' under: 'DC=xxxx,DC=xxxx,DC=xxxx,DC=xxxx'.
Ive tried the following with no luck:
$groupNames = 'groupName1' , 'groupName2' , 'groupName3'
foreach ($group in $groupNames) {
Get-AdGroupMember -Identity $group
}
Has anyone successfully compiled a list of group members in security groups from AD and exported them into a .CSV?
There are few things to consider when querying AD groups using the Get-AdGroup* commands.
The -Identity parameter only accepts values that match an object's Guid, ObjectSid, DistinguishedName, or SamAccountName. If your input is something other than one of those attribute values, you will either need to run another command to retrieve the proper data or change your list.
-Identity only accepts a single value, which means if you want to supply a list of values, you need to loop through them.
Get-AdGroupMember does not output as many attribute/value pairs as Get-AdUser. You cannot force it to output more attributes than it does. It does not have a -Properties parameter like Get-AdUser. Sometimes it requires using both commands to get all of the required data.
You can send Get-Ad* output to CSV using Export-Csv. If you do not use any property filtering like with Select-Object, the returned property names will be the columns of the CSV. The associated values of the properties will appear in rows with each row representing one returned object. You can choose to either send the entire results of the command once to the CSV or each time the command runs using Export-Csv -Append.
Use Select-Object to only output properties you care about. Select-Object Property outputs a custom object that includes only the property Property and the value(s) of Property for each object returned. If you only want to return the value rather than a custom object, you can use Select-Object -Expand Property.
Get-Content can be used to read a file. If the file contains only a list of values, perhaps SamAccountName values, you can use Get-Content file.txt to retrieve that list. The list will be an array that can be looped through.
Since Get-AdUser can be verbose, it is wise to use the -Properties parameter to explicitly list any extra properties beyond the default set you want to return. -Properties * will return all properties, but that is not best practice.
Given the above considerations, I would do the following:
$groupNames = 'groupName1' , 'groupName2' , 'groupName3'
# Alternatively, if you have a file (file.txt) with your group names listed as one group per line
$groupNames = Get-Content file.txt
# The Foreach-Object section is only needed if $groupNames does not contain a valid -Identity value
# The Filter below uses Name attribute as an example because it assumes $groupNames contains Name attribute values. If it contains another attribute, update the filter accordingly.
$SamAccountNames = $groupNames | Foreach-Object {
Get-AdGroup -Filter "Name -eq '$_'" | Select-Object -Expand SamAccountName
}
# Storing the loop output into a variable is efficient provided you have enough memory for the operation.
# Alternatively, you can just pipe the `Get-AdGroupMember` into `Export-Csv -Append` but that could be a lot of writes!
$output = foreach ($group in $SamAccountNames) {
Get-AdGroupMember -Identity $group # You can use Select-Object here for specific properties
}
$output | Export-Csv -Path output.csv -NoTypeInformation

How to replace text in get-mailboxfolderstatistics without breaking the array

The Exchange PowerShell commands for Mailbox Folder Statistics and Permissions are disjointed and require you to massage data to take statistics and make them usable as variables for removing folder permissions.
I'm trying to use the replace commands in PowerShell to manipulate the values without breaking the array itself.
I've tried various ways of using the -replace command to handle this as it has been unsuccessful.
I'm trying to use code similar to this:
Get-MailboxFolderStatistics -Identity jon#towles.com | Select Identity | ForEach-Object { $_."Identity" -replace '.com','.com:'}
When I use the replace function, it breaks the array so we no longer see headings and cannot use it with stuff like foreach-object {Remove-MailboxFolderPermissions -identity $_.identity -user testuser}
I expect that the replace function will still keep the data layout.
If you want to maintain your psobject structure, you need to avoid dereferencing properties or expanding properties. In your case, you can use a calculated property in your Select-Object command.
Get-MailboxFolderStatistics -Identity user#domain.com |
Select-Object #{Name='Identity';Expression={$_.Identity.Replace('.com','.com:')}}
Your current pipeline object $_ is a psobject with accessible properties. When you use the dereference operator ., you are retrieving a value for one of the properties. $_.Identity produces a different object. Since you do not incorporate that value back into a custom object, the only properties you have available are ones available to its object type, which does not include Identity.
With that said, you don't technically need to maintain your object schema to perform subsequent tasks. Even if you output a string with your first command, you can store that string in a variable and use it in another command. If your plan is to use a Foreach-Object to update all of your objects, you can update the pipelined object for future use within the loop.
Get-MailboxFolderStatistics -Identity user#domain.com | ForEach-Object {
$_.Identity = $_.Identity.Replace('.com','.com:')
Remove-MailboxFolderPermissions -Identity $_.Identity -User testuser
}

Powershell Custom column returning empty value with certain cmdlets

When adding a custom column with the get-mailbox cmdlet i get an empty value.
I'm trying to add a custom column using select #{} on the get-mailbox cmdlet. no matter what i tried the result is always an empty value, i changed the original cmdlet and replaced it with say get-process and then it did work.
I even tried with explicitly providing a username and not relying on the pipeline variable, and it didn't work.
get-mailbox <username> | select name, #{name="size"; expression={Get-MailboxStatistics $_.samaccountname | select -ExpandProperty TotalItemSize}}
Thanks in advance for any help.
Edit 1: The reason my question is not the same as Powershell script with Get-Mailbox and Get-MailboxStatistics missing output, as in the mentioned question the person was getting some results from their custom columns, just they were having issues with one row on one column, i don't even get results on the second or third rows.
Edit 2: I know i can create my own object, but i was trying to not to have to, this above code should be working (in a perfect world atleast). also the reason i'm not piping directly, i would've but i was trying to present my question with the least code possible to make it easier for the community to replicate it and to dissect it, the actual code i wanted to run is this
get-mailbox <username> | Get-MailboxStatistics | select displayname,TotalItemSize,#{name="Archive size";expression={Get-MailboxStatistics $_.samaccountname -archive | select -ExpandProperty TotalItemSize}}
My end goal was to get a table with a list of users with their mailbox size and their archive size.
Edit 3: never mind, i tried creating my own object and the same issue persisted. Provided my code used for the object.
get-mailbox <username> | foreach {[pscustomobject]#{name = $_.name; "mailbox size" = Get-MailboxStatistics $_.samaccountname | select -expand TotalItemSize; "Archive size" = Get-MailboxStatistics $_.samaccountname -archive | select -expand TotalItemSize}}
Thanks again!
Got it. Your code read like this:
get-mailbox <username> | Get-MailboxStatistics | select displayname,TotalItemSize,#{name="Archive size";expression={Get-MailboxStatistics $_.samaccountname -archive | select -ExpandProperty TotalItemSize}}
has an error. Your expression includes reference to samaccountname which is in Get-Mailbox output but not in Get-MailboxStatistics output, thus you're querying a null mailbox. To fix, query archive mailbox with a displayName attribute.
get-mailbox <username> | Get-MailboxStatistics | select displayname,TotalItemSize,#{name="Archive size";expression={Get-MailboxStatistics $_.displayname -archive | select -ExpandProperty TotalItemSize}}

-contains operator failing when it should not be

I am writing a script to create new AD users and doing a test to make sure an existing displayname is not found because New-ADUser will fail if one is found. Can someone help me understand why I might never get a true outcome from the following array list?
$ExistingDNs= Get-ADUser -SearchBase 'OU=whateverOU' -Filter * -Property displayname | select displayname | Out-string
My goal is to load up all the existing displaynames in an OU and then compare this with a method in which I read a CSV file to create a displayname, but I can't seem to get it to return as true.
If ($ExistingDNs.DisplayName -contains $DisplayName)
I was told this should work, but when I try looking at the array it is empty? Only $ExistingDSs shows me the list visually in ISE, where I can see clearly that a name exists that is the same in my CSV file, but the match is never found and never comes back as true even though both are string values I believe.
I'm sure it is because you are using Out-String which breaks the object array that select displayname would have created. Currently your $ExistingDNs is a newline delimited string when you really want a string array.
$ExistingDNs = Get-ADUser -SearchBase 'OU=whateverOU' -Filter * -Property displayname | select -ExpandProperty displayname
Also we use -ExpandProperty so you just end up with an array of strings. That way your conditional statement can be reduced to...
If ($ExistingDNs -contains $DisplayName)

Import Member Group attribute from AD to .csv

I am using ActiveRoles Management Shell under Windows XP , Powershell ver 2 for retreiving Group data from AD and exporting it to csv file.Everything works well apart from getting member list it is so long that the program is writing in excel cells under member column System.String[] each time.How can I make it write whole list there , is it possible ? I could actually have only the name of the member don't need whole connection path.Is there a possibility to get from group field member only name ?
get-QADGroup -SearchRoot 'ou=User,ou=Groups,ou=PL,dc=test,dc=com'| Select-Object -property name,sAMAccountName,description,groupType,member|Export-Csv -path Y:\csv\groups.csv
Ok, as Matt suggested you want an expression in your Select statement. I would use something like this:
#{l="Members";e={$_.Members -join ", "}}
Which when inserted into your one-liner looks like:
get-QADGroup -SearchRoot 'ou=User,ou=Groups,ou=PL,dc=test,dc=com'| Select-Object -property name,sAMAccountName,description,groupType,#{l='Members';e={$_.member -join ", "}}|Export-Csv -path Y:\csv\groups.csv -NoTypeInfo
I also added -NoTypeInfo to the export to skip the annoying lead line telling you it's a PSCustomObject or some such and actually just get your data (and headers).
I don't have access to the quest cmdlets so I will provide a solution based on cmdlets from the activedirectory
Get-ADUser -Filter * -SearchBase "OU=Employees,DC=Domain,DC=Local" -Properties memberof |
Select-Object name,#{Name="Groups";Expression={$_.MemberOf |
ForEach-Object{(Get-ADGroup -Identity $_).Name + ";"}}} |
Export-Csv C:\temp\TEST.CSV -Append
To make sense of this by line:
Should be self explanatory. Get all users in the OU defined. You would need to change this to suit your needs.
The select statement appears normal until you reach the calculated property Groups.
What continues from the previous line is cycling through every group that an individual user is a memberof and get the friendly name of the group (MemberOf returns DistinguishedName's). At the end of every group add a ";" as to not interfere with the CSV that will be made later.
Append to a csv file.
For brevity I didnt include all the extra properties that you included in your Select-Object statement. You would obviously need to add those back as the need fits.
Since you have the use the Quest cmdlets you could just change member in your select statement to the following:
#{Name="Groups";Expression={$_.member | ForEach-Object{"$_;"}}}
I cannot test if this will work. It is based on the assumption that member contains a simple name as supposed to a distinguishedname