I'm trying to extract some readable variables from AD, the following works.
$user = get-aduser "username" -Properties memberof, emailAddress, extensionattribute2, manager, physicalDeliveryOfficeName, url
$groups = ForEach ($group in $user.memberof){(Get-ADGroup $group).Name}
$groupStr = $groups -join "; " #Change "; " to "`r`n" for line break seperator
$user | Select-Object `
#{N="firstName";E={$_.GivenName}}, `
#{N="lastName";E={$_.Surname}}, `
#{N="email";E={$_.EmailAddress}}, `
#{N="businessArea";E={$_.extensionattribute2}}, `
#{N="accountName";E={$_.SamAccountName}}, `
#{N="manager";E={$_.Manager -replace '^CN=|,.*$'}}, `
#{N="office";E={$_.physicalDeliveryOfficeName}}, `
#{N="standardProfile";E={$_.url}}, `
#{n='Groups'; e={$groupStr}} | Export-CSV -NoTypeInformation "c:\out.csv"
However when I swap Get-aduser "username" to: Get-aduser -Filter {Enabled -eq $true} -SearchBase “ou=redacted,ou=UserAccounts,dc=redacted,dc=com”
It runs for a fairly long time and fills up the last 40gb on the disk and errors out as it's run out of space.
I know in the past I've wildcarded -Properties and run into similar issues (obvious now I understand) but I'm not sure what's causing the issue this time round.
{Enabled -eq $true} & -SearchBaselimit it to about 4 thousand users which I wouldn't think would take this long to run, and I've no idea what's using up the disk space.
Thanks in advance!
A slight augment in your code can achieve the results you want:
$users = get-aduser -filter "Enabled -eq '$true'" -Properties memberof, emailAddress, extensionattribute2, manager, physicalDeliveryOfficeName, url
$users | Foreach-Object {
$groups = ForEach ($group in $_.memberof) {
(Get-ADGroup $group).Name
}
$groupStr = $groups -join "; " #Change "; " to "`r`n" for line break separator
$_ | Select-Object #{N="firstName";E={$_.GivenName}},
#{N="lastName";E={$_.Surname}},
#{N="email";E={$_.EmailAddress}},
#{N="businessArea";E={$_.extensionattribute2}},
#{N="accountName";E={$_.SamAccountName}},
#{N="manager";E={$_.Manager -replace '^CN=|,.*$'}},
#{N="office";E={$_.physicalDeliveryOfficeName}},
#{N="standardProfile";E={$_.url}},
#{n='Groups'; e={$groupStr}}
} | Export-CSV -NoTypeInformation "c:\out.csv"
In your original code, $groups contains all of the groups for all enabled AD Users if you don't pick a specific user object for get-aduser. This is because $user.memberof will return all groups for every user in the $user array. Imagine 10 groups per user at 5000 users. You would have 50000 groups per user in your CSV.
-Properties adds attributes to return from the objects you are querying. It does not impact the number of objects you return only the size of the returned result. -Properties * vs. -Properties Attribute1,Attribute2 will likely use more memory but won't impact your CSV since you are selecting (Select-Object) the attributes you want to output. If you run Get-ADUser username, it will return a default list of attributes, which does not include mail for example. If you want to see the mail value along with the default attributes, then you must run Get-ADUser username -Properties Mail.
Related
<#
Run the Script On Active Directory to remove disabled users from All Groups and Set description what user was member of group if you have all the disable users in an OU.
Just add -SearchBase "OU=disabled,DC=domain,DC=com" after -filter 'enabled -eq $false'
#>
import-module activedirectory
$users=get-aduser -filter 'enabled -eq $false' -SearchBase "OU=Lockdown,DC=home,DC=ac,DC=uk" -Properties samaccountname,memberof |select samaccountname, #{n=’MemberOf’; e= { ( $_.memberof | % { (Get-ADObject $_).Name }) -join “,” }}
#set description
Foreach ($user in $users)
{ Set-ADUser $user.samaccountname -Replace #{info="Was a member of :- $($user.memberof)"}
# Export the list to csv
$Groups = (Get-ADPrincipalGroupMembership -Identity $user.SamAccountName | Select-Object -ExpandProperty name) -join ','
get-aduser $user.SamAccountName -properties memberof,samaccountname,givenname,surname | select samaccountname, #{name="Groups";expression={$Groups}} | export-csv "C:\Users\Administrator\Desktop\grpsss.csv" -Delimiter ";"
# Remove From all the Groups
Get-ADGroup -Filter {name -notlike "*domain users*"} | Remove-ADGroupMember -Members $user.samaccountname -Confirm:$False
}
$total = ($users).count
Write-Host "$total accounts have been processed..." -ForegroundColor Green
This script Removes all the groups from Disabled Users (From Disabled OU), It adds the names of those groups to Information Field along with an export of csv with the same information.
Porblem is that the csv is only populated with one user's groupmembership when there are many users in Disabled OU. question is, how do i export all the user and their group membership in a csv format. so i have a list of all the users that have been processed.
I always thought that export-csv will export eveything that powershell processes?
Thanks for your help in advance.
Your script attempts to export a csv for each user:
Foreach ($user in $users) {
...
get-aduser $user.SamAccountName -properties memberof,samaccountname,givenname,surname |
select samaccountname, #{name="Groups";expression={$Groups}} |
export-csv "C:\Users\Administrator\Desktop\grpsss.csv" -Delimiter ";"
...
}
However, this will mean that only the last user run in this foreach block will have its data written out to a .csv file.
This is because Export-Csv will overwrite the contents of an existing .csv file by default. So every user in your foreach block will overwrite the user before it.
To fix this, add the parameter switch -Append to the end of your Export-Csv command. This will add on each users data to the end of the file rather than overwrite it e.g.
Foreach ($user in $users) {
...
get-aduser $user.SamAccountName -properties memberof,samaccountname,givenname,surname |
select samaccountname, #{name="Groups";expression={$Groups}} |
export-csv "C:\Users\Administrator\Desktop\grpsss.csv" -Delimiter ";" -Append
...
}
hoping to get a little help here – I looked around the site but didn’t see anything quite like this (please direct me if there IS and I missed it).
I need to incorporate a new step in our user offboarding process, which would remove them from any AD Distribution Lists. I would like to set this up as a scheduled task to run once a night against two OU’s where the inactivated user accounts can be found.
I’d like to run this by pointing it at the USERS instead of the OU where the Distro Lists live, because I suspect that we’ll ultimately get the request to remove these users from OTHER types of group as well.
This snippet will remove AD Distro Lists from a single user, but leave all other types of AD groups alone:
# GroupCategory 0 = Distro List
# GroupCategory 1 = Security Group
# GroupScope 0 = DomainLocal
# GroupScope 1 = Global
# GroupScope 2 = Universal
$user = "userlogon"
Get-ADPrincipalGroupMembership -Identity $user|
Where {$_.GroupCategory -eq 0} |
ForEach {Remove-ADPrincipalGroupMembership -Identity $user -MemberOf $_ -Confirm:$false}
THIS snippet will look at an OU and return some info (just my example for using a variable with -searchbase):
$OUs = 'OU=PendingDeletion,OU=Users,DC=Stuff,DC=Place,DC=net','OU=HoldForReview,OU=Users,DC=Stuff,DC=Place,DC=net'
$OU | ForEach {Get-ADGroup -Filter * -Properties ManagedBy -SearchBase $_ } |
Select Name, ManagedBy |
Sort -Property Name
Out-GridView
BUT – Does it hold together that in order to complete my objective, I would do something like this?! I'm a bit out of my depth here, any advice for a re-write is appreciated:
$OUs = 'OU=PendingDeletion,OU=Users,DC=Stuff,DC=Place,DC=net','OU=HoldForReview,OU=Users,DC=Stuff,DC=Place,DC=net'
$user = "*"
$OUs | ForEach {
Get-ADPrincipalGroupMembership -Identity $user|
Where {$_.GroupCategory -eq 0} |
ForEach {Remove-ADPrincipalGroupMembership -Identity $user -MemberOf $_ -Confirm:$false}
}
There’s always a couple of ways to do stuff in PoSh, so I’m sure there’s a less-complicated way to do the same thing. If anyone has a different approach please feel free to suggest an alternative.
Thanks for taking a look!
So it sounds like you need three loops.
First, you will need to loop over the OU list to get the Users. We'll store the user objects in $Users
$OUs = 'OU=PendingDeletion,OU=Users,DC=Stuff,DC=Place,DC=net','OU=HoldForReview,OU=Users,DC=Stuff,DC=Place,DC=net'
$Users = ForEach ($OU in $OUs) {
Get-ADUser -Filter * -SearchBase $OU
}
Next loop over the users to get the groups that you want to remove. Then loop over the groups to remove each one.
ForEach ($User in $Users) {
Get-ADPrincipalGroupMembership -Identity $user |
Where-Object {$_.GroupCategory -eq 0} |
ForEach-Object {
Remove-ADPrincipalGroupMembership -Identity $user -MemberOf $_
}
}
I think I'd take this a little differently, by getting the group membership of all users, then grouping by AD group, and processing each group that way. Seems like it would be a lot fewer calls to AD. So I'd start out getting all of the users, just like BenH, except I would include their MemberOf property. Then I'd build a list of potential groups and filter down to just the Distribution Lists. I'd make a Hashtable of those as the keys, and make the value an array of each user that is in that group. Then loop through that removing the value of each from the associated key.
$OUs = 'OU=PendingDeletion,OU=Users,DC=Stuff,DC=Place,DC=net','OU=HoldForReview,OU=Users,DC=Stuff,DC=Place,DC=net'
$Users = ForEach ($OU in $OUs) {
Get-ADUser -Filter * -SearchBase $OU -Properties MemberOf
}
$UsersByGroup = #{}
ForEach($Group in ($Users.MemberOf | Select -Unique | Get-ADGroup | Where{ $_.GroupCategory -eq 0 })) {
$UsersByGroup.Add($Group.DistinguishedName,($Users | Where{ $Group.DistinguishedName -in $_.MemberOf}))
}
$UsersByGroup.Keys | ForEach{
Remove-ADGroupMember -Identity $_ -Members $UsersByGroup[$_] -Confirm:$false
}
I have a small script I wrote but I am wondering if this is the correct way to pull the MobilePhone property from Active Directory using powershell?
$csvfi = import-csv "C:\Users\\Documents\users.csv"
foreach($row in $csvfi)
{
$cellphone = $row.Phone
$fullname = $row.Name
$adphone = (Get-ADUser -Filter "Name -eq '$fullname'" -Properties * | Select MobilePhone).MobilePhone
Write-Host $fullname, $adphone
}
It just seems cumbersome to do -Filter, then -Properties *, then pipe to Select and then get the .MobilePhone attribute from that object.
As a side note, I just need the raw Mobile Phone number from AD, 1-AAA-NNN-NNNN so I can compare it with the cell phone number in the spread sheet users.csv.
$adphone = (Get-ADUser -Filter "Name -eq '$fullname'" -Properties MobilePhone).MobilePhone
This script works without error now, but the problem is that when several groups in the searchbase are found, the script will add all users from all groups to the cross forest target groups.
So for example:
ForestAGroup1 = contains 2 users
ForestAGroup2 = contains 2 users
::runs script::
now...
ForestBGroup1 = contains 4 users
ForestBGroup2 = contains 4 users
The ForestBGroup1/2 needs to contain the same identical users as ForestAGroup1/2.
Here is the script for reference:
$creds = Get-Credential
$Groups = Get-ADGroup -Properties * -Filter * -SearchBase "OU=TEST,OU=Shop Print Groups,OU=User,OU=domain Groups,DC=domainA,DC=com" | export-csv c:\temp\test.csv
$Groups = Get-ADGroup -Properties * -Filter * -SearchBase "OU=TEST,OU=Shop Print Groups,OU=User,OU=domain Groups,DC=domainA,DC=com"
Foreach($G In $Groups)
{
#Display group members and group name
Write-Host $G.Name
Write-Host "-------------"
$G.Members
#Add members to domainB group
$domainGMembers = import-csv C:\temp\test.csv | ForEach-Object -Process {Get-ADGroupMember -Identity $_.CN} | Select-Object samaccountname | export-csv c:\temp\gmembers.csv
$domainDNUser = import-csv C:\temp\gmembers.csv | ForEach-Object -Process {Get-ADUser $_.samaccountname -Server "domainA.com" -properties:Distinguishedname}
import-csv C:\temp\gmembers.csv | ForEach-Object -Process {Add-ADGroupMember -Server "domainB.com" -Identity $G.Name -Members $domainDNUser -Credential $creds -Verbose}
}
What are you doing?
You export to csv, but still try to save it to a variable
You search twice
You add all members from ALL groups in TEST-OU to every group in domainB
You waste time on saving and reading data that you already have in memory
You search for the user-object to get SamAccountName when you already have something ten times better, the DN. Then you use that SamAccountName to find the DN.
Try this (untested):
$creds = Get-Credential
$Groups = Get-ADGroup -Properties Members -Filter * -SearchBase "OU=TEST,OU=Shop Print Groups,OU=User,OU=domain Groups,DC=domain,DC=com"
Foreach($G In $Groups)
{
#Display group members and group name
Write-Host $G.Name
Write-Host "-------------"
$G.Members
#Add members to domainB group
$G.Members |
Get-ADUser -Server fairfieldmfg.com |
ForEach-Object { Add-ADGroupMember -Server "domainB.com" -Identity $G.Name -Members $_ -Credential $creds -Verbose }
}
I used a foreach-loop to run the Add-ADGroupMember because it usually fails in the middle of a group of members if it finds on the already is a member, but if we add them one at a time you get around that (or you could do a search and exclude those already in the group).
You may want to add -ErrorAction SilentlyContinue to Add-ADGroupMember to ignore those errors when you know the script works as it should.
I need to search through all users in AD, find their attribute "mail" and in this attribute replace #hell.com to #heaven.com
I'm stuck at exporting and importing to csv...
Import-Module ActiveDirectory
get-aduser -Filter {samaccountname -like "gmaleev"} -properties * | Select-Object SamAccountName,mail | export-csv -NoTypeInformation d:\1.csv
$impfile = "d:\1.csv"
Import-CSV $impFile
foreach ($user in $users)
{
$sam = $user.samaccountname
$email = $user.mail
write-host "User $sam has mail $mail"
}
It doesn't work, why?
The current issue is that you are running a cmdlet to import the data but not saving it. Your ForEach cmdlet is not processing any data so you should have blank output except that of Import-CSV which should be outputing to console.
Also it seems redundant to export the data to import it again. I will presume that you have a reason for exporting it.
Import-Module ActiveDirectory
$impfile = "d:\1.csv"
$results = Get-AdUser -Filter {samaccountname -like "gmaleev"} -properties * | Select-Object SamAccountName,mail
$results | export-csv -NoTypeInformation d:\1.csv
$results | foreach ($user in $users){
$sam = $user.samaccountname
$email = $user.mail
write-host "User $sam has mail $mail"
}
This should address what you are showing. It will get the same data and save it to the variable $results. Export that data and then piping it to the ForEach to process
Your title suggets that you want to change user attributes. To do that you would need to use Set-Aduser. Depending on what your environment is this might not be the best way to manipulate email attributes.