0

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" }
2
  • A computer name must be unique in the domain, so why would the query need to be specific to an OU? Also, why would it need to be a PowerShell script, the contents of which we don't know? Your question may get better results if you share the rationale for what you want to do.
    – Greg Askew
    Jun 26, 2016 at 13:08
  • This looks like Avery painful way to do what MDT could already do
    – Jim B
    Jun 27, 2016 at 3:35

2 Answers 2

1

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.

3
  • When searching in a specific OU using $searchdomain.Path, it also searches sub-OUs, which unfortunately defeat the purpose of my search. Can the search be narrowed down to just that OU in Path?
    – lyngsie
    Jun 27, 2016 at 21:01
  • You need to specify the System.DirectoryServices.SearchScope on the DirectorySearcher. See the updated code above.
    – Greg Askew
    Jun 27, 2016 at 22:40
  • Sorry, I have to withdraw the accepted solution. I did not test properly. It only works if the computer is already a member of the domain. If not it still throws this: FindOne() fails with "The specified domain either does not exist or could not be contacted" using GC.
    – lyngsie
    Jun 30, 2016 at 15:16
0

maybe you can create a web service and then query it from wherever you want...

e.g.: you create a PHP script which requires one parameter (computername) and returns true (if computername is already joined to the domain) or false.

Then you can query this page from within your PowerShell script, like this: (New-Object Net.WebClient).DownloadString("http://url?computername=xxxxx")

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .