You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

获取计算机最后登录时间遇Ticks差异问题及正确处理方法求助

问题

我需要从两台域控制器(DC)获取计算机最后登录时间,筛选出自2022年5月1日起未登录的计算机。已将第一台DC的计算机对象(含lastLogon、lastLogontimeStamp属性)存入$KolStacji23变量,第二台DC的存入$KolStacji71变量,随后对比这些属性值。

我的代码如下:

$Nieaktywne = ((Get-Date).AddDays(- 120)).Ticks
foreach ($Stacja23 in $KolStacji23) {
    foreach ($Stacja71 in $KolStacji71) {
        if ($Stacja23.Name -eq $Stacja71.Name) {
            if ((($($Stacja23.LastLogon) -lt $Nieaktywne) -and ($($Stacja71.LastLogon) -lt $Nieaktywne) -and ($($Stacja23.lastLogontimeStamp) -lt $Nieaktywne)) -and ($Stacja23.whenCreated -lt $Nieaktywne)) {
                $Stacja23.Name
                if ($Stacja23.lastLogontimeStamp -gt $Stacja23.LastLogon) {
                    $Stacja23.LastLogon = $Stacja23.lastLogontimeStamp
                }
                if ($Stacja71.LastLogon -gt $Stacja23.LastLogon) {
                    $Stacja23.LastLogon = $Stacja71.LastLogon                       }
                $Stacja23 | Select-Object Name, @{ N = 'lokalizacja'; E = { ($($_.CanonicalName)).split("/")[-3] } }, whenCreated, @{ N = 'LastLogon'; E = { [DateTime]::FromFileTime($_.LastLogon) } }, operatingSystem, Description | Export-Csv -Path $PlikListy -Delimiter ';' -Force -NoClobber -Encoding UTF8 -Append -NoTypeInformation
            }
            Break
        }
    }
}

系统为波兰语,其中“kwietnia”指4月,“sierpnia”指8月,“września”指9月。执行命令发现系统Get-Date的Ticks值与计算机账户属性的Ticks值差异极大:

PS C:\Windows\system32> Get-Date
czwartek, 1 września 2022 13:49:57

PS C:\Windows\system32> (Get-Date).AddDays(- 124)
sobota, 30 kwietnia 2022 13:50:06

PS C:\Windows\system32> ((Get-Date).AddDays(- 124)).Ticks
637869234152030929

而计算机账户属性的Ticks值及转换结果如下:

([DateTime]::FromFileTime($Stacja23.LastLogon))
środa, 22 września 2021 15:48:59

$Stacja23.LastLogon
132767921394245654

[DateTime]::FromFileTime($Stacja23.LastLogontimeStamp)
poniedziałek, 22 sierpnia 2022 19:05:11

$Stacja23.LastLogontimeStamp
133056615112570357

若直接使用[datetime]转换这些属性值,会得到公元400多年的远古日期:

$Stacja23.LastLogontimeStamp
133056615112570357

[datetime]$Stacja23.LastLogon
środa, 22 września 0421 13:48:59

[datetime]$Stacja23.LastLogontimeStamp
poniedziałek, 22 sierpnia 0422 17:05:11

请问计算机账户的这些属性的Ticks计算方式是否不同?该如何正确处理?是否需要添加对应1600年的Ticks值?具体数值是多少?


解决方案

1. 时间格式差异原因

AD中lastLogon和lastLogontimeStamp属性使用的是Windows文件时间格式,和.NET DateTime.Ticks的计数起点完全不同:

  • Windows文件时间:从1601年1月1日UTC开始,以100纳秒为间隔计数
  • .NET DateTime.Ticks:从0001年1月1日开始,以100纳秒为间隔计数

这就是直接用[datetime]转换AD属性值会得到远古日期的原因——两者的起始时间差了1600年左右。

2. 正确处理方式

不需要手动添加1600年的Ticks值,直接使用专门的转换方法和格式匹配的阈值即可:

步骤1:生成格式匹配的阈值时间

把筛选阈值(2022年5月1日)转换成Windows文件时间格式,用来和AD属性值直接比较:

# 定义2022年5月1日为阈值,转换为UTC的Windows文件时间
$Nieaktywne = (Get-Date "2022-05-01").ToUniversalTime().ToFileTime()

注:AD时间属性存储的是UTC时间,所以转换阈值时要统一为UTC,避免时区偏差

步骤2:修正代码中的比较逻辑

直接用转换后的Windows文件时间阈值和AD属性值比较,不需要用.NET的Ticks:
修正后的核心代码片段:

$Nieaktywne = (Get-Date "2022-05-01").ToUniversalTime().ToFileTime()
$thresholdDate = Get-Date "2022-05-01"

foreach ($Stacja23 in $KolStacji23) {
    foreach ($Stacja71 in $KolStacji71) {
        if ($Stacja23.Name -eq $Stacja71.Name) {
            # 比较AD属性的Windows文件时间与阈值
            $isInactive = ($Stacja23.LastLogon -lt $Nieaktywne) -and 
                         ($Stacja71.LastLogon -lt $Nieaktywne) -and 
                         ($Stacja23.lastLogontimeStamp -lt $Nieaktywne) -and
                         # whenCreated是DateTime类型,直接和日期对象比较
                         ($Stacja23.whenCreated -lt $thresholdDate)
            
            if ($isInactive) {
                # 取两个DC和lastLogontimeStamp中的最大时间作为最后登录时间
                $maxLogonTime = [Math]::Max($Stacja23.LastLogon, $Stacja71.LastLogon)
                $maxLogonTime = [Math]::Max($maxLogonTime, $Stacja23.lastLogontimeStamp)
                
                $Stacja23 | Select-Object Name, 
                    @{ N = 'lokalizacja'; E = { $_.CanonicalName.Split("/")[-3] } }, 
                    whenCreated, 
                    @{ N = 'LastLogon'; E = { [DateTime]::FromFileTime($maxLogonTime) } }, 
                    operatingSystem, Description | 
                Export-Csv -Path $PlikListy -Delimiter ';' -Force -NoClobber -Encoding UTF8 -Append -NoTypeInformation
            }
            Break
        }
    }
}

3. 额外说明

  • lastLogon:仅存储在用户/计算机登录的那台DC上,不会同步到其他DC,所以需要从多台DC收集后取最大值
  • lastLogontimeStamp:会在域中同步,但默认最多14天更新一次,精度不如lastLogon,但适合跨DC获取大致的登录时间

内容的提问来源于stack exchange,提问作者KrzychG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 20:36:38