Get-AdUser no acepting variable - powershell

im trying to pull out all the information regarding my domain admin adminsitrators
#set domains we are going to query
$domains = 'mydomainname.com'
#first here i bring the sam accounts names
Foreach ($domain in $domains)
{
$OUTPUT =Get-AdGroupMember -identity “Domain Admins” -recursive -server $domain |
Select-Object -Property samAccountName|
Select samAccountName;
$Outputs +=$OUTPUT;
$OUTPUT |Export-CSV "C:\File\$($domain).csv" -NoTypeInformation ;
}
$OUTPUT #this print the sam accounts
#here is the problem
Foreach ($user in $OUTPUT)
{
$Users2 =Get-ADUser -Filter "SamAccountName -like '$OUTPUT'" -Properties *
$USER3 +=$Users2;
$Users2 |Export-CSV "C:\File\$($domain)Userpop.csv" -NoTypeInformation ;
}

I think this is a problem with your filter. Try changing that line as follows:
Get-ADUser -Filter " SamAccountName -like `"$($user.samaccountname)`" " -Properties *
It can't be $OUTPUT as that's an array. Your loop variable is $user which is an object so you need the .samaccountname property. The filter needs a string with the -like matching a quoted string, so you need `" to pass the quote through to the final string.
Your CSV output of $user2 may not be what you expect either as each object is output to the same file. Perhaps you mean to have a -Append or write them to different files?
You'll probably want to reset $user3 as well. Perhaps add $user3 = #() before that loop.

You should always try to avoid adding to arrays with $array += $something, because that means the entire array gets rebuild in memory, costing time and resources.
Also, I would advise using more descriptive variable names, so the code will still be understandable after some time.
Then, because you are getting info from different domains, it is important to store the domain name in the first loop together with the samaccount names, so you can use these as -Server parameter in the second loop on Get-ADUser
Try
#set domains we are going to query
$domains = #('mydomainname.com') # since there is only one domain listed, use #() to force it into an array
$domainsAndAdmins = foreach ($domain in $domains) {
# store the SamAccountNames for this domain as objects in an array
$admins = Get-AdGroupMember -Identity 'Domain Admins' -Recursive -Server $domain |
Select-Object -Property SamAccountName
# export this to csv file
$outFile = 'C:\File\{0}.csv' -f $domain
$admins | Export-Csv $outFile -NoTypeInformation
# output an object with both the domain and the array of SamAccountNames
# this will be captured in variable $domainsAndAdmins
[PsCustomObject]#{Domain = $domain; Admins = $admins.SamAccountName }
}
# output on screen
$domainsAndAdmins | Format-Table -AutoSize
# will result in something like
#
# Domain Admins
# ------ ------
# mydomainname.com {jdoe, jbloggs, mpimentel}
# myseconddomainname.com {jdoe, mpimentel}
# next get ALL (?) properties from the users we found
$domainsAndAdmins | ForEach-Object {
$domain = $_.Domain
$result = foreach ($user in $_.Admins) {
Get-ADUser -Filter "SamAccountName -like '$user'" -Server $domain -Properties * -ErrorAction SilentlyContinue
}
$outFile = 'C:\File\{0}_Userpop.csv' -f $domain
$result | Export-Csv $outFile -NoTypeInformation
}

Related

Powershell Script to pull all AD users and last time password was changed and date of change

I am attempting to create a script to extract all AD users from 3 different domains with their last logon date as well as the last time they changed their password and extract it to a CSV. I have the following code:
$data = #()
$domains = "example.exa.com "," example.com",” ex.example.com”
foreach($domain in $domains)
{
$data | Foreach-Object –Process { get-aduser -filter * -server $domains -properties passwordlastset,lastlogondate | select name, passwordlastset,lastlogondate }
$data | Export-csv –Path C:\passwords.csv -notypeinformation
The following code does not produce any errors, but it runs infinitely with no results. Can anyone help with what I am doing wrong?
There are quite a few things wrong with your code:
You define the three domains with leading or trailing spaces
You loop through the $domains using iterating variable $domain, but in the loop you are using the complete array $domains
$data is defined as (empty) array on top, but still you use it to loop through its elements (which aren't there) by piping to Foreach-Object
Try to avoid adding items to an array with += as it needs to reconstruct the entire array in memory on every addition
Try:
$domains = 'example.exa.com','example.com','ex.example.com'
$data = foreach($domain in $domains) {
# just output the objects here, so they will be collected for you in variable $data
Get-ADUser -Filter * -Server $domain -Properties PasswordLastSet, LastLogonDate | Select-Object Name, PasswordLastSet, LastLogonDate
}
$data | Export-csv –Path 'C:\passwords.csv' -NoTypeInformation

Importing CSV splits certain lines

I have a fairly simple script that needs to check around 20,000 AD Groups for their membership count. That all works fine, I can take the list of groups run it through the script and for the most entries it works fine. However I was getting some errors that I couldn't figure out and hopefully someone here can point me in the right direction.
I am using the DN of the object to query AD and for around 10% it fails, but when I copy the DN from the file, paste it into a command window and run the command manually it works fine. Some more checking and it seems that when I read an offending line into my variable there is a line break in the middle for some reason.
When looking at the value of the variable I get the following:
Working Example - "CN=ABC, OU=Location, OU=Distribution Lists, DC=Domain, DC=COM"
Error Example - "CN=ABC, OU=Location, OU=Distribution
Lists, DC=Domain, DC=COM"
It seems to insert a return in-between Distribution and Lists on certain entries in the file. I have tried deleting the character in-between and replacing it with a space but I get the same result.
Could it be the length? I am still looking for a common factor but any suggestions would be great.
Thanks
Updated with requested content.
$Groups = Import-Csv C:\Temp\DLName.csv
write-host ($Groups).Count
$i=1
foreach ($Group in $Groups)
{
$GroupInfo = Get-ADGroupMembersRecursive -Groups $Group.Name
$MembersCount = ($GroupInfo | Measure-Object).Count
$MembersList = $GroupInfo | Select Name -ExcludeProperty Name
$FriendlyName = Get-ADGroup -Identity $Group.Name
$Export = $FriendlyName.Name + ", " + $MembersCount
$Export | Out-File C:\Temp\DLMembers.csv -Append
Write-host $FriendlyName "," $MembersCount
$i
$i++
}
Entry 1 and 3 work 2 doesn't, but the formatting here seems to have wrapped the entries.
Name
"CN=Company - DL Name1,OU=Country1 Distribution Lists,OU=Europe,OU=Acc,DC=Domain,DC=Domain,DC=com"
"CN=Company - DL Name2,OU=Country2 Distribution Lists,OU=Europe,OU=Acc,DC=Domain,DC=Domain,DC=com"
"CN=Company - DL Name3,OU=Country3 Distribution Lists,OU=America,OU=Acc,DC=Domain,DC=Domain,DC=com"
Top pic is the failure second pic works.
List Creation:
$SearchScope = "OU=OUName,DC=Domain,DC=Domain,DC=com"
$SearchFilter = {GroupCategory -eq 'Distribution'}
$Groups = Get-ADGroup -SearchBase $SearchScope -Filter
$SearchFilter | Sort-Object Name
foreach ($Group in $Groups)
{
$Group.DistinguishedName | Select Name -ExpandProperty Name
$Group.DistinguishedName | Out-File C:\Temp\DLName.csv -Append
}
Do not use a self-combined comma separated string and Out-File to create CSV files, because that will get you into trouble when fields happen to contain the delimiter character like in this case the comma (which will lead to mis-aligned data).
Your List Creation code should be like this:
$SearchBase = "OU=OUName,DC=Domain,DC=Domain,DC=com"
$SearchFilter = "GroupCategory -eq 'Distribution'"
Get-ADGroup -SearchBase $SearchBase -Filter $SearchFilter |
Sort-Object Name | Select-Object Name, DistinguishedName |
Export-Csv -Path 'C:\Temp\DLName.csv' -NoTypeInformation
Then you can use that csv later to do:
$Groups = Import-Csv -Path 'C:\Temp\DLName.csv'
Write-Host $Groups.Count
$result = foreach ($Group in $Groups) {
$GroupInfo = Get-ADGroupMember -Identity $Group.DistinguishedName -Recursive
# unnecessary.. $MembersCount = ($GroupInfo | Measure-Object).Count
# unused.. $MembersList = $GroupInfo.Name
# unnecessary.. $FriendlyName = Get-ADGroup -Identity $Group.Name
# output an object with the wanted properties
[PsCustomObject]#{
GroupName = $Group.Name
MemberCount = #($GroupInfo).Count # #() in case there is only one member in the group
}
}
# show on screen
$result | Format-Table -AutoSize
# output to CSV file
$result | Export-Csv -Path 'C:\Temp\DLMembers.csv' -NoTypeInformation
As you can see, I'm not using your custom function Get-ADGroupMembersRecursive because I have no idea what that outputs.. Also, there is no need for that because you can use the Get-ADGroupMember cmdlet with the -Recursive switch added

Compare list of computer from text file with AD-User property

I new in Powershell world and trying to write a script which perform following:
Get List of Computers from a text file
Get list of Users from a text file
Control if the computer name is added in LogonWorkstations field in each user account
Here is the script I have written as of yet.
$Computers = Get-Content Computers.txt
$Users = Get-Content -Path Users.txt | Sort-Object -Unique
$ADUsers = Get-ADUser -Filter * -Properties LogonWorkstations -SearchScope Subtree -SearchBase "OU=ck,OU=users-com,DC=domain,DC=com" |
Where-Object {$Users -contains $_.Name} | Format-List Name,LogonWorkstations
As the script shows I read and retrieve property for Users and have list of computers in text file.
There are 50+ computers and users my question is how can I compare this line wise example check if computer from line 1 of Computers.txt exist in LogonWorkstations property of user from line 1 of Users.txt?
If each line of both files are corresponding, you can use a simple for loop to iterate through both lists simultaneously. $ADUsers will contain the output of ADUser objects matching the conditions.
$ADUsers = for ($i = 0; $i -lt $Users.Count; $i++) {
Get-ADUser -Filter "Name -eq '$($Users[$i])'" -Properties LogonWorkstations |
Where-Object { ($_.LogonWorkstations -split ',') -contains $Computers[$i] }
}
Since LogonWorkstations contains a comma-separated string, you will have to do some string manipulation. Using the -split operator on the , character will result in an array of strings. The -contains operator works nicely when comparing an item or collection of items to a single item.
If you want to compare the LogonWorkstations value of a user to any computer in the list, you can do something like the following:
$ADUsers = foreach ($User in $Users) {
Get-ADUser -Filter "Name -eq '$User'" -Properties LogonWorkstations | Where-Object {
Compare-Object -Ref ($_.LogonWorkstations -split ',') -Dif $Computers -IncludeEqual -ExcludeDifferent
}
}
Compare-Object here will only return a value if there is an exact match.
Note: I believe the LogonWorkstations attribute has been replaced with UserWorkstations attribute. Both may work now but may not be guaranteed in the future.
I haven't tried the below code but hopefully, you will be able to work out any little issues:
$computers = Get-Content -Path #PATHTOCOMPUTERS.TXT
$users = Get-Content -Path #PATHTOUSERS.TXT | Sort-Object -Unique
#Set a counter to zero
$counter = 0
foreach ($user in $users){
try{
#Get the current user from AD
$adUser = Get-ADUser -Filter { Name -eq $user} -Properties LogonWorkStations -ErrorAction Stop
#Uses the current index using $counter to get the correct computer from computers.txt and
#checks if the user has it setup as a LogonWorkStation
if ($adUser.LogonWorkstations -eq $computers[$counter]){
Write-Host "$user has $computer as a logon workstation"
}else{
Write-Host "$user doesn't have $computer as a logon workstation"
}
}catch{
Write-Host "Failed to get the AD user"
}
#Increment the $counter
$counter++
}

Disable users from valid list

I've got a list of valid users provided by HR. The formatting was not cool, so I managed to get a new file like I wanted: one column, on each line the samaccountname (1st letter of firstname and name).
My file looks like this:
bgates
sjobs
bmarley
epresley
etc.
I'd like to disable users who are NOT in this list. I guess I have to deal with some if stuff, but I don't know how to.
#HariHaran, i have tried this:
#this part works fine
$list = Import-Csv .\listadnames2.csv -Delimiter ";"
$lol =
ForEach ($user in $list)
{
$user.prenom[0] + $user.nom
}
$lol | Out-File .\samaccountnames.csv
$validusers = Import-Csv .\samaccountnames.csv
$fullusers = Get-ADUser -Filter * -SearchBase "OU=USERS,DC=domain,DC=com" -ResultPageSize 0 -Prop samaccountname | Select samaccountname
foreach ($u in $validusers)
if ($u -match $fullusers) {continue} else
{
Set-ADUser -Identity $($._) -Enabled $false -whatif
}
The users list (samaccountnames.csv) you create in $lol is not a CSV file, but simply a text file with all constructed usernames each on a separate line.
Therefore you should read the file using
$validusers = Get-Content .\samaccountnames.csv instead of $validusers = Import-Csv .\samaccountnames.csv.
Then you'll have an array of samaccountnames to work with.
Next, I wonder why you use -ResultPageSize 0.. The default setting is 256 objects per page, so I can only imaging you could need this value to be higher than this default, not less.
(see the docs)
Taken from the part where you read the samaccountnames file, I think this will do the job:
$validusers = Get-Content .\samaccountnames.csv
# property 'SamAccountName' is returned by default as are
# 'DistinguishedName', 'Enabled', 'GivenName', 'Name', 'ObjectClass', 'ObjectGUID', 'SID', 'Surname' and 'UserPrincipalName'
# get the user objects from AD and loop through them to see if they need to be set disabled
Get-ADUser -Filter * -SearchBase "OU=USERS,DC=domain,DC=com" | ForEach-Object {
# the $_ automatic variable now holds an AD user object
# or use if($_.SamAccountName -notin $validusers). Only for PowerShell version 3.0 and up
if ($validusers -notcontains $_.SamAccountName) {
$_ | Set-ADUser -Enabled $false -WhatIf
}
}

List user details from Username

I am trying to create a script that will check a list of user names and show the user full name and some attribute settings from AD. Basically I have been sent a list of usernames which are just numbers and management want to know the users full name for each username. they also want to know want division they work for.
Below is the script I have created which doesn't work.
$csv = Import-Csv "C:\temp\users.csv"
foreach ($user in $csv) {
$name = $user.myid
Get-ADUser -Filter {EmployeeID -eq $name} -Properties * |
Get-ADUser -Division $user.Programme
} | Export-Csv "C:\Temp\Results.csv"
So I'm working under the assumption that there is a column named myid in your csv file that contains the id you need to be looking up. Assuming that is the case you'll need to make a few changes here. You'll need to remove the second get-aduser as it is not really doing anything for you, and there is no -division switch available to the get-aduser cmdlet, if you need to restrict your results to just a few settings you can do that using the -properties switch and piping to select as shown below. Keep in mind that none of this will matter if the users do not have the "employeeid" and "division" properties set on their AD accounts, which is fairly rare in my experience but if your company does as a matter of policy when creating accounts should be fine. If you replace the get-aduser line in your script with this it should get the account of any user with an EmployeeID property that matches the one in your spreadsheet and then output that person's full name, division, and employeeid to your CSV file.
Get-ADUser -Filter {EmployeeID -eq $name} -Properties "displayname","division","employeeid" | Select-Object "employeeid","displayname","division"
When in doubt, read the documentation. Get-ADUser doesn't have a parameter -Division. You need to select the properties you want in the output file. Also, foreach loops don't pass output into the pipeline. You need a ForEach-Object loop if you want to pass the output directly into Export-Csv:
Import-Csv 'C:\temp\users.csv' |
ForEach-Object {
$name = $_.myid
Get-ADUser -Filter "EmployeeID -eq $name" -Properties *
} |
Select-Object SamAccountName, DisplayName, Division |
Export-Csv 'C:\Temp\Results.csv' -NoType
Otherwise you need to collect the output in a variable:
$users = foreach ($user in $csv) {
$name = $user.myid
Get-ADUser -Filter "EmployeeID -eq $name" -Properties *
}
$users | Export-Csv 'C:\Temp\Results.csv' -NoType
or run the loop in a subexpression:
$(foreach ($user in $csv) {
$name = $user.myid
Get-ADUser -Filter "EmployeeID -eq $name" -Properties *
}) | Export-Csv 'C:\Temp\Results.csv' -NoType
This is a generic code structure that can be adapted for data collection / enumeration and production of CSV files, tailored to your scenario. We use similar at my workplace. It contains some error handling - the last thing you'd want is inaccurate results in your CSV file.
# Create an array from a data source:
$dataArray = import-csv "C:\temp\users.csv"
# Create an array to store results of foreach loop:
$arrayOfHashtables = #()
# Loop the data array, doing additional work to create our custom data for the CSV file:
foreach($item in $dataArray)
{
try
{
$ADObject = Get-ADUser -Filter { EmployeeID -eq $item.MyID } -Properties DisplayName,Division -ErrorAction Stop
}
catch
{
Write-Output "$($item.MyID): Error looking up this ID. Error was $($Error[0].Exception.Message)"
}
if($ADObject)
{
# Create a hashtable to store information about a single item:
$hashTable = [ordered]#{
EmployeeID=$item.myID
DisplayName=$ADObject.DisplayName
}
# Add the hashtable into the results array:
$arrayOfHashtables += (New-Object -TypeName PSObject -Property $hashTable)
}
else
{
Write-Output "$($item.MyID): No result found for this ID."
}
}
# If the results array was populated, export it:
if($arrayOfHashtables.Count -gt 0)
{
$arrayOfHashtables | Export-CSV -Path "C:\Temp\Results.csv" -Confirm:$false -NoTypeInformation
}
As mentioned elsewhere, division isn't a property on an AD object so you might need to lookup this data elsewhere. If you can do that with another line of PowerShell inside your foreach loop, you could add this to your hashtable object like so:
$hashTable = [ordered]#{
EmployeeID=$item.myID
DisplayName=$ADObject.DisplayName
Division=$DivisionFromOtherSource
}