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 标识的计算机林中找到全局目录,如果 ComputerNameNULL,则为本地计算机。

如果 DomainNameNULL ,并且 Flags 参数不包含 DS_GC_SERVER_REQUIRED 标志, 则 ComputerName 设置为 由 ComputerName 标识的计算机的主域的默认域名。

[in] DomainGuid

指向指定所查询域的 GUIDGUID 结构的指针。 如果 DomainGuid 不是 NULL ,并且找不到 由 DomainNameComputerName 指定的域, DsGetDcName 会尝试在 域具有 DomainGuid 指定的 GUID 的域中找到域控制器。

[in] SiteName

指向 null 终止的字符串的指针,该字符串指定返回的域控制器应实际存在的站点的名称。 如果此参数为 NULLDsGetDcName 会尝试返回离 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_REQUIREDDS_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_NAMEDS_IS_FLAT_NAME。 如果未指定两个标志, DsGetDcName 可能需要更长的时间才能查找域控制器,因为它可能必须同时搜索 DNS 样式和平面名称。

DS_IS_FLAT_NAME

指定 DomainName 参数是平面名称。 此标志不能与 DS_IS_DNS_NAME 标志组合在一起。

DS_KDC_REQUIRED

要求返回的域控制器当前正在运行 Kerberos 密钥分发中心服务。 此标志不能与 DS_PDC_REQUIREDDS_GC_SERVER_REQUIRED 标志组合在一起。

DS_ONLY_LDAP_NEEDED

指定返回的服务器为 LDAP 服务器。 返回的服务器不一定是域控制器。 服务器中没有暗示其他服务。 返回的服务器不一定具有可写 配置 容器和可写 架构 容器。 返回的服务器不一定用于创建或修改安全原则。 此标志可与 DS_GC_SERVER_REQUIRED 标志一起使用,以返回同时托管全局目录服务器的 LDAP 服务器。 返回的全局目录服务器不一定是域控制器。 服务器中没有暗示其他服务。 如果指定了此标志,则忽略 DS_PDC_REQUIREDDS_TIMESERV_REQUIREDDS_GOOD_TIMESERV_PREFERREDDS_DIRECTORY_SERVICES_PREFEREDDS_DIRECTORY_SERVICES_REQUIREDDS_KDC_REQUIRED 标志。

DS_PDC_REQUIRED

要求返回的域控制器为该域的主域控制器。 此标志不能与 DS_KDC_REQUIREDDS_GC_SERVER_REQUIRED 标志组合在一起。

DS_RETURN_DNS_NAME

指定 DomainControllerNameDomainControllerInfo 的 DomainControllerInfo 成员中返回的名称应为 DNS 名称。 如果 DNS 名称不可用,则返回错误。 不能使用 DS_RETURN_FLAT_NAME 标志指定此标志。 此标志表示 DS_IP_REQUIRED 标志。

DS_RETURN_FLAT_NAME

指定 DomainControllerNameDomainControllerInfo 的 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 解析名称,但找到的域控制器的域不一定与客户端加入的域匹配。

注意此标志组策略启用。 如果启用“下一个最靠近站点”策略设置,则会针对所有可用但未配置的网络适配器的计算机启用“下一个最近的站点 DC 位置”。 如果禁用策略设置,默认情况下不会对所有可用但未配置的网络适配器的计算机使用下一个最靠近站点 DC 位置。 但是,如果使用 DS_TRY_NEXTCLOSEST_SITE 标志显式进行 DC 定位符调用, DsGetDcName 将遵循下一个最接近的网站行为。 如果未配置此策略设置,则默认情况下不会对所有可用但未配置的网络适配器的计算机使用下一个最靠近站点 DC 位置。 如果显式使用 DS_TRY_NEXTCLOSEST_SITE 标志,将使用下一个最接近的网站行为。
 

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 服务。 如果 ComputerNameNULL,则在本地计算机上处理该函数。

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 分钟) 的值。

注意ForceRediscoveryInterval 的注册表设置已启用组策略。 如果禁用策略设置,则默认每隔 12 小时对计算机使用 Force Rediscovery。 如果未配置此策略设置,则强制重新发现默认每隔 12 小时将用于计算机,除非注册表中的本地计算机设置是不同的值。
 
请注意,如果指定 了DS_BACKGROUND_ONLY 标志, DsGetDcName 永远不会尝试重新发现域控制器名称,因为该标志的点是强制 DsGetDcName 使用缓存的域控制器名称,即使它已过期。

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 与启动会话时使用的名称相同。

注意 在启动跟踪会话时,所跟踪进程的注册表项必须存在于注册表中。 会话启动时,进程将根据进程名称和可选 PID) 是否存在注册表项来验证它是否应生成跟踪消息 (。 此过程仅在会话开始时检查注册表。 注册表中发生的任何更改之后不会对跟踪产生任何影响。
 

注意

dsgetdc.h 标头将 DsGetDcName 定义为别名,该别名根据 UNICODE 预处理器常量的定义自动选择此函数的 ANSI 或 Unicode 版本。 将非中性编码别名与非编码中性代码混合使用可能会导致编译或运行时错误不匹配。 有关详细信息,请参阅 函数原型的约定

要求

   
最低受支持的客户端 Windows Vista
最低受支持的服务器 Windows Server 2008
目标平台 Windows
标头 dsgetdc.h
Library NetApi32.lib
DLL NetApi32.dll

另请参阅

DOMAIN_CONTROLLER_INFO

目录服务函数

DsGetSiteName

DsValidateSubnetName

GUID

NetApiBufferFree

Windows 时间服务