我正在尝试在我的自动化帐户中创建一个操作手册,该操作手册会从 Entra 中删除所有陈旧设备(非活动时间 >= 180 天)。
我已经创建了具有正确 API 权限的应用程序注册,并将证书上传到我的自动化帐户,我还安装了所需的模块。
API权限:
尽管我添加了很多调试步骤,但我仍然遇到一些问题,当前版本的脚本仅显示欢迎使用图形消息,然后显然退出脚本:
Welcome to Microsoft Graph!
Connected via apponly access using 12345567-1213-2333-xxxxxxxx
Readme: https://aka.ms/graph/sdk/powershell
SDK Docs: https://aka.ms/graph/sdk/powershell/docs
API Docs: https://aka.ms/graph/docs
NOTE: You can use the -NoWelcome parameter to suppress this message.
脚本是这样的:
# Set the tenant ID and App Registration details
$tenantId = "tenantID"
$clientId = "clientID"
$thumbprint = "certificateThumbprint"
# Authenticate to Microsoft Graph using the certificate
Connect-MgGraph -ClientId $clientId -TenantId $tenantId -CertificateThumbprint $thumbprint
# Number of days a device must be inactive before deletion (180 days in this case)
$dt = (Get-Date).AddDays(-180)
# Initialize an array to hold all devices
$AllDevices = @()
# Fetch devices from Microsoft Graph with pagination
$uri = "https://graph.microsoft.com/v1.0/devices"
do {
Write-Host "Fetching devices from: $uri"
$response = Invoke-MgGraphRequest -Method GET -Uri $uri
if ($response -and $response.value) {
$AllDevices += $response.value
Write-Host "Fetched $($response.value.Count) devices"
} else {
Write-Host "No devices fetched or response is null"
}
$uri = $response.'@odata.nextLink'
} while ($uri -ne $null)
# Debugging: Output the total number of devices fetched
Write-Host "Total devices fetched: $($AllDevices.Count)"
# Filter devices that have not signed in for 180 days or more and are disabled
$DevicesToDelete = $AllDevices.value | Where-Object {
($_.approximateLastSignInDateTime -le $dt)
}
# Debugging: Output the number of devices identified for deletion
Write-Host "Devices identified for deletion: $($DevicesToDelete.Count)"
# Output devices for review (testing mode)
if ($DevicesToDelete.Count -gt 0) {
Write-Host "Devices identified for deletion (not deleted in this run):"
$DevicesToDelete | Select-Object displayName, id, approximateLastSignInDateTime
} else {
Write-Host "No devices found that meet the criteria for deletion."
}
# Delete the devices that were inactive for 180 days or more
# foreach ($Device in $DevicesToDelete) {
# Invoke-MgGraphRequest -Method DELETE -Uri "https://graph.microsoft.com/v1.0/devices/$($Device.id)"
# Write-Host "Deleted device: $($Device.displayName)"
# }
#Write-Output "Device cleanup process completed."
脚本的最后一部分被注释掉,因为我不想在测试过程中删除任何内容。也许我处理这件事的方式也是完全错误的。我很高兴得到所有的帮助!
谢谢!
您的代码存在一些问题,您可以进行改进。
首先,主机输出(由
Write-Host
生成)在自动化帐户作业输出中不可见。 AA 知道的唯一输出是成功、错误和警告。
第二期在这里:
$DevicesToDelete = $AllDevices.value | Where-Object {
.value
的对象中没有$AllDevices
,那些已经是device
类型对象。
一个改进,你不需要在客户端进行过滤
approximateLastSignInDateTime
,Graph API 知道如何通过此属性进行过滤:
本质上你可以做:
# `o` format is `yyyy-MM-ddTHH:mm:ss.fffffffZ`, Graph accepts it no problem :)
$dt = [datetime]::UtcNow.AddDays(-180).ToString('o')
$uri = "v1.0/devices?`$filter=approximateLastSignInDateTime le $dt"
$AllDevices = @()
和 $AllDevices += $response.value
效率低下,应该避免。您可以简单地将循环表达式的结果分配给一个变量,即:$AllDevices = do { ..... $response.value }
。有关详细信息,请参阅 为什么我应该避免使用增加赋值运算符 (+=) 来创建集合。
总之,您的代码可以是:
# Authenticate to Microsoft Graph using the certificate
$connectMgGraphSplat = @{
ClientId = 'clientID'
TenantId = 'tenantID'
CertificateThumbprint = 'certificateThumbprint'
NoWelcome = $true
Scopes = 'Device.ReadWrite.All' # this should be enough to run your code
}
Connect-MgGraph @connectMgGraphSplat
# Number of days a device must be inactive before deletion (180 days in this case)
$dt = [datetime]::UtcNow.AddDays(-180).ToString('o')
# Fetch devices from Microsoft Graph with pagination where
# `approximateLastSignInDateTime` is lower than or equal to `$dt`
$uri = "v1.0/devices?`$filter=approximateLastSignInDateTime le $dt"
$DevicesToDelete = do {
$response = Invoke-MgGraphRequest GET $uri
if ($response.value) {
$response.value
}
$uri = $response.'@odata.nextLink'
} while ($uri)
# Debugging: Output the total number of devices TO DELETE fetched
# NOTE: `Write-Host` was removing here, same as below with `"Deleted device:...`
"Total devices to delete fetched: $($DevicesToDelete.Count)"
foreach ($Device in $DevicesToDelete) {
Invoke-MgGraphRequest -Method DELETE -Uri "v1.0/devices/$($Device.id)"
"Deleted device: $($Device.displayName)"
}