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 标志,并且 DomainNameNULL,DsGetDcName 会尝试在 ComputerName 标识的计算机的林中找到全局目录,如果 ComputerNameNULL,该计算机是本地计算机。

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

[in] DomainGuid

指向 GUID 结构的指针,该结构指定所查询域的 GUID 。 如果 DomainGuid 不是 NULL ,并且找不到 由 DomainNameComputerName 指定的域, 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_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

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

DS_RETURN_FLAT_NAME

指定 DomainControllerInfo 的 DomainControllerNameDomainName 成员中返回的名称应为平面名称。 如果平面名称不可用,则返回错误。 不能使用 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 域服务 中,域控制器定位器功能设计为,一旦客户端找到首选域控制器,客户端将不会查找另一个域控制器,除非该域控制器停止响应或客户端重新启动。 这称为“域控制器粘性”。 由于工作站通常运行数月而不会出现问题或重启,因此此行为的一个意外后果是,如果特定域控制器因维护而关闭,则连接到该域控制器的所有客户端都会将其连接转移到另一个域控制器。 但是,当域控制器恢复时,客户端不会重新连接到它,因为客户端不会经常重启。 这可能会导致负载均衡问题。

以前,此问题的最常见解决方案是在每台使用 标志定期调用 DsGetDcNameDS_FORCE_REDISCOVERY 的客户端计算机上部署一个脚本。 这是一个有点繁琐的解决方案,因此 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 小时对计算机使用强制重新发现。 如果未配置此策略设置,默认情况下每隔 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 时间服务