Get AD-Computer not like distinguished name - windows

I am trying to get a list of computers from AD excluding some computers which are not in use anymore.
Here is my code:
$ServerList = Get-ADComputer -Filter * | Where {
$_.DistinguishedName -like "*Computers*" -and $_.DistinguishedName -notlike #("*server1*","*Server2*")
} | Select-Object Name
I am trying to put the computers which I was to exclude in an array instead of using
-and $_.DistinguishedName -notlike "*serverIwantToExclude*"
Can you guys give me any idea on how I could amend it ?

-notlike does not support collections on the right-hand side (RHS). A similarly intended approach is to use -notmatch, which is a regex string:
$ServerList = Get-ADComputer -Filter * |
Where { $_.DistinguishedName -like "*Computers*" -and $_.DistinguishedName -notmatch 'server1|Server2'} |
Select-Object Name
If you want your server names in a list first, you can create a regex string from that.
$serverdown = 'server1','server2'
$regex = $serverdown -join '|'
$ServerList = Get-ADComputer -Filter * |
Where { $_.DistinguishedName -like "*Computers*" -and $_.DistinguishedName -notmatch $regex} |
Select-Object Name
If you do not anchor your regex strings, it looks for the regex match anywhere within the target string (effectively having surrounding wildcards). | is an alternation (an effective OR).
There are other operators that support collections like -contains, -in, -notin, and -notcontains. However, they must match exactly and cannot use wildcards.

you can use the -inotin operator if you know the full name of the servers you wish to exclude, meaning you can not use a wildcard or regex with the -inotin operator. If this is the case and you know the names I recommend using the Name property of the ADComputer object.
[string[]] $excludedServers = 'server1','server2'
$ServerList = Get-ADComputer -Filter * | Where {
$_.DistinguishedName -like "*Computers*" -and $_.Name -inotin $excludedServers
} | Select-Object Name

another way to exclude them is to add all those computers to a group and exclude it
#Provide DN of the group
$groupname = "CN=groupname,OU=Groups,DC=Domain,DC=COM"
get-adcomputer -filter {(OperatingSystem -like "Windows")} | -properties * | ?{([string]$_.memberof -notmatch $groupname)} | select name, lastlogondate

Related

Get-AD Computer not match text file content

I want to get a list of all ad computers excluding the servers that are in a text file. Here's my code:-
$excludedServers = (Get-Content
"C:\Users\testuser\Documents\RdpDisconnectedSessions\ExcludedServers.txt").name #| Sort-Object
Get-ADComputer -Filter * | Where { $_.DistinguishedName -like "*Computers*" -and $_.DistinguishedName -notmatch $excludedServers } | Select-Object Name
Any advise please ?
First, Get-Content is not going to bring back objects so the .name portion is not going to work. If it's just a list of computernames, then simply change it to.
$excludedServers = Get-Content "C:\Users\testuser\Documents\RdpDisconnectedSessions\ExcludedServers.txt"
If it's a CSV with a name column, then you can do it a few ways. Sticking with the format you had this would work
$excludedServers = (Import-Csv "C:\Users\testuser\Documents\RdpDisconnectedSessions\ExcludedServers.txt").name
Now that you have your list of names, you can filter like this (assuming it is actually the names of the servers and not their distinguished name)
Get-ADComputer -Filter * | Where { $_.DistinguishedName -like "*Computers*" -and $_.name -notin $excludedServers } | Select-Object Name

How do I use the where-object cmdlet to find text that -contains a certain word

I'm setting up a contacts file in .csv format, as downloaded from google, to read with powershell on my windows 10 laptop. I have a long way to go to make this practical, but the first thing I've tried, and almost succeeded in, is to write a script that prompts the user to enter a name and then responds with the phone number for them. That script looks like this:
Param(
[Parameter(Mandatory=$true, Position=0, HelpMessage="What's their name?")]
$TheirNameIs
)
Import-Csv "*MYPATH*.csv" |
Sort 'Family name' -descending |
Where-object {$_.Name -eq $TheirNameIs} |
Select-Object -Property 'Name','Phone 1 - Type','Phone 1 - Value'
The problem I am having is Where-object works with -eq to find exact matches to the name the user enters, but I wanted to use -contains so that I could type in a first name and get all the contacts with that value in their name. I tried replacing -eq with -contains but wasn't getting any output unless I used the exact contact name
Where am I going wrong with the Where-object cmdlet?
You could replace the -eq operator by the -like operator and insert wildcards:
Param(
[Parameter(Mandatory=$true, Position=0, HelpMessage="What's their name?")]
$TheirNameIs
)
Import-Csv "*MYPATH*.csv" |
Sort 'Family name' -descending |
Where-object {$_.Name -like "*$TheirNameIs*"} |
Select-Object -Property 'Name','Phone 1 - Type','Phone 1 - Value'
You could also go for regular expressions and use the -match operator like #Olaf already mentioned. A solution could look like this:
Param(
[Parameter(Mandatory=$true, Position=0, HelpMessage="What's their name?")]
$TheirNameIs
)
Import-Csv "*MYPATH*.csv" |
Sort 'Family name' -descending |
Where-object {$_.Name -match ".*$TheirNameIs.*"} |
Select-Object -Property 'Name','Phone 1 - Type','Phone 1 - Value'

Find username in array beginning with 'n'

I have a hash table from AD containing usernames and service accounts. I'm trying to find all the service accounts. All usernames are uniquely identified by their first letters such as 'r' and service accounts with 's'. For example: r398831 and s882443. Here's an example of the array I have:
$null = $usrArr.Add([pscustomobject] #{
sName = $user.name
sGivenName = $user.GivenName
sSurname = $user.Surname
sEnabled = $user.Enabled
})
$lastSeen = $usrArr | select * | Where {$_.sEnabled -eq $true}
$lastSeen = $lastSeen | Sort-Object -Unique -Property sName
I've tried using -contains and -match but it doesn't seem to pull back what I'm after:
$svcAcc = $lastSeen | where-object {$_.sName -like "s"}
Do I have to perform a for each or have I just messed up my Syntax on this?
I'm thinking maybe I need to sort-object but there has to be a more simple way to pull off something so basic. Appreciate any advice on it.
Thanks in advance :)
Best,
Pete
The -like operator matches the wildcard pattern on the RHS against the entire LHS, so -like "s" would only ever match values that are in full identical to literal s.
To instead match inputs that start with literal s, use wildcard pattern s*:
$svcAcc = $lastSeen | where-object { $_.sName -like 's*' }
As an aside: Your use of select * seems redundant; similarly, -eq $true is not strictly necessary, so assigning to $lastSeen can be simplified to:
$lastSeen = $usrArr | Where-Object sEnabled | Sort-Object -Unique -Property sName
Note that Where-Object sEnabled is short for Where-Object { $_.sEnabled }, which is a syntax simplification introduced in PSv3, called a comparison statement.
You can use -match like you were trying to do but just turn your query into a regular expression using the caret anchor character.
$usrArr | Where-Object { $_.sName -match "^s" }

powershell: get-psdrive and where-object

Im trying to find every drive letter that isnt "C,E,L,S,T,W" on a windows 2008 server. Can anyone tell me the fault in my logic or how i can do this please?
[char[]]”CELSTW” | Where-Object {!(Get-PSDrive $_ )}
You are starting out with a list of drive letters you don't want (CELSTW) and outputting the ones that don't exist as a psdrive.
What you want is to start with a list of all PSDrives and filter them out where they match the ones you don't want:
Get-PSDrive | Where-Object { [char[]]"CELSTW" -notcontains $_.Name }
Although that is going to give you a bunch of other PSDrive types. You probably also want to filter it for the FileSystem provider:
Get-PSDrive | Where-Object { [char[]]"CELSTW" -notcontains $_.Name -AND $_.Provider.Name -eq "FileSystem"}
This should give you all psdrives where the name (driveletter) isn't "C,E,L,S,T,W"
Get-PSDrive | ?{[char[]]"CELSTW" -notcontains $_.name}
however if you want to exclude non-filesystem psdrives, try this:
Get-PSDrive | ?{[char[]]"CELSTW" -notcontains $_.name} | ?{$_.Provider.name -eq "FileSystem"}
You must go for this from the other end:
$drives = [char[]]"CD"
Get-PSDrive | ? { $drives -notcontains $_.Name}
Another example using the -notmatch operator:
Get-PSDrive | Where-Object { $_.Name -notmatch '[CELSTW]'}

Filter Get-ADComputer where "Name -notlike" in Powershell

My goal is to get a list of AD computer objects not following naming conventions with the whenCreated property. I am trying to export out a HTML file using the following PowerShell function:
function get_bad_names
{
$result = Get-ADComputer -searchbase $OU
-Filter {Name -notlike 'name1' -and
Name -notlike 'name2' -and
Name -notlike 'name3'}
-Properties whenCreated | sort whenCreated
$result | ConvertTo-Html | Out-File $dir\badnames.html
}
get_bad_names
Is there a more elegant way of structuring the Name filter lines? We have over 40 lines of different "names." In other words, over 40 lines in my script say Name -notlike 'name#' -and
Ideally I'd like for the code to read from a text file and export out the same results.
FYI: this function works but it is not ideally written. Any suggestions would be appreciated.
If you'd like to filter the query, construct an LDAP filter:
# Define the names to exclude
$NamesToExclude = "Name1","Name2","Name3"
# Turn them into LDAP clauses in the form of "(!(Name=Name1))"
$LDAPClauses = $NamesToExclude |ForEach-Object {
'(!(Name={0}))' -f $_
}
# Create a single query filter string with all the clauses from above
$LDAPFilter = "(&$LDAPClauses)"
$result = Get-ADComputer -LDAPFilter $LDAPFilter -SearchBase $OU -Properties whenCreated |Sort-Object whenCreated
You could filter with a regular expression using Select-Object but then you should get all computers in the OU with the -filter *, and that might strain your network. I would do the filtering and if more properties are needed, run Get-Computer again only for the matches:
Get-ADComputer -searchbase $OU -Filter * |
? { $_.name -match "name\d{1,2}" } | # Match if string "name" is followed one or two digits
Get-ADComputer -property * # Get all properties for the computers if needed
Is there a more elegant way of structuring the Name filter lines?
Not exactly. You have a fairly limited set of operators when you use the -Filter parameter of commands in the ActiveDirectory module because it has to translate them all to LDAP filters.
However, you can do something like this:
$ExcludedPatterns = 'Name1', 'Name2', 'Name3'
$ComputerFilter = foreach ($Pattern in $ExcludedPatterns) { "(Name -notlike '$Pattern')" }
$ComputerFilter = $ComputerFilter -join ' -and '
Get-ADComputer -Filter $ComputerFilter
Now you can maintain a list of name patterns.
Keep in mind that the -Filter property is not a ScriptBlock on the ActiveDirectory commands. They're all Strings and in spite of the documentation for these commands they should be written that way. Writing them as ScriptBlocks will eventually cause you problems with variable expansion.
Compare:
$ComputerName = hostname
Get-ADComputer -Filter "Name -eq '$ComputerName'"
Get-ADComputer -Filter { Name -eq '$ComputerName' }
Thank you to everyone for their feedback. I was impressed how fast the responses were.
I was able to achieve my goal using regular expressions reading from a text file.
My code now looks like this:
[regex]$Expression = Get-Content $dir\regex.txt
function get_bad_names
{
$result = Get-ADComputer -searchbase $OU
-Filter {Enabled -eq $true}
-Properties whenCreated | Where-Object {$_.Name -notmatch $Expression}| sort whenCreated
$result | ConvertTo-Html | Out-File $dir\badnames.html
}
get_bad_names

Resources