根据MSDN,UserPrinciple
和ComputerPrinciple
类的查找方法(如FindByLogonTime和FindByBadPasswordAttempt)使用UTC时间来过滤结果。但是,测试表明,这些方法似乎以本地时间为输入,而生成的对象使用UTC作为其时间属性,需要将其转换为本地时间。
这是一个示例,该示例似乎正确列出了自本地时间上午6点以来在服务器上尝试登录失败的所有用户:
static void Main()
{
var pc = new PrincipalContext(ContextType.Domain, dcServer);
PrincipalSearchResult<UserPrincipal> uFailed = UserPrincipal.FindByBadPasswordAttempt(pc, DateTime.Now.Date.AddHours(6), MatchType.GreaterThan);
string s = "";
foreach (UserPrincipal u in uFailed)
{
s += u.SamAccountName + ": " + Convert.ToDateTime(u.LastBadPasswordAttempt).ToLocalTime().ToString() + "\r\n";
}
Console.Write(s);
Console.Read();
}
请注意LastBadPasswordAttempt属性的UTC转换,但不在FindByBadPasswordAttempt筛选器中。
我担心将其投入生产,却不知道我是否有可能遗漏某些东西,或者MSDN文档是否错误。代码在查询的DC上运行,因此应该没有时区问题。
MSDN文档是准确的,您只需要注意传递.Kind
的DateTime
值的属性即可。
如果深入研究参考源或进行反汇编,您会发现DateTime
所传递的值最终会传递给DateTime.ToFileTimeUtc
,这确实会Kind
考虑到其行为。
因此,您可以传递基于的值DateTime.UtcNow
,该值为,具有.Kind
,DateTimeKind.Utc
并且可以正常工作;或者您可以像当前所做的那样传递值DateTime.Now
,并且传递具有的.Kind
,DateTimeKind.Local
并且本地时间将在查询之前转换为UTC。只要确保您意识到这是运行代码的计算机的本地时间即可。如果有可能与您的用户所在的时区不是同一时区,那么您可能需要使用TimeZoneInfo
该时间来获得与其他本地时区等效的UTC时间。
如果由于某种原因您决定传递自己构建的日期,则可能会有DateTimeKind.Unspecified
。对于此特定功能,将其视为UTC。并非所有日期/时间函数都适用,因此请务必小心。
另外,在输出中,Convert.ToDateTime
当您使用的值已经是时,无需调用DateTime
。因此ToString
,除非计划传递格式说明符,否则甚至不需要此代码中的。再说一次,如果您的用户可能在其他时区,请不要使用.ToLocalTime
,而是使用on上的一种方法进行TimeZoneInfo
转换。
另一项微小的优化,您可以根据需要使用DateTime.Today
代替DateTime.Now.Date
。(除了更具可读性之外,没有什么区别。)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句