dsGetDcNameA 函数 (dsgetdc.h)
DsGetDcName 函数返回指定域中域控制器的名称。 此函数接受其他域控制器选择条件,以指示对具有特定特征的域控制器的首选项。
语法
DSGETDCAPI DWORD DsGetDcNameA(
[in] LPCSTR ComputerName,
[in] LPCSTR DomainName,
[in] GUID *DomainGuid,
[in] LPCSTR SiteName,
[in] ULONG Flags,
[out] PDOMAIN_CONTROLLER_INFOA *DomainControllerInfo
);
参数
[in] ComputerName
指向一个 null 终止的字符串的指针,该字符串指定要处理此函数的服务器的名称。 通常,此参数为 NULL,指示使用本地计算机。
[in] DomainName
指向一个 null 终止的字符串的指针,该字符串指定要查询的域或应用程序分区的名称。 此名称可以是 DNS 样式名称,例如,fabrikam.com 或平面样式名称,例如 Fabrikam。 如果指定了 DNS 样式名称,可以使用或不使用尾随句点指定该名称。
如果 Flags 参数包含 DS_GC_SERVER_REQUIRED 标志, 则 DomainName 必须是林的名称。 在这种情况下,如果 DomainName 指定不是林根的名称,DsGetDcName 将失败。
如果 Flags 参数包含 DS_GC_SERVER_REQUIRED 标志且 DomainName 为 NULL,则 DsGetDcName 会尝试在 ComputerName 标识的计算机林中找到全局目录,如果 ComputerName 为 NULL,则为本地计算机。
如果 DomainName 为 NULL ,并且 Flags 参数不包含 DS_GC_SERVER_REQUIRED 标志, 则 ComputerName 设置为 由 ComputerName 标识的计算机的主域的默认域名。
[in] DomainGuid
指向指定所查询域的 GUID 的 GUID 结构的指针。 如果 DomainGuid 不是 NULL ,并且找不到 由 DomainName 或 ComputerName 指定的域, DsGetDcName 会尝试在 域具有 DomainGuid 指定的 GUID 的域中找到域控制器。
[in] SiteName
指向 null 终止的字符串的指针,该字符串指定返回的域控制器应实际存在的站点的名称。 如果此参数为 NULL, DsGetDcName 会尝试返回离 ComputerName 指定的计算机的站点最近的站点中的域控制器。 默认情况下,此参数应为 NULL。
[in] Flags
包含一组标志,这些标志提供用于处理请求的其他数据。 此参数可以是以下值的组合。
DS_AVOID_SELF
从域控制器调用时,指定返回的域控制器名称不应为当前计算机。 如果当前计算机不是域控制器,则忽略此标志。 此标志可用于获取域中另一个域控制器的名称。
DS_BACKGROUND_ONLY
如果未指定 DS_FORCE_REDISCOVERY 标志,此函数将使用缓存的域控制器数据。 如果缓存的数据超过 15 分钟,则通过 ping 域控制器刷新缓存。 如果指定了此标志,即使缓存的数据已过期,也会避免此刷新。 如果 定期调用 DsGetDcName 函数,则应使用此标志。
DS_DIRECTORY_SERVICE_PREFERRED
DsGetDcName 尝试查找支持目录服务函数的域控制器。 如果支持目录服务的域控制器不可用, DsGetDcName 将返回非目录服务域控制器的名称。 但是,在尝试查找目录服务域控制器超时后, DsGetDcName 仅返回非目录服务域控制器。
DS_DIRECTORY_SERVICE_REQUIRED
要求返回的域控制器支持目录服务。
DS_DIRECTORY_SERVICE_6_REQUIRED
要求返回的域控制器运行 Windows Server 2008 或更高版本。
DS_DIRECTORY_SERVICE_8_REQUIRED
要求返回的域控制器Windows Server 2012或更高版本运行。
DS_FORCE_REDISCOVERY
强制忽略缓存的域控制器数据。 如果未指定 DS_FORCE_REDISCOVERY 标志, DsGetDcName 可能会返回缓存的域控制器数据。 如果指定了此标志, 则 DsGetDcName 不会使用缓存信息 (如果存在) ,而是会执行新的域控制器发现。
此标志不应在正常情况下使用,因为使用缓存的域控制器信息具有更好的性能特征,有助于确保所有应用程序一致地使用同一域控制器。 只有在应用程序确定在没有此标志) 的情况下调用 时 DsGetDcName 返回的域控制器 (且无法访问此标志后,才应使用此标志。 在这种情况下,应用程序应使用此标志重复 DsGetDcName 调用,以确保忽略任何) 且发现可访问的域控制器时 (未使用的缓存信息。
DS_GC_SERVER_REQUIRED
要求返回的域控制器为使用此域作为根的域目录林的全局目录服务器。 如果设置了此标志并且 DomainName 参数不为 NULL, 则 DomainName 必须指定林名称。 此标志不能与 DS_PDC_REQUIRED 或 DS_KDC_REQUIRED 标志组合在一起。
DS_GOOD_TIMESERV_PREFERRED
DsGetDcName 尝试查找可靠时间服务器的域控制器。 可以将 Windows 时间服务配置为将一个或多个域控制器声明为可靠的时间服务器。 有关详细信息,请参阅 Windows 时间服务 文档。 此标志仅供 Windows 时间服务使用。
DS_IP_REQUIRED
此参数指示域控制器必须具有 IP 地址。 在这种情况下,DsGetDcName 会将域控制器的 Internet 协议地址置于 DomainControllerInfo 的 DomainControllerAddress 成员中。
DS_IS_DNS_NAME
指定 DomainName 参数是 DNS 名称。 此标志不能与 DS_IS_FLAT_NAME 标志组合在一起。
指定 DS_IS_DNS_NAME 或 DS_IS_FLAT_NAME。 如果未指定两个标志, DsGetDcName 可能需要更长的时间才能查找域控制器,因为它可能必须同时搜索 DNS 样式和平面名称。
DS_IS_FLAT_NAME
指定 DomainName 参数是平面名称。 此标志不能与 DS_IS_DNS_NAME 标志组合在一起。
DS_KDC_REQUIRED
要求返回的域控制器当前正在运行 Kerberos 密钥分发中心服务。 此标志不能与 DS_PDC_REQUIRED 或 DS_GC_SERVER_REQUIRED 标志组合在一起。
DS_ONLY_LDAP_NEEDED
指定返回的服务器为 LDAP 服务器。 返回的服务器不一定是域控制器。 服务器中没有暗示其他服务。 返回的服务器不一定具有可写 配置 容器和可写 架构 容器。 返回的服务器不一定用于创建或修改安全原则。 此标志可与 DS_GC_SERVER_REQUIRED 标志一起使用,以返回同时托管全局目录服务器的 LDAP 服务器。 返回的全局目录服务器不一定是域控制器。 服务器中没有暗示其他服务。 如果指定了此标志,则忽略 DS_PDC_REQUIRED、 DS_TIMESERV_REQUIRED、 DS_GOOD_TIMESERV_PREFERRED、 DS_DIRECTORY_SERVICES_PREFERED、 DS_DIRECTORY_SERVICES_REQUIRED和 DS_KDC_REQUIRED 标志。
DS_PDC_REQUIRED
要求返回的域控制器为该域的主域控制器。 此标志不能与 DS_KDC_REQUIRED 或 DS_GC_SERVER_REQUIRED 标志组合在一起。
DS_RETURN_DNS_NAME
指定 DomainControllerName 和 DomainControllerInfo 的 DomainControllerInfo 成员中返回的名称应为 DNS 名称。 如果 DNS 名称不可用,则返回错误。 不能使用 DS_RETURN_FLAT_NAME 标志指定此标志。 此标志表示 DS_IP_REQUIRED 标志。
DS_RETURN_FLAT_NAME
指定 DomainControllerName 和 DomainControllerInfo 的 DomainControllerInfo 成员中返回的名称应为平面名称。 如果平面名称不可用,则返回错误。 不能使用 DS_RETURN_DNS_NAME 标志指定此标志。
DS_TIMESERV_REQUIRED
要求返回的域控制器当前正在运行 Windows 时间服务。
DS_TRY_NEXTCLOSEST_SITE
指定此标志后, DsGetDcName 会尝试在调用方所在的同一站点中找到域控制器。 如果未找到此类域控制器,它将找到可以提供拓扑信息的域控制器,并调用 DsBindToISTG 以获取绑定句柄,然后通过 UDP 调用 DsQuerySitesByCost 以确定“下一个最近的站点”,最后缓存找到的站点的名称。 如果未在该站点中找到域控制器, 则 DsGetDcName 将回退到查找域控制器的默认方法上。
如果此标志与输入参数 SiteName 中的非 NULL 值结合使用,则会引发 ERROR_INVALID_FLAGS 。
此外,与 DS_TRY_NEXT_CLOSEST_SITE 一起使用的搜索类型特定于网站,因此,如果将此标志与 DS_PDC_REQUIRED结合使用,则忽略此标志。 最后,当与DS_RETURN_FLAT_NAME一起使用时, 将 忽略 DS_TRY_NEXTCLOSEST_SITE ,因为使用 NetBIOS 解析名称,但找到的域控制器的域不一定与客户端加入的域匹配。
DS_WRITABLE_REQUIRED
要求返回的域控制器可写;也就是说,托管目录服务的可写副本。
DS_WEB_SERVICE_REQUIRED
要求返回的域控制器当前正在运行 Active Directory Web 服务。
[out] DomainControllerInfo
指向 PDOMAIN_CONTROLLER_INFO 值的指针,该值接收指向包含所选域控制器数据的 DOMAIN_CONTROLLER_INFO 结构的指针。 此结构由 DsGetDcName 分配。 当不再需要该函数时,调用方必须使用 NetApiBufferFree 函数释放结构。
返回值
如果函数返回域控制器数据,则返回值 ERROR_SUCCESS。
如果函数失败,则返回值可以是以下错误代码之一。
注解
DsGetDcName 函数将发送到 ComputerName 指定的远程计算机上的 Netlogon 服务。 如果 ComputerName 为 NULL,则在本地计算机上处理该函数。
DsGetDcName 不验证返回的域控制器名称是否是实际域控制器或全局目录的名称。 如果需要相互身份验证,调用方必须执行身份验证。
DsGetDcName 不需要对指定域进行任何特定访问。 默认情况下,此函数不确保返回的域控制器当前可用。 相反,调用方应尝试使用返回的域控制器。 如果域控制器不可用,调用方应再次调用 DsGetDcName 函数,并指定 DS_FORCE_REDISCOVERY 标志。
响应时间
使用 DsGetDcName 时请注意以下计时详细信息:- DsGetDcName 进行网络调用,可能需要几秒钟到一分钟的时间,具体取决于网络流量、拓扑、DC 负载等。
- 不建议从 UI 或其他计时关键线程调用 DsGetDcName 。
- DC 定位器确实使用优化的逻辑来尽快提供 DC 信息。 它还使用站点上的缓存信息联系最近的 DC。
有关域控制器粘性的说明
在Active Directory 域服务中,域控制器定位器函数旨在使客户端找到首选域控制器后,除非域控制器停止响应或重启客户端,否则客户端将不会查找另一个域控制器。 这称为“域控制器粘性”。 由于工作站通常运行数月而没有问题或重启,因此此行为的一个意外后果是,如果特定域控制器进行维护,则连接到该控制器的所有客户端都会将其连接转移到另一个域控制器。 但是,当域控制器备份时,任何客户端都不会重新连接到它,因为客户端不会经常重启。 这可能会导致负载均衡问题。以前,此问题的最常见解决方案是在定期使用DS_FORCE_REDISCOVERY
标志调用 DsGetDcName 的每个客户端计算机上部署脚本。 这是一个有点繁琐的解决方案,因此 Windows Server 2008 和 Windows Vista 引入了一种导致域控制器粘性问题的新机制。
每当 DsGetDcName 从其缓存中检索域控制器名称时,它会检查此缓存条目是否已过期,如果是,则放弃该域控制器名称并尝试重新发现域控制器名称。 缓存项的生命周期由以下注册表项中的值控制
\ HKEY_LOCAL_MACHINE系统\CurrentControlSet\服务\Netlogon\参数\ForceRediscoveryInterval
和
\ HKEY_LOCAL_MACHINE软件\政策\微软\Netlogon\参数\ForceRediscoveryInterval
这些注册表项中的值的类型 为 REG_DWORD。 它们指定 DsGetDcName 应尝试重新发现域控制器名称之前的长度(以秒为单位)。 默认值为 43200 秒, (12 小时) 。 如果 ForceRediscoveryInterval 注册表项的值设置为 0,则客户端始终执行重新发现。 如果该值设置为4294967295,缓存永远不会过期,并且缓存的域控制器将继续使用。 建议不要将 ForceRediscoveryInterval 注册表项设置为小于 3600 秒 (60 分钟) 的值。
DsGetDcName 中的 ETW 跟踪
若要打开 DSGetDcName的 ETW 跟踪,请创建以下注册表项:\ HKEY_LOCAL_MACHINE系统\CurrentControlSet\服务\DCLocator\跟踪
密钥的结构如下:
String ProcessName
DWORD PID <optional>
ProcessName 必须是完整名称,包括要获取其跟踪信息的进程的扩展。 仅当存在同名的多个进程时,才需要 PID。 如果已定义,则仅启用具有该 PID 的进程进行跟踪。 不能仅跟踪 3 个 (或更多) 进程中的 2 个具有相同名称的进程。 如果存在同一进程名称的多个实例且未指定 PID,则将为所有实例启用跟踪) ,则可以启用一个实例或所有实例 (。
例如,这会跟踪App1.exe和App2.exe的所有实例,但仅跟踪 PID 为 999 的App3.exe实例:
App1.exe
App2.exe
App3.exe
PID 999
运行以下命令以启动跟踪会话:
tracelog.exe -start <sessionname> -guid #cfaa5446-c6c4-4f5c-866f-31c9b55b962d -f <filename> -flag <traceFlags>
sessionname 是为跟踪会话提供的名称。 DCLocator 跟踪提供程序的 guid 是“cfaa5446-c6c4-4f5c-866f-31c9b55b962d”。 filename 是写入事件的日志文件的名称。 traceFlags 是以下一个或多个标志,表示要跟踪哪些区域:
标志 | 十六进制值 | 说明 |
---|---|---|
DCLOCATOR_MISC | 0x00000002 | 其他调试 |
DCLOCATOR_MAILSLOT | 0x00000010 | Mailslot 邮件 |
DCLOCATOR_SITE | 0x00000020 | 站点 |
DCLOCATOR_CRITICAL | 0x00000100 | 重要错误 |
DCLOCATOR_SESSION_SETUP | 0x00000200 | 受信任的域维护 |
DCLOCATOR_DNS | 0x00004000 | 名称注册 |
DCLOCATOR_DNS_MORE | 0x00020000 | 详细名称注册 |
DCLOCATOR_MAILBOX_TEXT | 0x02000000 | 详细邮箱邮件 |
DCLOCATOR_SITE_MORE | 0x08000000 | 详细网站 |
运行以下命令以停止跟踪会话:
tracelog.exe -stop <sessionname>
sessionname 与启动会话时使用的名称相同。
注意
dsgetdc.h 标头将 DsGetDcName 定义为别名,该别名根据 UNICODE 预处理器常量的定义自动选择此函数的 ANSI 或 Unicode 版本。 将非中性编码别名与非编码中性代码混合使用可能会导致编译或运行时错误不匹配。 有关详细信息,请参阅 函数原型的约定。
要求
最低受支持的客户端 | Windows Vista |
最低受支持的服务器 | Windows Server 2008 |
目标平台 | Windows |
标头 | dsgetdc.h |
Library | NetApi32.lib |
DLL | NetApi32.dll |