Windows – Find Computer in AD from non-joined Windows 7

active-directorypowershellwindowswindows 7

I have a powershell script we use for several things, when a new computer has been installed with Windows 7. We also use it on Windows 10, and it all works well.
It runs at first login and the technician then decide, if the computer must be joined the domain or not. But we need to find a way to implement a check in the script, to see if the computername already exist in the specific OU, the technician will join to. We do not want to add the Active Directory module to all new Windows 7 PC's, as this is only needed once.

How can we accomplish to implement such a check in a powershell script, that must be able to run on a non-joined Windows 7 PC, and use the credentials the technician already typed in when the script initially runs?

UPDATE:

After we began to deploy Windows 10 (along with Windows 7), our former visual basic script acted differently. So we decided to rewrite it in powershell to suite both Windows 7 and 10. We also managed to find a way to rename and join the domain in the same session (= only 1 reboot needed). To manage this we use a (perhaps unsupported?) parameter in the JoinDomainOrWorkGroup from Win32_ComputerSystem, that forces the computer object to join the chosen OU, even if the object is already there. This happens if a user receives a new computer, and must have be given the same name.This is why I need to be able to check if it already exist in that specific OU, and ask the technician if this is OK before proceeding to join.

The new powershell script has alot of non-english and questions (read-host) for the technician using the script. So I decided to take out the snippet of the script, that concerns this matter.

# $computername, $ou and $credentials is set before this runs
$domain = "our.domain.com"
$computer = get-wmiobject Win32_ComputerSystem

$ret = $computer.rename($computername,$credentials.getnetworkcredential()).password,$credentials.username)
if ($ret.ReturnValue -eq 0)
{
   $ret = $computer.JoinDomainOrWorkGroup($domain,($credentials.GetNetworkCredential()).Password, $credentials.UserName, $OU,   0x1 + 0x2 + 0x20 + 0x400)

   Switch ($ret.ReturnValue)
   {
    "2224"    { 
                $ret = $computer.JoinDomainOrWorkGroup($domain,$pass,$user,$OU,33)
                if ($ret.ReturnValue -eq 1332) { write-host "Computer already exist in another OU. Either delete or move it before joining" -foregroundcolor red -backgroundcolor yellow}
              }
    "1326"    { Write-Host "Wrong username or password" -foregroundcolor red -backgroundcolor yellow }
    "2691"    { Write-Host "Computer is already joined to this OU" -foregroundcolor red -backgroundcolor yellow }
    "0"       { Write-Host "Computer was joined"-foregroundcolor Green }     
    default   { Write-Host "Undetermined error: $ret" }     
    }
}
else { write-host "Computer was not renamed. Try again ($counter/3)" }

UPDATE 2:
I also tried to do this, but failed. It returned False no matter what.

 $user = $credentials.username
 $pass = ($credentials.getnetworkcredential()).password

 $searchdomain = New-Object DirectoryServices.DirectoryEntry("LDAP://OUR.DOMAIN.COM", $user, $pass)
 $searchdomain.Path = "LDAP://< OU string >"
 $ComputerName = gc env:computername
 $searcher = New-Object System.DirectoryServices.DirectorySearcher($searchdomain)
 $searcher.filter = "(cn=$ComputerName)"
 $searchparm = $searcher.FindOne()
 if (!($searchparm))
 { Write-Host "Doesn't exist - proceed joining this OU" }
 else
 { Write-Host "Already exist - Ask to overwrite existing object" }

Best Answer

I was able to reproduce the issue with Update 2 using a local/non-domain account. LDAP did not work, GC does work. I'm not sure why. If it is only this query that is failing, perhaps using GC would be an acceptable workaround.

The same query using a regular .NET application does not fail.

I did notice the following in the Netlogon.log but I don't think there is anything wrong with the DNS in my test environment:

06/26 18:29:19 [CRITICAL] [3672] NetpDcGetNameIp: <ComputerName>: No data returned from DnsQuery.
06/26 18:29:19 [CRITICAL] [3672] NlBrowserSendDatagram: No transports available
06/26 18:29:19 [CRITICAL] [3672] NetpDcGetNameNetbios: <ComputerName>: Cannot NlBrowserSendDatagram. (ALT) 53
06/26 18:29:19 [CRITICAL] [3672] NetpDcGetName: <ComputerName>: IP and Netbios are both done.

$credentials = Get-Credential
$user = $credentials.username
$pass = ($credentials.getnetworkcredential()).password
$authType = ([System.DirectoryServices.AuthenticationTypes]::Secure -bor [System.DirectoryServices.AuthenticationTypes]::Sealing)
$searchdomain = New-Object System.DirectoryServices.DirectoryEntry("GC://contoso.com", $user, $pass, $authType)
$searchdomain.Path = "GC://OU=Computers,OU=HQ,DC=contoso,DC=com"
$ComputerName = gc env:computername
$searchScope = [System.DirectoryServices.SearchScope]::OneLevel
$searcher = New-Object System.DirectoryServices.DirectorySearcher($searchdomain, $null, $null, $searchScope)
$searcher.filter = "(cn=$ComputerName)"
# FindOne() fails with "The specified domain either does not exist or could not be contacted" if using LDAP instead of GC
$searchparm = $searcher.FindOne()
# Write-Host $searchparm.Path
if (!($searchparm)) { Write-Host "Doesn't exist - proceed joining this OU" } else { Write-Host "Already exist - Ask to overwrite existing object" }

I tested this on Windows Server 2016 TP5 that has Windows Management Framework 5.1/PowerShell 5.1 and the issue does not exist. I would speculate this is an issue with PowerShell 5.0 and may be resolved in future versions/hotfixes.