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

PowerShell函数查询AD未登录计算机返回空列表问题求助

问题诊断与修复

你的函数返回空结果的核心问题是Group-Object后的过滤逻辑错误,同时还有几个次要的语法/逻辑问题,下面逐一说明:

1. 核心错误:Group-Object后的属性访问错误

Group-Object Name会将同一计算机的多DC查询结果分组,生成的组对象包含Name、Count、Group属性,没有直接的LastLogon属性。你原代码中的Where-Object LastLogon -ge $inactiveDateValue是在过滤不存在的属性,PowerShell会将未定义的属性视为$null,而$null -ge 任意值的结果是$false,因此返回空;当改为-le时,$null -le 任意值结果为$true,所以返回所有组,即全部计算机。

正确的逻辑是:对每个计算机组,提取组内所有LastLogon值的最大值(即该计算机的最新登录时间),再判断这个最大值是否早于/等于你设定的不活跃阈值(因为你要找的是长时间未登录的机器,即最新登录时间在$inactiveDate之前)。

2. 次要问题:AD Filter的变量解析错误

Get-ADComputer -Filter 'Enabled -eq $true'中的单引号会阻止$true的变量解析,AD服务会将$true视为字符串,而非布尔值,导致过滤条件失效。应该改用双引号,或者直接写AD语法认可的TRUE。

3. 冗余的日期转换

[System.DateTime]$todaysDate = (Get-Date -Format d)将日期转为字符串再转回DateTime是完全冗余的,直接用Get-Date即可完成日期计算。


修正后的函数代码

Function Get-OldNames {
    # 查询指定OU中长时间未登录的启用状态计算机,聚合所有DC的LastLogon数据获取最新登录时间
    [CmdletBinding()]
    param(
        # 目标OU的LDAP路径
        [string]$TargetOU = "OU=Computers,OU=NewYork,OU=US,DC=contoso,DC=com",
        # 未活跃天数(负数表示向前推N天)
        [int]$InactiveDays = -90
    )

    # 计算不活跃阈值的FileTime格式(AD存储LastLogon的格式)
    $inactiveDate = (Get-Date).AddDays($InactiveDays)
    $inactiveDateFileTime = $inactiveDate.ToFileTime()

    # 获取所有域控制器
    $domainControllers = Get-ADDomainController -Filter *

    # 聚合所有DC的计算机登录数据
    $allComputerLogs = foreach ($dc in $domainControllers) {
        Write-Host "Querying $($dc.Name)..."
        Get-ADComputer -Filter "Enabled -eq $true" -SearchBase $TargetOU -Server $dc.Name -Properties LastLogon |
            Select-Object Name, LastLogon, @{Name='LastLogonAsDate';Expression={
                # 处理LastLogon为0的情况(从未登录过的计算机)
                if ($_.LastLogon -eq 0) { [DateTime]::MinValue }
                else { [DateTime]::FromFileTime($_.LastLogon) }
            }}
    }

    # 按计算机名分组,提取每组最新的登录时间,筛选未活跃机器
    $inactiveComputers = $allComputerLogs |
        Group-Object Name |
        ForEach-Object {
            # 获取该计算机的最新LastLogon(FileTime值越大时间越新)
            $latestLogon = $_.Group | Sort-Object LastLogon -Descending | Select-Object -First 1
            # 判断最新登录时间是否早于阈值
            if ($latestLogon.LastLogon -le $inactiveDateFileTime) {
                [PSCustomObject]@{
                    Name = $_.Name
                    LatestLastLogon = $latestLogon.LastLogonAsDate
                    DomainController = $latestLogon.PSComputerName
                }
            }
        }

    # 返回结果(如果只需要名称,可改为return $inactiveComputers.Name)
    return $inactiveComputers
}

关键改进说明

  • 改为使用Param()块定义参数,提升函数的灵活性和可复用性
  • 处理了LastLogon为0的边界情况(从未登录的计算机)
  • 分组后正确提取每个计算机的最新登录记录,并与阈值对比
  • 修复了AD Filter的变量解析问题
  • 返回包含更多信息的自定义对象(如需仅返回名称,直接取$inactiveComputers.Name即可)

内容的提问来源于stack exchange,提问作者Ed R.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 07:44:58