delphi - 转换类型的变体(调度)
问题描述
我正在尝试使用 Delphi 7 / ADO 为每个用户读取 AD 中的 lastLogonTimeStamp 字段。我的循环可以读取所需的字段。字符串字段易于使用,但我未能解码时间戳。它是 Variant 类型,vartype 返回 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
) 表示 COMIDispatch
对象接口。在这种情况下这是有道理的,因为它lastLogonTimeStamp
是UTC 格式,包装在 COM 对象中以公开对其和成员的访问。有关更多详细信息,请参阅AD 用户的属性:lastLogonTimestamp和Acitve 目录:使用 LARGE_INTEGER / INTEGER8 语法处理属性。Integer8
FILETIME
LowPart
HighPart
尝试这样的事情:
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;
推荐阅读
- java - Thymeleaf 如何知道使用哪个端点?
- r - 由于线性假设中的小数,系统在计算上是奇异的
- typescript - 我可以将开放式元组转换为封闭式元组吗?
- node.js - 使用 babel 时模块构建失败
- next.js - 与 React-NextJS 一起使用的 react-apollo 抛出“无法读取未定义的属性”
- r - 使用 dplyr mutuate(或其他包)根据每行中特定值的计数创建新列
- javascript - 如何使用 Jquery 动态添加属性值?
- python - 在 termux 中,如何让 vim python omnicomplete 工作?
- java - 为什么转换 JSON RESTful Webservice 后 POJO 中的一些变量等于 null?
- php - 如何从源代码运行 Composer 和/或允许使用 PhpStorm 进行逐步调试?