使用 PowerShell 按列表过滤输出

Filtering output by a list with PowerShell

我想做的是获取超过 90 天的登录名,并将它们与 Get-WmiObject Win32_UserProfile 输出中的当前配置文件列表进行比较。我已经尝试了几个小时,但仍然无法弄清楚为什么它没有按照(我认为)应该的方式处理名称列表。

Invoke-Command -ComputerName wsci201oit -ScriptBlock {
    $AllUsers = Get-WmiObject Win32_UserProfile | Where-Object -FilterScript {
        $_.LocalPath -notlike 'c:\windows*' -and
        $_.LocalPath -notlike '*ADMINISTRATOR' -and
        $_.LocalPath -notlike '*Public' -and
        $_.LocalPath -notlike '*Temp'
    } | Select-Object -Property LocalPath, SID

    $Over90 = Get-ChildItem C:\Users | where {
        $_.LastWriteTime -lt (Get-Date).AddDays(-30) -and
        $_.Name -notlike 'ADMINISTRATOR' -and
        $_.Name -notlike 'Public' -and
        $_.Name -notlike 'TEMP'
    } | Select-Object Name
    $Over90 | Select-Object Name | Out-File C:\Windows\Temp\Over90.txt
    $List = Get-Content -Path C:\Windows\Temp\Over90.txt

    $AllUsers | Where-Object { $_.LocalPath -like "*$List" }
}

$AllUsers 的输出包含像 C:\Users\adm-thomas 这样的路径和 SID。 $List 的输出只包含 adm-thomas。我正在尝试将 $List 中的 "adm-thomas" 匹配到 "C:\Users\adm-thomas" LocalPath 并针对 $List.

中的每个名称进行测试

您可以使用 Get-ChildItem 中的 FullPath 属性,但从 LastUseTime 属性 中获取相同的信息似乎效率更高Win32_UserProfile 然后整个命令可以只是过滤的远程 WMI 查找。

Get-CimInstance Win32_UserProfile -ComputerName wsci201oit |
    Where-Object {
        $_.Special -eq $False -and
        $_.SID -notmatch '-500$' -and
        $_.LastUseTime -lt (Get-Date).AddDays(-30) 
    } |
    Select-Object -ExpandProperty LocalPath, SID

注意:我使用了默认情况下在 WSMAN 上运行的 CIM cmdlet。有一个 Special 属性 可以删除除本地管理员之外的所有特殊用户。如果 Administrator 已重命名,则匹配 SID 会更安全。

您可能要调整的第一件事是 C:\Users 的子文件夹的处理。将子文件夹名称列表写入文件,然后在下一条指令中读取该文件,这是完全没有意义的。更糟糕的是,由于您没有删除 table header,如果您恰好拥有用户帐户 "name",则可能会出现误报。只需展开 Name 属性 即可获得文件夹名称列表。您还可以通过对照要排除的名称列表检查名称来简化过滤。

$excludes  = 'ADMINISTRATOR', 'Public', 'TEMP'
$threshold = (Get-Date).AddDays(-30)
...
$List = Get-ChildItem C:\Users | Where-Object {
    $_.PSIsContainer -and
    $_.LastWriteTime -lt $threshold -and
    $exclude -notcontains $_.Name
} | Select-Object -Expand Name

然后您需要调整从 Win32_UserProfile class 检索的数据。由于只有路径的叶部分与以后的比较相关,因此使用 calculated property 仅提取该信息:

... | Select-Object @{n='Username';e={Split-Path -Leaf $_.LocalPath}}, SID | ...

这样你就可以根据上面的 $List 过滤结果:

Get-WmiObject Win32_UserProfile | Where-Object {
    $_.LocalPath -notlike 'c:\windows*'
} | Select-Object @{n='Username';e={Split-Path -Leaf $_.LocalPath}}, SID | Where-Object {
    $List -contains $_.Username
}