转换类型的变体(调度)
Convert variant of type (Dispatch)
我正在尝试使用 Delphi 7 / ADO 为每个用户读取 AD 中的 lastLogonTimeStamp 字段。我的循环可以读取所需的字段。字符串字段很容易使用,但我未能解码时间戳。它的类型是 Variant 和 vartype returns 9 (Dispatch)
我尝试过各种类型转换,包括 INT64(我相信这是时间戳的存储方式)和 varToStr。所有记录都是 vartype 9 除了一个是 vartype 1 可能是因为它是空的。
ADOQuery1: TADOQuery;
ADOQuery1SN: TWideStringField;
ADOQuery1CN: TWideStringField;
ADOQuery1AdsPath: TWideStringField;
ADOQuery1lastLogonTimestamp: TVariantField;
logonfield : variant;
logonfield := ADOQuery1lastLogonTimestamp.value;
stringgrid1.Cells[1,i] := vartostr(logonfield);
我想获取每个用户的上次登录日期,但程序会过滤掉例外情况。我可以得到字符串字段。但我得到:
错误:无法将类型(调度)转换为类型(字符串)
[或我尝试过的任何其他东西! TDateTime, INT64 ...]
变体类型 9 (varDispatch
) 表示 COM IDispatch
对象接口。在这种情况下这是有道理的,因为 lastLogonTimeStamp
是 FILETIME
UTC format, wrapped in a COM object to expose access to its LowPart
and HighPart
members. See Attributes for AD Users : lastLogonTimestamp and Acitve Directory: Handling attributes with LARGE_INTEGER / INTEGER8 syntax 中的 Integer8
以获取更多详细信息。
尝试这样的事情:
function LargeIntegerToDate(value: Variant): TDateTime;
var
ftUTC, ftLocal: TFileTime;
st: TSystemTime;
begin
Result := 0;
if VarIsNull(value) then
Exit;
if not VarIsType(varDispatch) then
raise Exception.Create('Unsupported type');
ftUTC.dwHighDateTime := value.HighPart;
ftUTC.dwLowDateTime := value.LowPart;
if (ftUTC.dwLowDateTime = 0) and (ftUTC.dwHighDateTime = 0) then
begin
Result := EncodeDate(1601, 1, 1);
Exit;
end;
try
FileTimeToLocalFileTime(ftUTC, ftLocal);
FileTimeToSystemTime(ftLocal, st);
Result := SystemTimeToDateTime(st);
except
end;
end;
...
var
logonfield : Variant;
begin
logonfield := ADOQuery1lastLogonTimestamp.Value;
StringGrid1.Cells[1, i] := DateToStr(LargeIntegerToDate(logonfield));
end;
我正在尝试使用 Delphi 7 / ADO 为每个用户读取 AD 中的 lastLogonTimeStamp 字段。我的循环可以读取所需的字段。字符串字段很容易使用,但我未能解码时间戳。它的类型是 Variant 和 vartype returns 9 (Dispatch)
我尝试过各种类型转换,包括 INT64(我相信这是时间戳的存储方式)和 varToStr。所有记录都是 vartype 9 除了一个是 vartype 1 可能是因为它是空的。
ADOQuery1: TADOQuery;
ADOQuery1SN: TWideStringField;
ADOQuery1CN: TWideStringField;
ADOQuery1AdsPath: TWideStringField;
ADOQuery1lastLogonTimestamp: TVariantField;
logonfield : variant;
logonfield := ADOQuery1lastLogonTimestamp.value;
stringgrid1.Cells[1,i] := vartostr(logonfield);
我想获取每个用户的上次登录日期,但程序会过滤掉例外情况。我可以得到字符串字段。但我得到:
错误:无法将类型(调度)转换为类型(字符串) [或我尝试过的任何其他东西! TDateTime, INT64 ...]
变体类型 9 (varDispatch
) 表示 COM IDispatch
对象接口。在这种情况下这是有道理的,因为 lastLogonTimeStamp
是 FILETIME
UTC format, wrapped in a COM object to expose access to its LowPart
and HighPart
members. See Attributes for AD Users : lastLogonTimestamp and Acitve Directory: Handling attributes with LARGE_INTEGER / INTEGER8 syntax 中的 Integer8
以获取更多详细信息。
尝试这样的事情:
function LargeIntegerToDate(value: Variant): TDateTime;
var
ftUTC, ftLocal: TFileTime;
st: TSystemTime;
begin
Result := 0;
if VarIsNull(value) then
Exit;
if not VarIsType(varDispatch) then
raise Exception.Create('Unsupported type');
ftUTC.dwHighDateTime := value.HighPart;
ftUTC.dwLowDateTime := value.LowPart;
if (ftUTC.dwLowDateTime = 0) and (ftUTC.dwHighDateTime = 0) then
begin
Result := EncodeDate(1601, 1, 1);
Exit;
end;
try
FileTimeToLocalFileTime(ftUTC, ftLocal);
FileTimeToSystemTime(ftLocal, st);
Result := SystemTimeToDateTime(st);
except
end;
end;
...
var
logonfield : Variant;
begin
logonfield := ADOQuery1lastLogonTimestamp.Value;
StringGrid1.Cells[1, i] := DateToStr(LargeIntegerToDate(logonfield));
end;