WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

ADSI
plus

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Return Closest Domain Controller using ADSI


Question:

How can I retrieve the name of the closest domain controller using ADSI functions. I have used wntGetDC (1) to return the PDC, but I'm not sure if wntGetDC (0) will give me what I need. We are running a script that performs various ADSI calls domestically and internationally. It succeeds most of the time, except when running it internationally. The ADSI call wants to come back to the US to get its information, instead of using a closer server at the site. Please help.

Answer:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SiteFunctions.wbt
; Functions for AD Site determination and other site functions
; written by Carlos E Junco Jr
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

if FileLocate("WWADS34I.DLL") == "" then exit
AddExtender("WWADS34I.DLL")

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GetSubnetObj(IPAddress, AsCN)
; Gets SubnetObj that IP Address belongs to
; IPAddress(string) = IPAddress whose subnet membership you need
; SubnetMask(string) = Subnet mask used by host at IPAddress
; DomainName(string) = name of domain in forest or domain controller (i.e. domainname.com or server.domainname.com)
; Returns = site object which IPAddress belongs to, or returns "**None**" if belongs to no subnet object,
; or returns "**Error**" if error occurs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

#definefunction GetSubnetObj(IPAddress, SubnetMask, DomainName)
subnetStr = ""
subnetMaskBits = 0
strADRoot = ""
subnetObjPath = ""

; Check if valid IP Address string
i = ItemCount(IPAddress, ".")
if i != 4 then return "**Error**"
for i = 1 to 4
num = ItemExtract(i, IPAddress, ".")
if !IsNumber(num) then return "**Error**"
if num < 0 || num > 255 then return "**Error**"
next

; Check if valid Subnet Mask string
i = ItemCount(SubnetMask, ".")
if i != 4 then return "**Error**"
for i = 1 to 4
num = ItemExtract(i, SubnetMask, ".")
if !IsNumber(num) then return "**Error**"
if num < 0 || num > 255 then return "**Error**"
next

; Create subnet string
for i = 1 to 4
ipNum = ItemExtract(i, IPAddress, ".")
subnetNum = ItemExtract(i, SubnetMask, ".")
part = ipNum & subnetNum
subnetStr = strcat(subnetStr, part)
if i != 4 then subnetStr = strcat(subnetStr, ".")
; count bits for subnet
for c = 1 to 8
subnetMaskBits = subnetMaskBits + ((subnetNum >> (c - 1)) & 1)
next
next
subnetStr = strcat(subnetStr, "\/", subnetMaskBits)
; Get Subnet Object
strADRoot = dsGetProperty("LDAP://%DomainName%/RootDSE", "configurationNamingContext")
SubnetObjPath = "LDAP://%DomainName%/cn=%subnetStr%,cn=subnets,cn=sites,%strADRoot%"
if !dsisObject(SubnetObjPath) then return "**None**"
; return string
return SubnetObjPath
#endfunction
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GetSiteObj(SubnetObj)
; Gets Site Object associated with subnet object
; SubnetObj(string) = full path to subnet ojbect
; returns Site Object associated to the subnet object or returns "**Error**" if error occurs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#definefunction GetSiteObj(SubnetObj)
siteStr = ""
domainPrefix = ""
; Check if valid object
if !dsisObject(SubnetObj) then return "**Error**"
siteStr = dsGetProperty(SubnetObj, "siteObject")
i = StrIndex(SubnetObj, "/", 8, @FWDSCAN)
domainPrefix = StrSub(SubnetObj, 1, i)
return strcat(domainPrefix, siteStr)

#endfunction
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CreateLDAPChildStr(ParentPath, Child)
; Create LDAP child string
; ParentPath(string) = parent LDAP path
; Child(string) = child object(s) (i.e. "CN=Whatever" or "CN=Whatever,CN=SomethingElse")
; returns full ldap path to child or "" if error
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#definefunction CreateLDAPChildStr(ParentPath, Child)
i = StrIndex(ParentPath, "/", 8, @FWDSCAN)
if i < 9 then return ""
str = StrSub(ParentPath, 1, i)
if str == "" then return ""
str2 = StrSub(ParentPath, i + 1, -1)
if str2 == "" then return ""
return strcat(str, Child, ",", str2)
#endfunction
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GetSiteDCs(SiteObj, DomainName, flags)
; Gets domain controlles in the specified site
; SiteObj(string) = path to site object
; DomainContext(string) = domain whose domain controllers you want, if blank, will get DCs from all domains (i.e. "DC=Domain,DC=com")
; flags(int) = flags specifying kinds of domain controllers, can be added together:
; 1 = Global Catalog Server
; 2 = Bridgehead Server
; returns list of domain controllers or "**Error**" if error occurs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#definefunction GetSiteDCs(SiteObj, DomainContext, flags)
SiteServersPath = ""
ServersPaths = ""
DCsPaths = ""
OnlyGCs = flags & 1
OnlyBHs = flags & 2
DomainContext = StrClean(DomainContext, " ", "", @FALSE, 1)
; Check if valid siteobj
if !dsisObject(SiteObj) then return "**Error**"
SiteServersPath = CreateLDAPChildStr(SiteObj, "CN=Servers")
if SiteServersPath == "" then return "**Error**"
ServersPaths = dsGetChldPath(SiteServersPath, "server")
c = ItemCount(ServersPaths, @TAB)
if c == 0 then return ""
for i = 1 to c
ServerPath = ItemExtract(i, ServersPaths, @TAB)
if ServerPath == "" then return "" ; shouldn't happen
; Check if DC
NTDSSettingsPath = CreateLDAPChildStr(ServerPath, "CN=NTDS Settings")
if !dsisObject(NTDSSettingsPath) then continue
if (OnlyGCs)
isGC = dsGetProperty(NTDSSettingsPath, "options")
if isGC == "" then continue
if !(isGC & 1) then continue
endif
if (OnlyBHs)
transports = dsGetProperty(ServerPath, "bridgeheadTransportList")
if transports == "" then continue
endif
if DomainContext != ""
hostname = dsGetProperty(ServerPath, "dNSHostName")
if hostname == "" then return "" ; shouldn't happen
defNamingContext = dsGetProperty("LDAP://%hostname%/RootDSE", "defaultNamingContext")
defNamingContext = StrClean(defNamingContext, " ", "", @FALSE, 1)
if stricmp(defNamingContext, DomainContext) != 0 then continue
endif
DCsPaths = ItemInsert(ServerPath, -1, DCsPaths, @TAB)
next
return DCsPaths
#endfunction

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Test 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

UserAccount = "admin1@subdomain.root.domain.com"
pass = AskPassword("Enter Password", UserAccount)
dsSetCredent(UserAccount, pass)

; You would get the IP and subnet of the machine the script is running on for closest DC or Site.
subnet = GetSubnetObj("10.128.200.63", "255.255.255.0", "subdomain.root.domain.com")
Message("subnet", subnet)
site = GetSiteObj(subnet)
Message("site", site)
DCs = GetSiteDCs(site, "", 1)
AskItemList("Domain Controllers", DCs, @TAB, @unsorted, @single)

Article ID:   W15820
File Created: 2004:03:30:15:41:00
Last Updated: 2004:03:30:15:41:00