I have a notepad list of 100 users. Normally I use the below script to get all the users within one OU but this time I have users from different OU and I have to search using Samaccountname.
clear
$UserInfoFile = New-Item -type file -force "C:\Scripts\UserInfo.txt"
"Login`tGivenname`tEmail" | Out-File $UserInfoFile -encoding ASCII
Import-CSV "C:\Scripts\OU.txt" | ForEach-Object {
$dn = $_.dn
$ObjFilter = "(&(objectCategory=User)(objectCategory=Person))"
$objSearch = New-Object System.DirectoryServices.DirectorySearcher
$objSearch.PageSize = 15000
$objSearch.Filter = $ObjFilter
$objSearch.SearchRoot = "LDAP://$dn"
$AllObj = $objSearch.FindAll()
foreach ($Obj in $AllObj)
{ $objItemS = $Obj.Properties
$Ssamaccountname = $objItemS.samaccountname
$SsamaccountnameGN = $objItemS.givenname
$SsamaccountnameSN = $objItemS.sn
$SsamaccountnameEN = $objItemS.mail
"$Ssamaccountname`t$SsamaccountnameGN`t$SsamaccountnameSN`t$SsamaccountnameEN" | Out-File $UserInfoFile -encoding ASCII -append
} # End of foreach
} # End of ForEach-Object
I am trying to use the list of samaccountname to get the name and email of those users. I am new to Powershell so the above script itself was a bit difficult for me to grasp and now I am on an even more difficult task.
Not sure if I understand your question correctly, but if you want to filter the user list by account names you could do something like this:
$accounts = Get-Content userlist.txt
...
$objSearch.FindAll() | ? {
$accounts -contains $_.Properties.sAMAccountName
} | % {
"{0}`t{1}`t{2}" -f ($_.Properties.givenname, $_.Properties.sn, $_.Properties.mail)
}
BTW, I'd recommend using the ActiveDirectory PowerShell module if possible. That will allow you to retrieve user accounts with a simple Get-ADUser, thus simplifying your code. The OU can be extracted from the user's distinguished name by splitting the dn at the first comma. Something like this:
$accounts = Get-Content userlist.txt
Get-ADUser * -Properties * | ? {
$accounts -contains $_.Properties.sAMAccountName
} | select #{n="ou";e={($_.distinguishedName -split ",", 2)[1]}}, mail, givenName, sn, homeDirectory
or like this:
Get-Content userlist.txt | Get-ADUser -Properties * |
select #{n="ou";e={($_.distinguishedName -split ",", 2)[1]}}, mail, givenName, sn, homeDirectory
Untested, though, since I don't have an AD at hand here.
I can't test it now but give this a try. You don't need to search AD if you know the user's DN. You can bind to it directly using the DN.
Import-CSV "C:\Scripts\OU.txt" | ForEach-Object {
$dn = $_.dn
$user = [adsi]"LDAP://$dn"
New-Object PSObject -Propertry #{
samaccountname = $user.Properties['samaccountname']
givenname = $user.Properties['givenname']
sn = $user.Properties['sn']
mail = $user.Properties['mail']
}
} | Export-Csv $UserInfoFile
Related
I am having the below code which is giving me the list of ad groups a specific user is part of
Get-Content "C:\Automation Scripts\users.txt" | Get-ADUser | ForEach{
$user = $_
$groups = Get-ADPrincipalGroupMembership $user
$groups | %{ New-Object PSObject -Property #{ User = $user.SamAccountName; Group = $_.SamAccountName } }
} | Export-Csv "C:\Automation Scripts\User_Groups.csv" -NoTypeInformation
It is working fine and I am getting the result, but the result is coming like below
"User","Group"
"A92M7202822","Domain Users"
"A92M7202822","A92GS-505-Central Team Data"
"A92M7202822","A00GRP-AdminAccounts"
"A92A7803642","Protected Users"
"A92A7803642","A00GRP-AdminAccounts"
I need the result in csv like below
User,Group
A92M7202822,"Domain Users
A92GS-505-Central Team Data
A00GRP-AdminAccounts
A92GS-505-Ids-Analytics-Share-A92DFS
A92GS-505-Data-DSICF-DEV
A92GS-505-Data-DSICF-PRD
CFRGRP-FS-FR4000_SSgt_CFIDS_RW"
A92A7803642,"Domain Users
Protected Users
A00GRP-AdminAccounts"
One cell for user and next cell should have all the groups in it.
Please let me know what changes need to be done for this
Try not to use New-Object, instead you can use PSCustomobject. Also, in your script you have used $user.samaccountname as values for both User and Groups. I have replaced group name value with name you may modify it.
$output = #()
$output += Get-Content "C:\Automation Scripts\users.txt" | Get-ADUser | ForEach{
$user = $_
$groups = Get-ADPrincipalGroupMembership $user
[PSCustomObject]#{
'User'= $user.SamAccountName
'Group' = $groups.Name
}
}
$output | Export-Csv "C:\Automation Scripts\User_Groups.csv" -NoTypeInformation
And another efficient way of doing this is like:
$users = Get-Content "C:\Automation Scripts\users.txt"
$output = foreach ($user in $users)
{
$groups = Get-ADPrincipalGroupMembership $user
foreach($group in $groups)
{
[PSCustomObject]#{
User = $user
Group = $group.Name
}
}
}
$output | Export-Csv "C:\Automation Scripts\User_Groups.csv" -NoTypeInformation
I am trying to export certain users' SamAccountName and EmployeeNumber from AD to csv. I only have EmployeeNumbers from HR in csv file and have to match it to SamAccountName in AD. My code does not work past 'if' condition. When I echo output there are same values for $a and $b all in String type. This file C:\temp\UsersToDisable.csv contains 4 and 3 number with column name "EmployeeNumber". This is what i came up with:
Import-Module ActiveDirectory
$Nums = Import-Csv "C:\powershell\EmployeeNumbers.csv"
$Users = Get-ADUser -Filter "*" -Property EmployeeNumber -SearchBase
"DC=my,DC=example,DC=com" | Where { $_.EmployeeNumber -ne $null } |
Select SamAccountName,EmployeeNumber
Foreach ($user in $Users)
{
$EmployeeNumber = $user.EmployeeNumber
foreach ($Line in $Nums)
{
$number = $line.EmployeeNumber
$a = $number.toString()
$b = $EmployeeNumber.toString()
echo $a $b
if($a -eq $b)
{
echo $user.SamAccountName
$result += ,(Get-ADUser $user.SamAccountName -Properties * | Select SamAccountName,employeeNumber)
}
}
} $result | Export-CSV "C:\temp\CCI_All_Users.csv" -NoTypeInformation
Thank you for any advice!
Loading all the users from the directory and then searching once again for the same user in the directory is not an ideal solution for performance reason.
Try the following code. For each number from the input file, search in the directory the user having the current EmployeeNumber, requesting to load the EmployeeNumber property. Then select only the desired properties and export them to CSV.
Import-Module ActiveDirectory
$Nums = Import-Csv "C:\powershell\EmployeeNumbers.csv"
$Nums | ForEach-Object {
Get-ADUser -LdapFilter "(EmployeeNumber=$_)" -Property EmployeeNumber -SearchBase "DC=my,DC=example,DC=com" |
Select-Object SamAccountName, EmployeeNumber
} | Export-CSV "C:\temp\CCI_All_Users.csv"
An alternative to Hazrelle's helpful answer, very similar but instead of looping over each line of the CSV, taking advantage of the LDAPFilter capabilities with the help of some string manipulation:
# This assumes there is a column named "EmployeeNumber" in the CSV
$Nums = (Import-Csv "C:\powershell\EmployeeNumbers.csv").EmployeeNumber
# Assuming Nums is an Array with Employee Numbers. i.e.:
# $Nums => A123,A456,A789
# $filter would look like this:
# (|(employeenumber=A123)(employeenumber=A456)(employeenumber=A789))
$filter = [string]::Format(
'(|(employeenumber={0}))',
($Nums -join ')(employeenumber=')
)
$params = #{
Properties = 'EmployeeNumber'
SearchBase = 'DC=my,DC=example,DC=com'
LDAPFilter = $filter
}
Get-ADUser #params | Select-Object samAccountName, EmployeeNumber |
Export-CSV "C:\temp\CCI_All_Users.csv" -NoTypeInformation
Worth mentioning, $result += ,(Get... is not recommended.
I am trying to create a csv file which contains the username and the group memberships from a list of usernames to a CSV file.
But the CSV file is formatted as below
******;"CN=Cal_ACABLHolidayCalendar_Editor
Username and group in 1 cell
$list = Get-Content c:\Tools\Powershell\ACA\userlist.txt
$list | `
%{
$user = $_;
get-aduser $user -Properties memberof | `
select -expand memberof | `
%{new-object PSObject -property #{User=$user;Group=$_;}} `
} |
export-csv –Path "C:\Tools\Powershell\ADUsers.csv" -Delimiter ‘;’ –NoTypeInformation -Encoding UTF8
How can I have the formatting as the first cell with the username and the below cells with the groups
Export-CSV is the wrong way to achieve your desired solution.
You should be better with something like this:
$excelfile = "C:\Daten\test.xlsx"
###Excel Parameter###
$excel = New-Object -COM "Excel.Application"
$excel.displayalerts = $false
$excel.visible = $false
$excel.usercontrol = $false
$Workbook=$excel.Workbooks.open($excelfile)
$Worksheet=$Workbook.Worksheets.Item(1)
$Worksheet.Activate() | Out-null
$x = 1
$y = 1
$list = get-content c:\daten\list.txt
foreach ($user in $list){
$groups = (get-aduser $user -Properties memberof | select -expand memberof | %{new-object PSObject -property #{User=$user;Group=$_;}} | select -ExpandProperty Group)
$z = $groups.count
$excel.cells.item($y,$x) = $user
for ($i = 2; $i -le $groups.count+1; $i++)
{
$excel.cells.item($i,$x) = $groups[$i]
}
$x=$x+1
}
$Workbook.Save()
$Workbook.Close()
get-process *excel* | kill -Force
Its not 100% correct. Something is wrong with the counter of the username. First user works good though.
I have the below working script that checks if a large list of users in a CSV file are a member of an AD group and writes the results to results.csv.
Not sure how to convert the script so I can change $group = "InfraLite" to $group = DC .\List_Of_AD_Groups.CSV.
So the script doesn't just return matches for one AD group but so it returns matches for the 80 AD groups contained in the List_of_AD_groups.csv also. Writing a YES/NO for each AD group in a new column in the CSV (or if that's not possible creating a seperate .csv file for each group with results would do also.
I could do this manually by changing the value of $group and export file name, and re-running the script 80 times but must be a quick was with PS to do this?
e.g. results.csv:
NAME AD_GROUP1 AD_GROUP2 AD_GROUP80 etc etc.
user1 yes no yes
user2 no no yes
user3 no yes no
echo "UserName`InfraLite" >> results.csv
$users = GC .\user_list.csv
$group = "InfraLite"
$members = Get-ADGroupMember -Identity $group -Recursive |
Select -ExpandProperty SAMAccountName
foreach ($user in $users) {
if ($members -contains $user) {
echo "$user $group`tYes" >> results.csv
} else {
echo "$user`tNo" >> results.csv
}
}
I played with this for a while, and I think I found a way to get you exactly what you were after.
I think Ansgar was on the right path, but I couldn't quite get it to do what you were after. He mentioned that he didn't access to an AD environment at the time of writing.
Here is what I came up with:
$UserArray = Get-Content 'C:\Temp\Users.txt'
$GroupArray = Get-Content 'C:\Temp\Groups.txt'
$OutputFile = 'C:\Temp\Something.csv'
# Setting up a hashtable for later use
$UserHash = New-Object -TypeName System.Collections.Hashtable
# Outer loop to add users and membership to UserHash
$UserArray | ForEach-Object{
$UserInfo = Get-ADUser $_ -Properties MemberOf
# Strips the LPAP syntax to just the SAMAccountName of the group
$Memberships = $UserInfo.MemberOf | ForEach-Object{
($_.Split(',')[0]).replace('CN=','')
}
#Adding the User=Membership pair to the Hash
$UserHash.Add($_,$Memberships)
}
# Outer loop to create an object per user
$Results = $UserArray | ForEach-Object{
# First create a simple object
$User = New-Object -TypeName PSCustomObject -Property #{
Name = $_
}
# Dynamically add members to the object, based on the $GroupArray
$GroupArray | ForEach-Object {
#Checking $UserHash to see if group shows up in user's membership list
$UserIsMember = $UserHash.($User.Name) -contains $_
#Adding property to object, and value
$User | Add-Member -MemberType NoteProperty -Name $_ -Value $UserIsMember
}
#Returning the object to the variable
Return $User
}
#Convert the objects to a CSV, then output them
$Results | ConvertTo-CSV -NoTypeInformation | Out-File $OutputFile
Hopefully that all makes sense. I commented as much of it as I could. It would be very simple to convert to using ADSI if you didn't have RSAT installed on whatever machine you're running this on. If you need that let me know, and I'll make some quick modifications.
I've also tossed a slightly modified version of this in a Gist for later reference.
The trivial solution to your problem would be to wrap your existing code in another loop and create an output file for each group:
$groups = Get-Content 'C:\groups.txt'
foreach ($group in $groups) {
$members = Get-ADGroupMember ...
...
}
A more elegant approach would be to create a group mapping template, clone it for each user, and fill the copy with the user's group memberships. Something like this should work:
$template = #{}
Get-Content 'C:\groups.txt' | ForEach-Object {
$template[$_] = $false
}
$groups = #{}
Get-ADGroup -Filter * | ForEach-Object {
$groups[$_.DistinguishedName] = $_.Name
}
Get-ADUser -Filter * -Properties MemberOf | ForEach-Object {
$groupmap = $template.Clone()
$_.MemberOf |
ForEach-Object { $groups[$_] } |
Where-Object { $groupmap.ContainsKey($_) } |
ForEach-Object { $groupmap[$_] = $true }
New-Object -Type PSObject -Property $groupmap
} | Export-Csv 'C:\user_group_mapping.csv' -NoType
I am trying to create an "initial" text file that will hold a script run of all users + department + direct reports. My next step after making this file is to create another file the same way but compare it to the original to see if the department for the users ever changed. (not sure yet how to compare the department value just yet)
My current issue is that the department, even though the process is identical to another program I have made in the past, won't print it. Furthermore, when it prints my direct reports it prints only the first one with the whole extension of CN=..., OU=... etc.
I want it to print this way:
username | Department(extensionAttribute14) | Direct Reports (as a single string)
we38432 | IT-Security | cm03456: 04555a: ....etc
My original script used this code for department:
$deps = Get-Aduser -filter {name -like *} -Properties name, extensionAttribute14 | Select name, extensionAttribute14 | Export-CSV $listing -notypeinformation
and this worked. I tried the {name -like *} but that gave me errors in my current program. I know the Export-CSV makes it work but I can't use this format anymore.
for the direct reports my original was this:
foreach ($ID in $directReports){
if ($ID -ne $Null){
$directreports = get-aduser $ID
$directreports.name | Out-File $output -Append
}
This code printed line by line the direct reports but I want them all listed in the same excel cell when I send it there.
I have printed a listing of all the members in the past using ":" and it worked but it is not the case with the direct reports listing. I just get errors when I use this format from my other program:
foreach ($member in $empty.members){
$string = $member.substring(3,$member.indexof(",")-3)
$members = $members + ":" + $string
}
I hope someone can help me with my two issues.
Import-Module ActiveDirectory
$documentOld = "C:\Temp\Old_Supervisor_list_mo_yyyy.txt"
Clear-Content $documentOld
$Header = `
"User ID" <#+ "|" + `
"Department" + "|" + `
"Direct Reports"#>
$Header | Out-File $documentOld -Append
$Users = Get-AdUser -Filter * -Properties name, Enabled, Manager, extensionAttribute14 | Select Enabled, name, Manager, extensionAttribute14
foreach ($user in $Users){
if ($user.enabled –eq $true) {
$name = $user.name
$directReports = Get-ADUser -Identity $name -Properties directreports | Select -ExpandProperty directreports
$department = $user.extensionAttribute14
foreach ($ID in $directReports){
if ($ID -ne $Null){
$directreports = get-aduser $ID
# $string = $directreports + ":"
}#end if $ID
}#end foreach $ID
$listing = `
$name + "|" + $deparment + "|" + $directreports#$string
$listing | Out-File $documentOld -Append
}# end if
}# end foreach $user
Let see if we can make this a little easier and efficient.
Import-Module ActiveDirectory
$documentOld = "C:\Temp\Old_Supervisor_list_mo_yyyy.txt"
$Users = Get-AdUser -Filter * -Properties name,Enabled,Manager,extensionAttribute14 | Where-Object{$_.Enabled}
$Users | ForEach-Object{
$props = #{
Name = $_.Name
Department = $_.extensionAttribute14
DirectReports = ($_.Manager | Where-Object{$_} | ForEach-Object{Get-Aduser $_ | Select-object -ExpandProperty Name}) -join ":"
}
New-Object -TypeName psobject -Property $props
} | Select-Object Name,Department,DirectReports | Export-CSV -Delimiter "|" -NoTypeInformation -Path $documentOld
First we get all the users from your directory with Get-AdUser -Filter * taking all the properties outside the norm that we want. Since you just wanted accounts that are enabled we filter those out now with Where-Object{$_.Enabled}.
The fun part is creating the custom object array ( which is necessary for input for Export-CSV). Create a small hashtable called $props where we set the properties by their friendly names. The special one being DirectReports where we take all the users manager DN's ( Assuming they have one where is what Where-Object{$_} does by filtering out nulls/empty strings.) and use Get-Aduser to get there names. Since you could have more than one manager an array is most likely returned we use -join to ensure only a single string is given for the DirectReports property. That property collection is created for every user and it is then used to create a New-Object which is sent to the output stream.
The Select-Object that follows is just to ensure the order of columns in the CSV that is created. No need for making a CSV file with lots of Out-Files when Export-CSV and -Delimiter "|" will do the hard work for you.