如何在Delphi中获取Windows上的完全限定域名

时间:2011-12-09 14:29:30

标签: windows delphi domain-name

我需要在Delphi中为域上的Windows机器获取完全限定的域名。

我尝试使用LookupAccountSid,但它只提供了netbios域名, 在我的情况下它是“内部网”但我需要完整的“intranet.companyname.com”

任何想法?

4 个答案:

答案 0 :(得分:9)

尝试使用GetUserNameEx Windows API函数。

const
  NameUnknown            = 0;
  NameFullyQualifiedDN   = 1;
  NameSamCompatible      = 2;
  NameDisplay            = 3;
  NameUniqueId           = 6;
  NameCanonical          = 7;
  NameUserPrincipal      = 8;
  NameCanonicalEx        = 9;
  NameServicePrincipal   = 10;
  NameDnsDomain          = 12;

function GetUserNameExString(ANameFormat: DWORD): string;
var
  Buf: array[0..256] of Char;
  BufSize: DWORD;
  GetUserNameEx: function (NameFormat: DWORD; lpNameBuffer: LPSTR;
    var nSize: ULONG): BOOL; stdcall;
begin
  Result := '';
  BufSize := SizeOf(Buf) div SizeOf(Buf[0]);
  GetUserNameEx := GetProcAddress(GetModuleHandle('secur32.dll'), 'GetUserNameExA');
  if Assigned(GetUserNameEx) then
    if GetUserNameEx(ANameFormat, Buf, BufSize) then
      Result := Buf;
end;
例如,

使用NameDnsDomain格式,如果您登录“www.mydomain.com”域,则会生成www.mydomain.com\user_name


由于我现在在我们的应用程序中根据自己的需要实现了这个,所以@ iPath的评论是正确的。更好地使用GetComputerNameEx,并根据自己的需要指定其中一个COMPUTER_NAME_FORMAT

Delphi实现看起来像这样(Unicode版本):

interface
...
type
  COMPUTER_NAME_FORMAT = (
    ComputerNameNetBIOS,
    ComputerNameDnsHostname,
    ComputerNameDnsDomain,
    ComputerNameDnsFullyQualified,
    ComputerNamePhysicalNetBIOS,
    ComputerNamePhysicalDnsHostname,
    ComputerNamePhysicalDnsDomain,
    ComputerNamePhysicalDnsFullyQualified,
    ComputerNameMax);

function GetComputerNameExString(ANameFormat: COMPUTER_NAME_FORMAT): WideString;

implementation
...
function GetComputerNameExW(NameType: COMPUTER_NAME_FORMAT; lpBuffer: LPWSTR;
  var nSize: DWORD): BOOL; stdcall; external kernel32 name 'GetComputerNameExW';

function GetComputerNameExString(ANameFormat: COMPUTER_NAME_FORMAT): WideString;
var
  nSize: DWORD;
begin
  nSize := 1024;
  SetLength(Result, nSize);
  if GetComputerNameExW(ANameFormat, PWideChar(Result), nSize) then
    SetLength(Result, nSize)
  else
    Result := '';
end;

答案 1 :(得分:1)

NetGetJoinInformation应该可以正常使用。

MSDN:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa370423(v=vs.85).aspx

示例:

type
  PWKSTA_INFO_100 = ^WKSTA_INFO_100;

  WKSTA_INFO_100 = packed record
    wki100_platform_id: DWord;
    wki100_computername: PWChar;
    wki100_langroup: PWChar;
    wki100_ver_major: DWord;
    wki100_ver_minor: DWord;
  end;

  TNetSetupJoinStatus =
  (
    NetSetupUnknownStatus,
    NetSetupUnjoined,
    NetSetupWorkgroupName,
    NetSetupDomainName
  );

  TNetApiBufferFreeFunction = function(ABuffer: Pointer): DWORD; stdcall;
  TNetWkstaGetInfoFunction  = function(const AServername: PWChar; const ALevel: DWord; const ABufptr: Pointer): DWORD; stdcall;
  TNetGetJoinInformationFunction = function(const AServerName: PWChar; out ANameBuffer: PWChar; out ABufferType: TNetSetupJoinStatus): DWORD; stdcall;

const
  NERR_SUCCESS = 0;

function GetLocalComputerDomainName: string;
var
  NetApiBuffer: Pointer;
  NetApi: THandle;
  NetApiBufferFree: TNetApiBufferFreeFunction;
  NetWkstaGetInfo: TNetWkstaGetInfoFunction;
  NetGetJoinInformation: TNetGetJoinInformationFunction;
  NetSetupJoinStatus: TNetSetupJoinStatus;
  NameBuffer: PWideChar;
begin
  Result := '';
  NetApi := LoadLibrary('netapi32.dll');
  if NetApi <> 0 then
  begin
    NetApiBufferFree      := TNetApiBufferFreeFunction(     GetProcAddress(NetApi, 'NetApiBufferFree'));
    NetGetJoinInformation := TNetGetJoinInformationFunction(GetProcAddress(NetApi, 'NetGetJoinInformation'));
    NetWkstaGetInfo       := TNetWkstaGetInfoFunction(      GetProcAddress(NetApi, 'NetWkstaGetInfo'));
    if @NetApiBufferFree <> nil then
    begin
      if @NetSetupJoinStatus <> nil then
      begin
        if NetGetJoinInformation(nil, NameBuffer, NetSetupJoinStatus) = NERR_SUCCESS then
        begin
          if NetSetupJoinStatus = NetSetupDomainName then
          begin
            Result := NameBuffer;
          end;
          NetApiBufferFree(NameBuffer);
        end;
      end;
    end;
    FreeLibrary(NetApi);
  end;
end;

答案 2 :(得分:1)

我尝试了以上所有方法,但没有成功。最后,我决定只是抓住环境变量。

uses jclSysInfo;

function GetDomain:string;
begin
     result:=GetEnvironmentVariable('USERDNSDOMAIN');
end;

在Server 2008 R2上测试 - 工作正常。返回“server.home.lan”。 导致Windows 7非域连接PC上的空字符串。

答案 3 :(得分:0)

唯一正确使用的api是DsGetDcName。 由于NetGetJoinInformation仍来自“管理员时代”,因此该域是LM兼容的。

这里的代码是C,但是您足够聪明,可以在Delphi中执行相同的操作:)

PDOMAIN_CONTROLLER_INFOW pdomInfo ;
auto result1 = ::DsGetDcNameW(nullptr, nullptr, nullptr, nullptr, DS_DIRECTORY_SERVICE_PREFERRED | DS_RETURN_DNS_NAME, &pdomInfo);
if (result1 == ERROR_SUCCESS) {
auto retVal = SysAllocString(pdomInfo->DomainName);
                ::NetApiBufferFree(pdomInfo);
}