我有一个PowerShell脚本,我们使用了几个东西,当一台新的计算机已经安装了Windows 7的时候,我们也在Windows 10上使用它,而且一切正常。 它在第一次login时运行,然后由技术人员决定,如果计算机必须join域。 但是我们需要find一种方法在脚本中执行检查,以查看计算机名是否已经存在于特定的OU中,技术人员将join。 我们不想将Active Directory模块添加到所有新的Windows 7 PC上,因为这只需要一次。
我们如何才能在PowerShell脚本中实现这样的检查,必须能够在未join的Windows 7 PC上运行,并使用脚本初始运行时技术人员已经键入的凭据?
更新 :
在我们开始部署Windows 10(与Windows 7一起)之后,我们以前的可视基本脚本的行为有所不同。 所以我们决定在PowerShell中重写它以适应Windows 7和Windows 10.我们还设法find了在同一个会话中重命名和join域的方法(=只需要1次重启)。 为了pipe理这个,我们在Win32_ComputerSystem的JoinDomainOrWorkGroup中使用一个(也许不受支持的)参数,强制计算机对象join所选的OU,即使对象已经在那里。 如果用户收到一台新的计算机,并且必须给出相同的名称,则会发生这种情况。这就是为什么我需要能够检查该特定OU是否已经存在,并且在继续join之前向技术人员询问是否正确。
新的powershell脚本有很多非英语和技术人员使用脚本的问题(读取主机)。 所以我决定拿出脚本的片段,这涉及到这个问题。
# $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)" }
更新2:我也试图做到这一点,但失败了。 无论如何,它都会返回False。
$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" }
我能够使用本地/非域帐户重新生成Update 2的问题。 LDAP不起作用,GC工作。 我不知道为什么。 如果只是这个查询失败,也许使用GC将是一个可接受的解决方法。
使用常规.NET应用程序的相同查询不会失败。
我在Netlogon.log中注意到了以下内容,但我不认为在我的testing环境中DNS有什么问题:
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" }
我在具有Windows Management Framework 5.1 / PowerShell 5.1的Windows Server 2016 TP5上testing了此问题,并且问题不存在。 我会推测这是PowerShell 5.0的一个问题,并可能在未来的版本/修补程序中解决。
也许你可以创build一个Web服务,然后从任何地方查询它…
例如:创build一个需要一个参数(computername)的PHP脚本,并返回true(如果computername已经join到域中)或false。
然后,您可以从PowerShell脚本中查询此页面,如下所示:(New-Object Net.WebClient).DownloadString(“ http:// url?computername = xxxxx ”)