I want to generate a list of users, with the exception of a list of names. This exclusion list changes from week to week.
$exclude = #('smith, bob', 'jones, tom', ...)
$csvmaster = #()
$uacct = 'User Account'
$UserID = 'User ID'
$lastname = 'Last Name'
... other attributes
$ulist = get-aduser -filter {enabled -eq 'true'} -properties * | ? {$_.Distinguishedname -like '*Standard User*' -and $_.title -ne $null -and $_.employeenumber -ne $null}
foreach ($u in $ulist)
{
if ($u.name -notmatch $exclude) {
$csvline = New-Object System.Object
$csvline | Add-Member -MemberType NoteProperty -name $UserID -value $u.EmployeeNumber
$csvline | Add-Member -MemberType NoteProperty -name $lastname -value $u.surname
...other attributes
$csvmaster += $csvline
}
}
...Output to csv
When I run this, the names I want to exclude still make it into the list. I also tried -notcontains and excluding them like this:
$ulist = get-aduser -filter {enabled -eq 'true'} -properties * | ? {$_.Distinguishedname -like '*Standard User*' -and $_.title -ne $null -and $_.employeenumber -ne $null -and $_.name -notmatch $exclude}
This behaves the same way.
Cheers.
So I think my problem was the way Get-ADUser accepts input value. And/Or my logic in general. I changed the code to this:
$exclude = #( ..list..of..names..)
$csvline = #()
$ulist = get-aduser ...
foreach ($u in $ulist)
{
if ($exclude -notcontains $u.name)
{
...
$csvline += $u.name
}
}
And it is doing what I need.
Related
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
I'm trying to clean up our storage from legacy users that no longer exist and getting misc results.
I have a share with all usernames as folder names (ex. \\storage\homedir\joeblow) AD username: Joeblow. Throughout various years users have been removed from the domain but the folders were never removed from the share. So I am walking the share and using that to query the domain to find if said user still exists. I seems to work most the time and fail randomly. Not sure why, because manually sometimes the code will execute fine. Any thoughts?
Here is the code:
Import-Module ActiveDirectory
$folders = dir \\storage.domain.edu\C$\homedir3 | where {$_.PSIsContainer -eq $true}
$folder4 = "\\storage.domain.edu\C$\homedir4"
function New-Folder($Name, $Size) {
$folderList = New-Object PSObject
$folderList | Add-Member -MemberType NoteProperty -Name Name -Value $Name
$folderList | Add-Member -MemberType NoteProperty -Name Size -Value $Size
$folderList | Add-Member -MemberType NoteProperty -Name User -Value $User
}
foreach ($i in $folders) {
Write-Host "Folder presently is folder $i"
#$ADuser=Get-ADUser -Filter {$i.sAMAccountName.ToUpper() -eq"$i"} -SearchBase "OU=Active,OU=UserAccounts,DC=ad,DC=domain,DC=edu"
#$ADuser=Get-ADUser -Filter {samaccountname -eq $i} -SearchBase "OU=Active,OU=UserAccounts,DC=ad,DC=domain,DC=edu" -Property samaccountname
$r = "\\STORAGE.domain.EDU\HOMEDIR\$i"
$r = $r.ToUpper()
$ADuser = Get-ADUser -Filter {sameaccountname -eq $i} -SearchBase "OU=Active,OU=UserAccounts,DC=ad,DC=domain,DC=edu" -Property homeDirectory, samaccountname
if (!$ADuser) {
Write-Host "Null yo"
$ADuser = Get-ADUser -Filter {homeDirectory -eq $r} -SearchBase "OU=Active,OU=UserAccounts,DC=ad,DC=domain,DC=edu" -Property homeDirectory, samaccountname
}
$ADname = $ADuser.samaccountname.ToUpper()
$ADuser = $ADuser.homeDirectory
$ADuser = $ADuser.toupper()
Write-Host "R be this: $r and equal $ADuser"
#Write-Host "The person's folder name is: $ADuser"
#$iUp = $i.ToUpper()
Write-Host "The folder's is: $i"
if ($ADuser -eq $r) {
Write-Host "User: $ADname is in HomeDir3 $ADuser"
} else {
#(Test-Path "$folder4\$ADuser".trim()) {
#$notFound = $i
$folderList = New-Folder -Name $ADuser -User
Write-Host "$ADname failed"
}
}
#}
Write-Host "$folderList"
#$leftOvers = Compare-Object $folder4 $notFound
#Write-Host " Here is whats left $leftOvers"
#$i | Out-File -append "C:\deadaccounts.txt"
Hi I am trying to run a script to get users in a network into an array so that it can be outputted to a csv file along with other data that I am going to get, such as distribution groups.
The code script I am running is giving an error:
Method invocation failed because [System.Management.Automation.PSObject] doesn't contain a method named 'op_Addition'.
The script is a simple for loop:
$ActiveDirectoryList=#()
$UserDetails = get-aduser -filter {enabled -eq $true} -properties * | Select DisplayName,EmailAddress, SAMAccountName
$counter = 0
foreach($User in $UserDetails){
$ActiveDirectoryList = New-Object PSObject
$Users = get-aduser $User.SAMAccountName -properties *
if(!$Users.EmailAddress -eq ""){
$counter++
$ActiveDirectoryList | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $Users.DisplayName
$ActiveDirectoryList | Add-Member -MemberType NoteProperty -Name "Email Address" -Value $Users.EmailAddress
write-host $Users.DisplayName
$ActiveDirectoryList+=$ActiveDirectoryList
}
}
Tried looking on the internet for a solution but they don't seem to solve anything.
Don't reuse the same variable name for the array, and the individual objects that you want to add to the array. Here I've renamed the PSObject variable to $ActiveDirectoryObject:
$ActiveDirectoryList=#()
$UserDetails = get-aduser -filter {enabled -eq $true} -properties * | Select DisplayName,EmailAddress, SAMAccountName
$counter = 0
foreach($User in $UserDetails){
$ActiveDirectoryObject = New-Object PSObject
$Users = get-aduser $User.SAMAccountName -properties *
if(!$Users.EmailAddress -eq ""){
$counter++
$ActiveDirectoryObject | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $Users.DisplayName
$ActiveDirectoryObject | Add-Member -MemberType NoteProperty -Name "Email Address" -Value $Users.EmailAddress
write-host $Users.DisplayName
$ActiveDirectoryList += $ActiveDirectoryObject
}
}
Additional Note: This can also occur if you don't declare the array as an array or mistype it when you declare it. Simple little error. But, maybe it will help someone that comes here and still can't get it resolved. Check your array variable name declaration carefully.
# Example 1 of how you could unintentionally fubar it.
$ActiveDirectoryList=$null
# Example 2 of how you could unintentionally fubar it.
$ActiveDirectoryList_ExaggeratedExampleWrongName=#()
# Example 3. Same as 2 above, but not as easily identifiable type error
$ActiveDirectoryLists=#()
$UserDetails = get-aduser -filter {enabled -eq $true} -properties * | Select DisplayName,EmailAddress, SAMAccountName
$counter = 0
foreach($User in $UserDetails){
$ActiveDirectoryObject = New-Object PSObject
$Users = get-aduser $User.SAMAccountName -properties *
if(!$Users.EmailAddress -eq ""){
$counter++
$ActiveDirectoryObject | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $Users.DisplayName
$ActiveDirectoryObject | Add-Member -MemberType NoteProperty -Name "Email Address" -Value $Users.EmailAddress
write-host $Users.DisplayName
$ActiveDirectoryList += $ActiveDirectoryObject
}
}
+= kills puppies. (the whole array is copied every time)
$UserDetails = get-aduser -filter {enabled -eq $true} -properties |
Select DisplayName,EmailAddress, SAMAccountName
$counter = 0
$ActiveDirectoryList = foreach($User in $UserDetails){
$Users = get-aduser $User.SAMAccountName -properties *
if(!$Users.EmailAddress -eq ""){
$counter++
New-Object PSObject -property #{
Displayname = $Users.DisplayName
'Email Address' = $Users.EmailAddress
}
write-host $Users.DisplayName
}
}
This can be simplified to:
$ActiveDirectoryList = get-aduser -filter {enabled -eq $true -and
EmailAddress -like '*'} -properties Displayname,EmailAddress |
select Displayname,#{n='Email Address';e={$_.EmailAddress}}
I have an AD group that has other AD groups as members. Some of these groups may have "sub-groups" as well. I want to recursively descend through this group and find answers to several questions about the users in that group. For example:
Is User-X "enabled" in the overall group?
Does the account of User-X have values in ANY of the properties: AccountExpirationDate, accountExpires and Deleted?
I would like a displayed result that contains the properties: DisplayName, SamAccountName, AccountExpirationDate, accountExpires, Deleted and enabled (from the group object)
I have tried doing an "Add-Member" to insert the "enabled" value from get-ADgroupMember but I get the error:
Add-Member : Cannot add a member with the name "enabled" because a member with that name already exists. If you want to over
write the member anyway, use the Force parameter to overwrite it.
... but there is no such element as far as I can tell. I have renamed the member in the Add-Member to several very unique things but I still get the same error.
my current attempt is:
Import-Module ActiveDirectory
get-adgroupmember -Identity "My big AD group of groups" -recursive |
Where-Object -FilterScript {($_.ObjectClass -eq 'user')} |
ForEach-Object {
$enabled = $_.enebled
Get-ADUser `
-Filter {(name -eq $_.name)} `
-Properties DisplayName,SamAccountName,AccountExpirationDate,accountExpires,Deleted |
Add-Member -Name "myITGGroupEnabled" -Value $enabled -MemberType NoteProperty |
Where-Object `
-FilterScript {
($_.AccountExpirationDate -lt [datetime]::now) `
-OR ($_.accountExpires -eq $true) `
-OR ($_.Deleted -eq $true) `
-OR ($_.myITGGroupEnabled -eq $false)
}
Select-Object DisplayName,SamAccountName,AccountExpirationDate,accountExpires,Deleted,GroupEnabled
break
}
I am lost. Ideas?
I think all you need is a new PSObject. Like this:
...
Get-AdUser -Filter {name -eq $_.name} -Properties .... | % {
If ( ($_.AccountExpirationDate -lt [datetime]::now) `
-OR ($_.accountExpires -eq $true) `
-OR ($_.Deleted -eq $true) `
-OR ($_.myITGGroupEnabled -eq $false)) {
New-Object PSObject -Property #{MyITGGRoupEnabled=$enabled}
}
}
i wrote a script that gonna disabled old users...
and i need to do an exclude list to it...
the exclude list should be .csv, with 3 columns "Name","SamaccountName","Reason"...
i'm kind of stuck with the exclude list filtering...
i tried to do -notmatch and -notcontains and nothing worked for me...
i even try to do a foreach with if but the same...
Function Get-ADLockOldUsers {
param ()
begin{
[datetime]$myDate = '01/01/1601 02:00:00'
$colObj = #()
$AllUsers = (Get-ADUser -Filter * -Properties lastLogonTimestamp | ? {$_.Enabled} | Select-Object Name,SamAccountName,#{N="LastLogon";E={[datetime]::FromFileTime($_.lastLogonTimestamp)}})
$AllUsers = $AllUsers | ? {(Get-Date).AddDays(-30) -gt $_.LastLogon -and -not ($_.LastLogon -eq $myDate)}
}
process {
$AllUsers | % {
$obj = New-Object psobject
$obj | Add-Member noteproperty 'Name' $_.Name -Force
$obj | Add-Member noteproperty 'SamAccountName' $_.SamAccountName -Force
$obj | Add-Member noteproperty 'LastLogon' $_.LastLogon -Force
$obj | Add-Member noteproperty 'NeedDisabled' $true -Force
$colObj += $obj
}
}
end { return $colObj }
}
Function Set-ADLockUser {
param()
begin{
if (Test-Path '.\excludeusers.csv') {
$excludeUsers = Import-Csv '.\excludeusers.csv'
$DUser = #()
$colUsers = Get-ADLockOldUsers
$colUsers | ? {$_.SamAccountName -notcontains $excludeUsers} | % {Set-ADUser -Identity $_.SamAccountName -Enabled $false -WhatIf }
}
else { Write-Output "Error! excludeusers.csv cannot be found, stop script"; break }
}
process {
}
end{}
}
Set-ADLockUser
A string value can never contain an array, so
$_.SamAccountName -notcontains $excludeUsers
will always evaluate to $true. You need to reverse the check and make the reference an array of strings (the CSV import produces an array of custom objects). Selecting only the field SamaccountName from the imported CSV and switching the arguments should do what you want:
$excludeUsers = Import-Csv '.\excludeusers.csv' | % { $_.SamaccountName }
...
$colUsers | ? { $excludeUsers -notcontains $_.SamAccountName } | ...
As a side note, you could simplify the the code for finding obsolete accounts like this:
$myDate = Get-Date '01/01/1601 02:00:00'
$limit = (Get-Date).AddDays(-30)
$colObj = Get-ADUser -Filter * -Properties * `
| ? { $_.Enabled } `
| select Name,SamAccountName,#{n="NeedDisabled";e={$true}},
#{n="LastLogon";e={[datetime]::FromFileTime($_.lastLogonTimestamp)}} `
| ? { $limit -gt $_.LastLogon -and $_.LastLogon -ne $myDate }
This is the final solution...
<#
.Synopsis
Get All Users in the Domain and check the last logon Date
.Example
Set-ADLockUser -ReportOnly:$true
Get all users that didn't logon for a 30 days and write a report to the current directory
.Example
Set-ADLockUser -ReportOnly:$false
Get all users that didn't logon for a 30 days and disabled them
.Description
Get All Users in the Domain and check the last logon Date, and exclude some users from a list .\excludeusers.csv
.Parameter ReportOnly
Specifies if the script is in reportmode or active mode if ReportOnly=$false all the relevant users will lock
.Outputs
PSObject[]
.Notes
Name: Set-ADLockUser
Author: Ohad Halali
Date: 14.07.2013
.Link
#>
Function Get-ADLockOldUsers {
param ()
begin{
[datetime]$myDate = '01/01/1601 02:00:00'
$colObj = #()
$AllUsers = (Get-ADUser -Filter * -Properties lastLogonTimestamp | ? {$_.Enabled} | `
Select Name,SamAccountName,#{N="LastLogon";E={[datetime]::FromFileTime($_.lastLogonTimestamp)}}) | `
? {(Get-Date).AddDays(-30) -gt $_.LastLogon -and -not ($_.LastLogon -eq $myDate)}
}
process {
$AllUsers | % {
$obj = New-Object psobject
$obj | Add-Member noteproperty 'Name' $_.Name -Force
$obj | Add-Member noteproperty 'SamAccountName' $_.SamAccountName -Force
$obj | Add-Member noteproperty 'LastLogon' $_.LastLogon -Force
$obj | Add-Member noteproperty 'NeedDisabled' $true -Force
$colObj += $obj
}
}
end { return $colObj }
}
Function Set-ADLockUser {
param([bool]$ReportOnly=$true)
begin{
if (Test-Path '.\excludeusers.csv') {
$excludeUsers = Import-Csv '.\excludeusers.csv'
$colUsers = Get-ADLockOldUsers | ? {$excludeUsers.SamAccountName -notcontains $_.SamAccountName}
if ($ReportOnly) {
$colUsers | Export-Csv '.\Report.csv' -NoClobber -NoTypeInformation -Encoding ASCII -Force
}
else {
$colUsers.SamAccountName | Set-ADUser -SamAccountName $_ -Enabled:$False -Replace #{info="Disabled after no login for 30 days (Script)"} -WhatIf
}
}
else { Write-Output "Error! excludeusers.csv cannot be found, stop script"; break }
}
process {}
end{}
}
Set-ADLockUser