What I need to do is to export specific AD users and some of their properties to a CSV file. What I need to have there is some of the default properties like Name, SamAccountName, Enabled and some custom ones: businesscategory, extensionAttribute9 etc.
I'm struggling with my if - else statements, as they seem to not be comparing employeenumber to $null
$name = Read-Host -Prompt "Please enter the name for output file."
$filename = $name+".csv"
$domain = #('DOMAIN1','DOMAIN2','DOMAIN3','DOMAIN4')
$result = foreach ($item in $domain) {
Get-ADUser -server $item -Properties businesscategory, extensionAttribute4,
extensionAttribute9, extensionAttribute13, employeenumber, Enabled -ResultPageSize 100 -Filter *
if (($null -ne $_.employeenumber) -and ($_.employeenumber -notlike '*svc*')) {
Select-Object Name,
SamAccountName,
UserPrincipalName,
#{n="businesscategory"; e={$_.businesscategory -join ", "}},
#{n="extensionAttribute4";e={$_.extensionAttribute4 -join ", "}},
#{n="extensionAttribute9";e={$_.extensionAttribute9 -join ", "}},
#{n="extensionAttribute13";e={$_.extensionAttribute13 -join ", "}},
DistinguishedName, employeenumber, Enabled
} else { (...)
The above is part of my code where it should enter into first if. It does that, but it exports all accounts, whether employeenumber is present or not.
Another issue is that the exported CSV doesn't contain columns created from custom attributes, instead it shows some other properties that I did not ask for.
This used to work fine if I used Where-Object instead of if - else and checked the values like below:
Where-Object {
($_.SamAccountName -notlike '*proprietary*') -and
($_.UserPrincipalName -notlike '*proprietary*') -and
($_.SamAccountName -notlike '*mailbox*') -and (...)
Unfortunately I need to use if - else to make more complex comparisons and selections, but can't figure it out
The problem is in this line:
$result = foreach ($item in $domain) {
Get-ADUser -server $item -Properties ... # => not assigned to any variable
Then in this line:
if (($null -ne $_.employeenumber) -and ($_.employeenumber -notlike '*svc*')) {
Since $_ doesn't exist, you are comparing something like:
$null -ne $null -and $null -notlike '*svc*'
Which will always be $false. It's also worth mentioning that this is a foreach loop, different from ForEach-Object, the automatic variable $_ ($PSItem) doesn't mean anything here.
The next problem comes when using Select-Object as the beginning of the statement, there is no object being piped to it.
Select-Object Name, SamAccountName, UserPrincipalName, ...
In this case, the if condition could be removed completely with some LDAP Filtering:
# employee number is not `$null` AND employee number is not like `*svc*`
-LDAPFilter "(&(employeenumber=*)(!employeenumber=*svc*))"
The code would look like this:
$name = Read-Host -Prompt "Please enter the name for output file."
$filename = $name + ".csv" # Consider using `$HOME` here, or an absolute Path
$param = #{
LDAPFilter = "(&(employeenumber=*)(!employeenumber=*svc*))"
ResultPageSize = 100
Properties = #(
'businesscategory'
'extensionAttribute4'
'extensionAttribute9'
'extensionAttribute13'
'employeenumber'
)
}
'DOMAIN1','DOMAIN2','DOMAIN3','DOMAIN4' | ForEach-Object {
$param['Server'] = $_
foreach($user in Get-ADUser #param) {
[pscustomobject]#{
Name = $user.Name
SamAccountName = $user.SamAccountName
UserPrincipalName = $user.UserPrincipalName
BusinessCategory = $user.businesscategory -join ", "
extensionAttribute4 = $user.extensionAttribute4 -join ", "
extensionAttribute9 = $user.extensionAttribute9 -join ", "
extensionAttribute13 = $user.extensionAttribute13 -join ", "
DistinguishedName = $user.DistinguishedName
employeenumber = $user.employeenumber
Enabled = $user.Enabled
Domain = $_ # Adding the Domain of this user here
}
}
} | Export-Csv $filename -NoTypeInformation
Related
I'm having issues trying to have my script read and apply the AD groups with my script. Right now, it's just posting what's in my script, but I would like to have the script read what's in my .txt file and use it with the rest of my script.
$filePath = "C:\Users\UserName\Downloads\ADGroupList.txt"
Get-Content -Path $filePath
Get-ADGroup -filter {Name -like "$filePath" } -Properties managedBy |
ForEach-Object {
$managedBy = $_.managedBy;
if ($managedBy -ne $null)
{
$manager = (get-aduser -Identity $managedBy -Properties emailAddress);
$managerName = $manager.Name;
$managerEmail = $manager.emailAddress;
}
else
{
$managerName = 'N/A';
$managerEmail = 'N/A';
}
Write-Output $_; } |
Select-Object #{n='Group Name';e={$_.Name}}, #{n='Managed By Name';e={$managerName}}, #{n='Managed By Email';e={$managerEmail}}
Export-Csv -Path "C:\Users\UserName\Documents\ADGroupManagerList.csv"
The easiest way is to loop over the group names you have in the ADGroupList.txt file (assuming this is a list of group names, each on a separate line)
$filePath = "C:\Users\UserName\Downloads\ADGroupList.txt"
# just loop over the group names you have in the text file and capture the output
$result = Get-Content -Path $filePath | ForEach-Object {
$group = Get-ADGroup -Filter "Name -like '$_'" -Properties managedBy
# create an object pre filled in when no manager was found
$obj = [PsCustomObject]#{
'Group Name' = $group.Name
'Managed By Name' = 'N/A'
'Managed By Email' = 'N/A'
}
# test if the ManagedBy is populated
if (-not [string]::IsNullOrWhiteSpace($group.ManagedBy)) {
# try to use the DN in property ManagedBy to find the manager
try {
$manager = Get-ADUser -Identity $group.ManagedBy -Properties EmailAddress -ErrorAction Stop
$obj.'Managed By Name' = $manager.Name
$obj.'Managed By Email' = $manager.EmailAddress
}
catch {
Write-Warning "No user found for '$($group.ManagedBy)'.. Please check AD."
}
}
# output the object so it gets collected in variable $result
$obj
}
# write the file
$result | Export-Csv -Path "C:\Users\UserName\Documents\ADGroupManagerList.csv" -NoTypeInformation
For workaround you can use this powershell script to get the mangedBy of groups.
Get-ADGroup -filter * -Properties managedBy |
ForEach-Object {
$managedBy = $_.managedBy;
if ($managedBy -ne $null)
{
$manager = (get-aduser -Identity $managedBy -Properties emailAddress);
$managerName = $manager.Name;
$managerEmail = $manager.emailAddress;
}
else
{
$managerName = 'N/A';
$managerEmail = 'N/A';
}
Write-Output $_; } |
Select-Object #{n='Group Name';e={$_.Name}}, #{n='Managed By Name';e={$managerName}}, #{n='Managed By Email';e={$managerEmail}}
My goal is to dump a CSV of our AD groups, their members, and whether those member objects are enabled, but I'm running into a strange (probably self-inflicted) issue, wherein a Foreach-Object loop is behaving unexpectedly.
The output almost works. It dumps a CSV file. The file has rows for each group, populated with the correct group-related data, and the right number of rows, following the number of group members. However, group member properties on those rows is repeated, showing the same user data over and over for each groupmember result, apparently following the properties of the last returned object from Get-ADGroupMember.
To try to diagnose the issue, I added the line Write-Host $GroupMember.Name -ForegroundColor Gray. This is how I knew the entries in the CSV were the last-returned results for each group. Confusingly, the console correctly echoes each group member's display name.
I'm assuming there's some kind of logic error at work here, but I have had no luck finding it. Any help would be appreciated!
clear
Import-Module ActiveDirectory
# CONFIG ========================================
# Plant Number OU to scan. Used in $CSV and in Get-ADComputer's search base.
$PlantNumber = "1234"
# FQDN of DC you want to query against. Used by the Get-AD* commands.
$ServerName = "server.com"
# Output directory for the CSV. Default is [Environment]::GetFolderPath("Desktop"). Used in $CSV. NOTE: If setting up as an automated task, change this to a more sensible place!
$OutputDir = [Environment]::GetFolderPath("Desktop")
# CSV Output string. Default is "$OutputDir\$PlantNumber"+"-ComputersByOS_"+"$(get-date -f yyyy-MM-dd).csv" (+'s used due to underscores in name)
$CSV = "$OutputDir\$PlantNumber"+"GroupMembers_"+"$(get-date -f yyyy-MM-dd).csv"
# Create empty array for storing collated results
$collectionTable = #()
# Get AD groups, return limited properties
Get-AdGroup -filter * -Property Name, SamAccountName, Description, GroupScope -SearchBase "OU=Security Groups,OU=$PlantNumber,OU=Plants,DC=SERVER,DC=COM" -server $ServerName | Select SamAccountName, Description, GroupScope | Foreach-Object {
Write-Host "Querying" $_.SamAccountName "..."
#Initialize $collectionRow, providing the columns we want to collate
$collectionRow = "" | Select GroupName, GroupScope, GroupDesc, MemberObjectClass, MemberName, MemberDisplayName, Enabled
# Populate Group-level collectionRow properties
$collectionRow.GroupName = $_.SamAccountName
$collectionRow.GroupDesc = $_.Description
$collectionRow.GroupScope = $_.GroupScope
# Process group members
Get-ADGroupMember -Identity ($collectionRow.GroupName) -Server $ServerName -Recursive | ForEach-Object {
$GroupMember = $_
# Echo member name to console
Write-Host $GroupMember.Name -ForegroundColor Gray
$collectionRow.MemberName = $GroupMember.SamAccountName
$collectionRow.MemberDisplayName = $GroupMember.name
$collectionRow.MemberObjectClass = $GroupMember.ObjectClass
# If the member object is a user, collect some additional data
If ($collectionRow.MemberObjectClass -eq "user") {
Try {
$collectionRow.Enabled = (Get-ADUser $GroupMember.SamAccountName -Property Enabled -ErrorAction Stop).Enabled
If ($collectionRow.Enabled -eq "TRUE") {$collectionTable += $collectionRow}
}
Catch {
$collectionRow.Enabled = "ERROR"
$collectionTable += $collectionRow
}
}
}
}
Write-Host "`n"
# Attempt to save results to CSV. If an error occurs, alert the user and try again.
$ExportSuccess = 'false'
while ($ExportSuccess -eq 'false') {
Try
{
# Export results to $CSV
$collectionTable| Export-csv $CSV -NoTypeInformation -ErrorAction Stop
# If the above command is successful, the rest of the Try section will execute. If not, Catch is triggered instead.
$ExportSuccess = 'true'
Write-Host "`nProcessing complete. Results output to"$CSV
}
Catch
{
Write-Host "Error writing to"$CSV"!" -ForegroundColor Yellow
Read-Host -Prompt "Ensure the file is not open, then press any key to try again"
}
}
There are many things from your code you need to fix, I'll just point out the most important ones:
Don't use #() and +=
You keep using 'True' and 'False' which are strings, PowerShell booleans are $true and $false.
There is also too much redundant code. Also ForEach-Object is slow, if your groups have many members and since you're using -Recursive it's better to use a fast loop instead.
$PlantNumber = "1234"
$ServerName = "server.com"
$OutputDir = [Environment]::GetFolderPath("Desktop")
$fileName = "${PlantNumber}GroupMembers_$(Get-Date -f yyyy-MM-dd).csv"
$CSV = Join-Path $OutputDir -ChildPath $fileName
# $collectionTable = #() => Don't do this to collect results, ever
$adGroupParams = #{
# Name and SAM are default, no need to add them
Properties = 'Description', 'GroupScope'
SearchBase = "OU=Security Groups,OU=$PlantNumber,OU=Plants,DC=SERVER,DC=COM"
Server = $ServerName
Filter = '*'
}
# Get AD groups, return limited properties
$collectionTable = foreach($group in Get-AdGroup #adGroupParams)
{
Write-Host "Querying $($group.samAccountName)..."
foreach($member in Get-ADGroupMember $group -Server $ServerName -Recursive)
{
# if this member is 'user' the Enabled property
# will be a bool ($true / $false) else it will be $null
$enabled = if($member.ObjectClass -eq 'User')
{
(Get-ADUser $member).Enabled
}
[pscustomobject]#{
GroupName = $group.SamAccountName
GroupDesc = $group.Description
GroupScope = $group.GroupScope
MemberName = $member.SamAccountName
MemberDisplayName = $member.Name
MemberObjectClass = $member.ObjectClass
Enabled = $enabled
}
}
}
as i understand, you need to export list of groups with members to a csv file and know if member accounts are enabled or not, if this what you want, you can check the below code
$output = #()
Import-Module ActiveDirectory
$ServerName = "server.com"
$PlantNumber = "1234"
$OutputDir = [Environment]::GetFolderPath("Desktop")
$CSV = "$OutputDir\$PlantNumber"+"GroupMembers_"+"$(get-date -f yyyy-MM-dd).csv"
$groups = Get-AdGroup -filter * -Property Description -SearchBase "OU=Security Groups,OU=$PlantNumber,OU=Plants,DC=SERVER,DC=COM" -server $ServerName
foreach ($group in $groups){
$members = Get-ADGroupMember -Identity $group.SamAccountName -Recursive
foreach ($member in $members){
$output += [pscustomobject]#{
GroupName = $group.SamAccountName
GroupDesc = $group.Description
GroupScope = $group.GroupScope
MemberName = $member.samaccountname
MemberDisplayName = $member.Name
MemberObjectClass = $member.ObjectClass
Enabled = $(Get-ADUser -Identity $member.samaccountname).enabled
}
}
}
$output | Export-Csv $CSV -NoTypeInformation
I am explicitly NOT refering your code. I'd just like to show how I would approach this task. I hope it'll help you anyway.
$Server = 'Server01.contoso.com'
$SearchBase = 'OU=BaseOU,DC=contoso,DC=com'
$CSVOutputPath = '... CSV path '
$ADGroupList = Get-ADGroup -Filter * -Properties Description -SearchBase $SearchBase -Server $Server
$ADUserList = Get-ADUser -Filter * -Properties Description -SearchBase $SearchBase -Server $Server
$Result =
foreach ($ADGroup in $ADGroupList) {
$ADGroupMemberList = Get-ADGroupMember -Identity $ADGroup.sAMAccountName -Recursive
foreach ($ADGroupmember in $ADGroupMemberList) {
$ADUser = $ADUserList | Where-Object -Property sAMAccountName -EQ -Value $ADGroupmember.sAMAccountName
[PSCustomObject]#{
ADGroupName = $ADGroup.Name
ADGroupDescription = $ADGroup.Description
ADGroupMemberName = $ADUser.Name
ADGroupMemberSamAccountName = $ADUser.sAMAccountName
ADGroupMemberDescription = $ADUser.Description
ADGroupMemberStatus = if ($ADUser.Enabled) { 'enabled' }else { 'diabled' }
}
}
}
$Result |
Export-Csv -Path $CSVOutputPath -NoTypeInformation -Delimiter ',' -Encoding utf8
It'll output only the a few properties but I hope you get the idea.
BTW: The properties DistinguishedName, Enabled, GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName are included in the default return set of Get-ADUser and the properties DistinguishedName, GroupCategory, GroupScope, Name, ObjectClass, ObjectGUID, SamAccountName, SID are included in the default return set of Get-ADGroup. You don't need to query them explicitly with the parameter -Properties.
First script I have tried to put together. Im trying to get a new variable with ad user name and ad computer by comparing user name property and description properties. I don't know how to pull the properties I want into the new variables based on a compare-object or match. The description property has a setup of username - ######## numbers very.
Variables used (date tell expire)
$SevenDayWarnDate, $ThreeDayWarnDate, $OneDayWarnDate
AD user
$7, $3, $1 -properties "Name", "PasswordExpiry
AD computer
$comp "Name", "Description"
I was then going to make a pop up on user computer based on expiring passwords.
Below is what I was trying to do but im not sure if the needed information was passed as computer filed comes back empty.
$SevenDayWarnDate = (get-date).adddays(7).ToLongDateString()
$7= Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False -and PasswordLastSet -gt 0 } `
-Properties "Name", "msDS-UserPasswordExpiryTimeComputed" | Select-Object -Property "Name", `
#{Name = "PasswordExpiry"; Expression = {[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed").tolongdatestring() }} `
|Where-object -Property PasswordExpiry -EQ $SevenDayWarnDate
$comp = Get-Adcomputer -Filter {Enabled -eq $True} -SearchBase "OU=,DC=" -properties "Name", "Description" `
| Select-Object -Property "Name", "Description"
Compare-Object -ReferenceObject $7 -DifferenceObject $comp -IncludeEqual -ExcludeDifferent -PassThru |
ForEach-Object {
[PSCustomObject]#{
Name = $_.name
Computer = ($comp.name | Where-Object Description -match $_.name).Directory
}
}
Working code based on Santiago Squarzon below.
$dayArray= #()
$dayArray=#(7,3,1)
foreach ($day in $dayArray)
{
$SevenDayWarnDate = (get-date).adddays($day).ToLongDateString()
$filter = "Enabled -eq '$True' -and PasswordNeverExpires -eq '$False' -and PasswordLastSet -gt '0'"
$computerArray= #()
$users = Get-ADUser -Filter $filter -Properties "Name", "msDS-UserPasswordExpiryTimeComputed" |
Select-Object Name, #{
Name = "PasswordExpiry"
Expression =
{
[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed").tolongdatestring()
}
} | Where-object -Property PasswordExpiry -EQ $SevenDayWarnDate
# => It might be better to use:
# PasswordExpiry -ge [datetime]::Now -and PasswordExpiry -le $sevenDayWarnDate
# Find the computers each user is using
$result = foreach($user in $users)
{
$temp=$user.Name
if ($comp = Get-ADComputer -Filter "Description -like '*$temp*'" -Properties Description)
{
[PSCustomObject]#{
Name = $user.Name
PasswordExpiry = $user.PasswordExpiry
ComputerName = $comp.Name
ComputerDescription = $comp.Description
}
$tmpArray= #()
$tmpArray= $comp.Name.Split(" ")
foreach($item in $tmparray)
{
$computerArray += $item
}
$tmpArray = $Null
# }
}
continue
}
foreach($computer in $computerArray)
$tmpMessage =
$tmpMessageTitle =
{Send-RDUserMessage -HostServer $env:COMPUTERNAME -UnifiedSessionID 1 -MessageTitle $tmpMessageTitle -MessageBody $tmpMessage
}
$result | Format-Table
}
Based on the comments and the code in question, I'm guessing this is what you're looking for. There is no need to use Compare-Object, you can simply query Active Directory to get the user's computer based on the Description property.
$SevenDayWarnDate = [datetime]::Now.AddDays(7)
$filter = "Enabled -eq '$True' -and PasswordNeverExpires -eq '$False' -and PasswordLastSet -gt '0'"
$users = Get-ADUser -Filter $filter -Properties "Name", "msDS-UserPasswordExpiryTimeComputed" |
Select-Object Name, #{
Name = "PasswordExpiry"
Expression = {
[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")
}
} | Where-object -Property PasswordExpiry -EQ $SevenDayWarnDate
# => It might be better to use:
# {$_.PasswordExpiry -ge [datetime]::Now -and $_.PasswordExpiry -le $sevenDayWarnDate}
# Find the computers each user is using
$result = foreach($user in $users)
{
if($comp = Get-ADComputer -LDAPFilter "(description=$($user.Name))" -Properties Description)
{
[PSCustomObject]#{
Name = $user.Name
PasswordExpiry = $user.PasswordExpiry
ComputerName = $comp.Name
ComputerDescription = $comp.Description
}
continue
}
Write-Host "No computer was found for User: $($user.Name)"
}
$result | Format-Table
Hi I have a script that will partially work if I write "write-host" but doesn't work at all when exporting the information to a text file. I want to find the user ID's description, name, displayname and manager. Please help me understand why it isn't working.
Import-Module ActiveDirectory
$document = "C:\Temp\ADupdate yyyy.txt"
Clear-Content $document
<#
-ne = not equal CN=xxpc37254,OU=Standard,OU=Users,OU=Corporate,DC=we,DC=dirsrv
-eq = equal
-lt = less than
-gt = greater than
-ge = greater than or qual to
-le = less than or equal to
#>
$Header = `
"User ID" + "|" + `
"Display Name" + "|" + `
Description" + "|" + `
"ID Owner" + "|" + `
"ID Owner Name"
#Write out the header
$Header | Out-File $document -Append
#$Users = Get-ADUser -Filter {name -like "xxpc*" -or name -like "xxmd*"} - SearchBase "OU=Corporate,DC=we,DC=dirsrv,DC=com" -Properties name, displayname, description, manager
$Users = Get-ADUser -filter {name -like "xxpc*" -or name -like "xxmd*"} -Properties name, displayname, description, manager
foreach ($User in $Users)
{
#manager missing
if ($Users.Manager -eq $null) {
$owner = "MISSING"
$ownerid = "MISSING"
$ownername = "MISSING"
} else {
#grab the manager's name, surname, and department
$owner = Get-ADUser ($userid.Manager) -Properties GivenName, Surname, Department
$ownerid = $owner.Name
$ownername = $owner.Surname + "." + $owner.GivenName
}
$listing = `
$Users.Name + "|" + `
$Users.DisplayName + "|" + `
$Users.Description + "|" + `
$ownerid + "|" + `
$ownername
$listing | Out-File $document -Append
Ok. The reason why it's not working is probably because the if statement inside the foreach is wrong. You should use $user inside the foreach, not $users like you use here.
That being said, you should read up on creating custom objects, and get the data you want, create a custom object and write that to the pipeline. That way you can use the output in a lot of different ways, whether that is to write to a text file, a csv file, xml or just to the screen.
I have a list of users full name that I'd like to get their SAMaccount name but when I run my code I get no results. Anyone have any ideas?
$users = Get-Content C:\users\admin\Desktop\move.txt
foreach ($user in $users){
Get-ADUser -Filter {Name -eq "$user"} |Select-Object name, samaccountname
}
It could be that $user is null inside the script block. Try to use double quotes instead of braces and put the variable in single quotes to make the valid query (name contain spaces):
Get-ADUser -Filter "Name -eq '$user'" | Select-Object name, samaccountname
Here is a powershell script that should work for you. You'll want to go to the link to read the fine details, http://wbarena.com/2015/01/powershell-find-ad-user-full-name.html.
Import-Module ActiveDirectory
$aResults = #()
$List = Get-Content “.\List.txt”
ForEach($Item in $List){
$Item = $Item.Trim()
$User = Get-ADUser -Filter{displayName -like $Item -and SamAccountName -notlike “a-*” -and Enabled -eq $True} -Properties SamAccountName, GivenName, Surname, telephoneNumber, mail
$hItemDetails = New-Object -TypeName psobject -Property #{
FullName = $Item
UserName = $User.SamAccountName
Email = $User.mail
Tel = $User.telephoneNumber
}
#Add data to array
$aResults += $hItemDetails
}
$aResults | Export-CSV “.\Results.csv”
Use first and last name separately.
foreach ($user in $users){
$SplitName = -split $user
Get-ADUser -Filter {(GivenName -eq $SplitName[0]) -and (Surname -eq $splitName[1])} |Select-Object name, samaccountname
}