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

PowerShell查询特定设备最后登录活动的问题求助

问题分析与解决建议

核心问题

你需要获取Azure门户「用户>设备」页面中「活动」列的设备登录时间,但使用Get-AzureADAuditSignInLogs的两种写法均无返回结果,同时脚本混合使用了Microsoft Graph PowerShell模块(Connect-MgGraph、Get-Mg* cmdlet)和AzureAD模块(Connect-AzureAD、Get-AzureADAuditSignInLogs),这可能导致权限或语法适配问题。

问题排查与修复步骤

1. 权限缺失

Get-AzureADAuditSignInLogs需要AuditLog.Read.All和Directory.Read.All权限,Connect-AzureAD默认不会请求这些权限。如果坚持使用AzureAD模块,需重新连接并指定权限:

Connect-AzureAD -Scopes "AuditLog.Read.All", "Directory.Read.All"

更建议统一使用Microsoft Graph PowerShell模块(你的脚本主要基于此),避免混合模块带来的兼容性问题。

2. 语法错误修正

你尝试的两种Get-AzureADAuditSignInLogs写法存在问题:

  • 第一种:Filter路径错误,应为DeviceDetail/DeviceId,且变量嵌入需注意引号解析:
    # 正确写法
    $deviceResults = Get-AzureADAuditSignInLogs -Filter "DeviceDetail/DeviceId eq '$deviceID'" -Top 1
    
  • 第二种:Where-Object无法直接使用DeviceDetail/DeviceId作为属性路径,需用脚本块,且单引号包裹变量会导致变量不解析:
    # 正确写法
    Get-AzureADAuditSignInLogs | Where-Object { $_.DeviceDetail.DeviceId -eq $deviceID }
    

3. 推荐方案:统一使用Microsoft Graph模块

既然脚本主要使用Get-Mg* cmdlet,建议用Get-MgAuditLogSignIn替代Get-AzureADAuditSignInLogs,语法更一致且权限管理更清晰:

# 获取设备最新登录时间
$latestSignIn = Get-MgAuditLogSignIn -Filter "DeviceDetail/DeviceId eq '$deviceId'" -Top 1 -Property CreatedDateTime
$loginTime = if ($latestSignIn) { $latestSignIn.CreatedDateTime } else { "无登录记录" }

使用前确保Connect-MgGraph已请求正确权限:

Connect-MgGraph -NoWelcome -Scopes "AuditLog.Read.All", "Directory.Read.All", "User.Read.All"

4. 完整脚本优化建议

以下是整合登录时间查询的优化版脚本,同时修复了数组效率问题(避免用+=重建数组):

# 连接Microsoft Graph并请求必要权限
Connect-MgGraph -NoWelcome -Scopes "AuditLog.Read.All", "Directory.Read.All", "User.Read.All"

# 导入CSV数据
$CSVData = Import-CSV -Path "C:\PSTest\Employees.csv"

# 优化账户存在性检查函数,避免重复查询
function Test-AccountExists {
    param($UserN)
    $user = Get-MgUser -Filter "Displayname eq '$UserN'" -ErrorAction Ignore
    return [PSCustomObject]@{
        Exists = [bool]$user
        UserObject = $user
    }
}

# 使用ArrayList提升数组操作效率
$resultsArr = New-Object System.Collections.ArrayList

foreach ($row in $CSVData) {
    $fullname = "$($row.'First Name') $($row.'Last Name')"
    $empId = $row.'Employee Id'
    
    Write-Host "处理用户:$fullname (ID: $empId)"

    $accountCheck = Test-AccountExists -UserN $fullname

    if ($accountCheck.Exists) {
        $user = $accountCheck.UserObject
        Write-Host "找到用户:$($user.UserPrincipalName) (ID: $($user.Id))"

        $devices = Get-MgUserOwnedDevice -UserId $user.Id

        if ($devices) {
            foreach ($device in $devices) {
                $deviceDetails = Get-MgDevice -DeviceId $device.Id
                $deviceId = $device.Id

                # 查询设备最新登录时间
                $latestSignIn = Get-MgAuditLogSignIn -Filter "DeviceDetail/DeviceId eq '$deviceId'" -Top 1 -Property CreatedDateTime
                $loginTime = if ($latestSignIn) { $latestSignIn.CreatedDateTime } else { "无登录记录" }

                # 检查合规状态
                $complianceState = if ($deviceDetails.IsCompliant) { "Y" } else { "N" }

                $null = $resultsArr.Add([PSCustomObject]@{
                    'Employee Id' = $empId
                    'Full Name' = $fullname
                    'User Principal Name' = $user.UserPrincipalName
                    'Device Name' = $deviceDetails.DisplayName
                    'Compliance State' = $complianceState
                    'Last Login Time' = $loginTime
                    'Azure Account' = "Yes"
                })
            }
        }
        else {
            Write-Host "该用户无关联设备"
            $null = $resultsArr.Add([PSCustomObject]@{
                'Employee Id' = $empId
                'Full Name' = $fullname
                'User Principal Name' = $user.UserPrincipalName
                'Device Name' = "No device in Azure"
                'Compliance State' = "NA"
                'Last Login Time' = "NA"
                'Azure Account' = "Yes"
            })
        }
    }
    else {
        Write-Host "未找到该用户"
        $null = $resultsArr.Add([PSCustomObject]@{
            'Employee Id' = $empId
            'Full Name' = $fullname
            'User Principal Name' = "NA"
            'Device Name' = "NA"
            'Compliance State' = "NA"
            'Last Login Time' = "NA"
            'Azure Account' = "No"
        })
    }
}

# 导出结果到CSV
$resultsArr | Export-Csv -Path "C:\pstest\Results.csv" -NoTypeInformation

# 清理资源
$resultsArr.Clear()
Disconnect-MgGraph

额外注意事项

  • 登录日志默认保留30天,如果设备超过30天未登录,将无法查询到记录。
  • 确保执行脚本的账号具有足够的Azure AD权限(全局管理员、安全管理员或审计管理员角色)。
  • 避免在循环中频繁调用Graph API,可考虑批量查询提升效率(比如先收集所有设备ID,再批量查询登录日志)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:05:13