I'm trying to create a loop that tests the connection to specific computers in the Active Directory. The output is #{name=KY-WH-DT01} when I'm looking for KY-WH-DT01. I'm not sure what I'm doing wrong.
As a workaround, I've pulled the list manually and properly inserted it into the variable as hard code.
function testConnection {
$computers = Get-ADComputer -filter 'Name -like "KY-WH*" -or name -like "KY-SR"' | select name
$pass = 0
$fail = 0
foreach ($computer in $computers) {
$testConnection = Test-Path "\\$computer\C$" -ErrorAction Stop
if ($testConnection -eq $true) {
Write-Host $computer -ForegroundColor Green
$pass = $pass + 1
}
else {
Write-Host $computer -ForegroundColor Red -BackgroundColor Black
$fail = $fail + 1
}
}
Write-Host $null
Write-Host "Passed: $pass | Failed: $fail"
}
testConnection
...
This code should output a list of computer names with colors determining whether the connection test passed or failed by turning them either red or green.
You need to drill down a little bit in your variable.
foreach ($computer in $computers.Name) {
This will do it if you only want the name or the computer and no other variable.
You can also change your initial search to include the -ExpandProperty switch and you will not need to dig down into the property.
$computers = Get-ADComputer -filter 'Name -like "KY-WH*" -or name -like "KY-SR"' | select -ExpandProperty name
Related
How can this script below modified to export the list of the both servers.txt and Accounts.txt that is not available in Active Directory?
The below script is working fine to import the lists from both files that are available and online, but I need to get the list of wrong or unavailable accounts & computer name into separate log files like:
failed_username.log and failed_computername.log respectively.
$Servers = Get-Content "C:\Users\$env:username\desktop\servers.txt" | Where-Object { ((Get-ADComputer -Filter "Name -eq '$($_)'" -Properties OperatingSystem).OperatingSystem -like '*Windows Server*') -and (Test-Connection -ComputerName $_ -Count 2 -Quiet) }
$Users = Get-Content "C:\Users\$env:username\desktop\Accounts.txt" | Where-Object { (Get-ADUser -Filter "SamAccountName -eq '$($_)'") }
ForEach ($Server in $Servers)
{
$ComputerName = $Server.Trim()
Write-Host "Processing $ComputerName" -ForegroundColor Green
ForEach ($Username in $Users)
{
$UserName = $User.Trim()
Write-Host "Processing $UserName" -ForegroundColor DarkGreen
}
}
May I suggest another approach? I think it wouldn't make that much sense to put users and computers to the same list.
I'd do it this way: I'd collect the information about the computers in a list like this:
$ServerInputList =
Get-Content "C:\Users\$env:username\desktop\servers.txt"
foreach ($ComputerName in $ServerInputList) {
[PSCustomObject]#{
Name = $ComputerName
OS = (Get-ADComputer -Filter "Name -eq '$($ComputerName)'" -Properties OperatingSystem).OperatingSystem
Online = Test-Connection -ComputerName $ComputerName -Count 1 -Quiet
}
}
Now you can easily filter for the computers you want.
The same would work for the users.
Need to write a script to take an input file (text) list of names, check if it exists in AD, and create new computers.
The requirements are as follows -
Computer names are based on the users name (input from file)
Names must be 15 characters (for name resolution)
if the truncated name doesnt exist, create a computer object in specific OU with the truncated name.
If the truncated name does exist, append -# and test to see if it exists until it finds one that doesnt, then create new computer object with that name.
At the end I will need to output the results to an array but I haven't started adding that yet since this doesn't work.
So I finally got the "else" part but the if part at the beginning does not work.
$users = get-content C:\scriptdata\VMS.txt
$OU = ************
foreach ($user in $users)
{
$cleanname = if ($user.Length -gt 15) { $user.Substring(0, 15) } else { $user }
$exist = (get-adcomputer $cleanname) -eq $null
if ((get-adcomputer $cleanname) -like "get-adcomputer : Cannot find an object with identity")
{
New-ADComputer -Name $cleanname -Path "$OU" -SAMAccountName $cleanname -confirm
}
else
{
$count=0
DO{
$count++
$cleanname13 = if ($user.Length -gt 13) { $user.Substring(0, 13) } else { $cleanname }
$cleannamedash = $cleanname13 + '-' + "$count"
}
UNTIL ((get-adcomputer $cleannamedash | out-null) -eq $null)
New-ADComputer -Name $cleannamedash -Path "$OU" -SAMAccountName $cleannamedash -confirm
}
}
currently works for -# but not for those that dont exist at all.
Have a look at Naming conventions in Active Directory for computers, domains, sites, and OUs.
You'll find that there is more to a valid computer name than just the length.
Mind that the New-ADComputer cmdlet creates a new computer object, but does not join a computer to a domain.
Something like this should work (untested)
$computers = Get-Content C:\scriptdata\VMS.txt | Where-Object { $_ -match '\S'}
$OU = ************
foreach ($name in $computers) {
$newName = ($name -creplace '[\\/:*?"<>|.]','').Substring(0, 15)
try {
$computer = Get-ADComputer -Filter "Name -eq '$newName'" -PassThru -ErrorAction Stop
}
catch {
$computer = $null
}
if ($computer) {
# a computer with that name already exists, create a new name by adding a dash and two digit number
$count = 0
$name12 = $newName.Substring(0, 12) # we're going to add three characters
# get an array of computernames that are like the one you want to create
$existingComputers = Get-ADComputer -Filter "Name -like '$name12-*'" | Select-Object -ExpandProperty Name
do {
$newName = '{0}-{1:00}' -f $name12, ++$count
}
until ($existingComputers -notcontains $newName -or $count -gt 99)
if ($count -gt 99) {
$newName = '{0}-XX' -f $name12
throw "Cannot create computer $newName because all index numbers 00..99 are taken.."
}
}
# use splatting, because New-ADComputer has MANY parameters
$props = #{
'Name' = $newName
'Path' = $OU
'SamAccountName' = $newName
'Enabled' = $true
'Confirm' = $true
}
Write-Host "Creating computer '$newName'"
New-ADComputer #props
}
I assume you mean that this is the line that's not working:
if ((get-adcomputer $cleanname) -like "get-adcomputer : Cannot find an object with identity")
And even this doesn't work:
$exist = (get-adcomputer $cleanname) -eq $null
The reason is the same in both cases: If the computer doesn't exist, then Get-ADComputer throws an exception and the comparison is never done.
There is a good article about this here, but in short, the solution is to catch the exception. For you, it would look something like this:
try {
$computer = Get-ADComputer $cleanname
# If we get here, we know it exists
# You can put your loop here and just keep looping until Get-ADComputer throws an exception
}
catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException]
{
# Whatever you last tried doesn't exist. Create it here.
}
I have a script that can have a list of AD servers (with Get-ADComputer) and the results goes to a TXT file. I don't know how to only have Online Servers only. I only need their names.
I tried to do some IF {} Else{} with the cmdlet Test-Connection -CN $Server but it doesn't work (I'm probably doing it wrong). Here is my code :
$TXTFile = "C:\Scripts\Serv.txt"
$TXTOutput = #()
Write-Host "INFO: Finding servers from AD"
$Servers = Get-ADComputer -Filter {OperatingSystem -like "*server*" -and Enabled -eq $true} | SORT Name
Write-Host "INFO:"$Servers.Count"Records found"
ForEach ($Server in $Servers) {
$ServerHash = $NULL
$ServerHash = [ordered]#{
"Servers Name" = $Server.Name
}
$TXTOutput += New-Object PSObject -Property $ServerHash
}
$TXTOutput
I want, if possible, to have all of my AD Online Servers name in a TXT file. For now I only have all of my servers (Online and Offline). It's my first post so sorry if I made it wrong !
You can use -Quiet parameter with Test-Connection cmdlet in order to get just True or False and then make a decision based on that result.
$TXTFile = "C:\Temp\Serv.txt"
$TXTOutput = #()
$servers=Get-ADComputer -Filter {OperatingSystem -like "*server*" -and Enabled -eq $true} | select -expandproperty Name
ForEach ($Server in $Servers) {
if ((Test-Connection $Server -Count 2 -Quiet) -eq $true) {
$TXTOutput += $Server
}
}
$TXTOutput | Out-File $TXTFile
You can pipe $TXTOutput to sort if you want. Keep in mind that this might take a while since you are basically pinging each server twice -Count 2.
I'm comparing users between two domains to make sure users that are disabled in one, are disabled in the other, using these two steps:
Domain 1:
Get-ADUser -SearchBase "OU=ou2,OU=ou1,DC=pre,DC=domain1,DC=com" -Filter * -Properties * | Select-Object Name | Export-Csv -encoding "utf8" Users.csv
Domain 2:
$input = import-csv -path "Users.csv"
ForEach ($User in $input) {
$result = get-aduser -SearchBase "OU=ou2,OU=ou1,DC=pre,DC=domain2,DC=com" -Filter "name -eq '$($User.Name)'" | Select-Object Enabled
If ($result -eq $null) { Write-host -ForegroundColor Yellow $User "Name not found. Please do a manual check"
}
elseif ($result -like '*False*')
{
Write-host -ForegroundColor Red "**" $User "** must be disabled!"
}
else {get-aduser -SearchBase "ou=Users,ou=SCS,ou=All,dc=osit,dc=ad" -Filter "name -eq '$($User.Name)'" -Properties * | Select-Object Name, Enabled}
}
This works, but gives me the following output:
Name Enabled
---- -------
Firstname1 Lastname1 True
#{Name=Firstname2 Lastname2} - Name not found. Please do a manual check
How do I remove "#{Name=" and "}"?
I have tried adding -ExtendProperity to $result, and Replace with no luck. I'm probably doing it wrong..
$User is a custom object (type [pscustomobject], as output by Import-Csv), and #{Name=Firstname2 Lastname2} is its stringified representation[1], because Write-Host stringifies its arguments for display.
Access the .Name property instead to get just the name:
Write-host -ForegroundColor Yellow $User.Name "- Name not found. Please do a manual check"
More idiomatically, using a single expandable string (string interpolation inside "..."):
Write-host -ForegroundColor Yellow "$($User.Name) - Name not found. Please do a manual check"
If you want to include the full object representation as it would appear if you printed it directly to the console, you need Out-String, but note that you'll end up with multi-line output:
Write-host -ForegroundColor Yellow "$($User | Out-String) - Name not found. Please do a manual check"
[1] You can verify this as follows: $user = [pscustomobject] #{ Name = 'Firstname1 LastName1' }; "$user". The output is string #{Name=Firstname1 LastName1}.
I have created a PowerShell script to find the computer name from the values in the description. We put the users name in the description and computer name is an asset tag number. If you continue and put the name in a second time it works. If you look for another user you have to do it twice also.
Here is my script:
Import-Module ActiveDirectory
do {
$a = Read-Host "Enter first or last name of user"
$b = "*$a*"
# Validates if the command returns data
$searcher = $(try {
Get-ADComputer -Filter {Description -like $b} -Properties
Name,Description | Select Name,Description
} catch {
$null
})
if ($searcher -ne $null) {
Get-ADComputer -Filter {Description -like $b } -Properties Name,Description |
Select Name,Description
} else {
Write-Host Could not find: $a -ForegroundColor "yellow"
}
# If running in the console, wait for input before closing.
if ($Host.Name -eq "ConsoleHost") {
Write-Host "Press any key to continue..."
$Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp") > $null
}
$again = Read-Host 'Would you like to search again? (Y/N)'
} until ($again -eq 'No' -or $again -eq 'n')
Here is a working example using your script with a few changes.
The big change that allowed it to work was piping to Out-Host from using Get-ADComputer
# installs AD module
Import-Module ActiveDirectory
Do {
$a = Read-Host "Enter first or last name of user"
$b = "*$a*"
try {
Get-ADComputer -Filter {Description -like $b} -Properties Name, Description -ErrorVariable MyError |
Select-Object Name,Description |
Out-Host
if ($MyError){
write-host Could not find: $a -foregroundcolor Yellow
}
}
catch {
write-host Could not find: $a -foregroundcolor Red
}
$again = Read-host 'Would you like to search again? (Y/N)'
}
Until (
$again -eq 'No' -or $again -eq 'n'
)