根据 Appdata\Local 文件夹的日期删除用户配置文件

Delete user profiles based on the date of the Appdata\Local folder

感谢 Microsoft 打破了“在系统重新启动时删除早于指定天数的用户配置文件”GPO 并且这些年来都没有修复它,我需要一个脚本来删除旧的用户配置文件。问题是,我不需要它查找用户配置文件文件夹本身的修改日期,而是根据用户配置文件的 Appdata 文件夹中本地文件夹的修改日期删除用户配置文件。我注意到,即使您每天登录,用户个人资料文件夹的修改日期可能多年都不会改变,但本地文件夹似乎确实会根据您的登录时间而改变。

所以,我从用户 cxr-aus 制作的 spiceworks post 中抓取了这个。

$useraccounts = Get-ChildItem -path C:\users\ | Where-Object lastwritetime -lt (Get-Date).AddDays(90) | Select-Object Name

$sort = $useraccounts | ForEach-Object {$_.Name}

$removeaccounts = $sort -join "|"

Get-WmiObject -Class Win32_userprofile | Where-Object {($_.LocalPath -match "$removeaccounts") -and (!$_.special)} | Remove-WmiObject -whatif

您可以删除代码末尾的 -whatif 以使其删除用户配置文件。 我 运行 遇到的第一个问题是我需要这个来删除多个用户配置文件,因此 Remove-WmiObject 不起作用,因为 Get-WmiObject return 对我来说有多个配置文件,所以要修复它为了工作,我使用 % { $_.Delete()} 而不是像下面这样。

警告:请谨慎使用以下代码,因为 -whatif 不适用于它,它可能会开始从您的计算机上删除多个配置文件。

$useraccounts = Get-ChildItem -path C:\users\ | Where-Object {$_.lastwritetime -lt (Get-Date).AddDays(90)} | Select-Object Name
Foreach ( $user in $useraccounts) {
$sort = $useraccounts | ForEach-Object {$_.Name}

$removeaccounts = $sort -join "|"
$Username = $removeaccounts.name
Get-WmiObject -Class Win32_userprofile | Where-Object {($_.LocalPath -match "$Username") -and (!$_.special)} |  % { $_.Delete()}}

您可以看到我确实更改了代码的其他一些方面以尝试将其分解,以便代码一次在一个配置文件上运行。这种方法有效,因为它将根据用户配置文件文件夹的修改日期开始删除文件夹 但问题是它会删除昨天可能已经使用过的用户配置文件,但是用户配置文件文件夹的修改日期没有改变。 所以我需要脚本做的是:

1.Get C:\users 目录中的所有用户配置文件文件夹

  1. 进入用户配置文件文件夹并获取 appdata\local 文件夹的修改日期。

3.Then return 只有 appdata\local 文件夹在这种情况下 90 天未被修改的用户配置文件文件夹。

我已经尝试了一些方法来改变这段似乎是死胡同的代码。有人可以帮我解决这个问题吗?

好的。

确保在生产中使用之前彻底测试它。

我添加了一些有用的注释来破译您在这段代码中尝试做的事情。

$VerbosePreference = 'Continue'

## getting the name of the users
## this returns the filtered results below
$useraccounts = Get-ChildItem -Path $env:HOMEDRIVE\users\ | Where-Object lastwritetime -LT (Get-Date).AddDays(90)

## $useraccounts returns

<#

Directory: /Users

UnixMode   User             Group                 LastWriteTime           Size Name
--------   ----             -----                 -------------           ---- ----
drwxr-x--- jacoby         staff                5/2/2022 19:04           1056 jacoby
drwxrwxrwt root             wheel               3/26/2022 00:21            128 Shared

#>

## $useraccounts.name returns

<#

PS > $useraccounts.name

jacoby
Shared

#>

## if we use get-childitem | get-member we can see that we have access to a lot of 
## properties returned like the .name value

#### we don't need any of this
####$sort = $useraccounts | ForEach-Object {$_.Name}
#####$removeaccounts = $sort -join '|'

## ok let's do something here
## for each account in my list
foreach ($account in $useraccounts) {

    ## let's write some info so we know what's happening
    Write-Verbose -Message ('currently working with {0}' -f $account)

    ## we want to check moditfication time of folder so we gotta see if it exists
    ## we want to test c:\users\ the current account \ appdata\local
    ## $account.FullName gives us c:\users\accountname so we just need to add the rest

    $testpath1 = $account.FullName + '\appdata\local'
    Write-Verbose -Message ('we generated the path {0}' -f $testpath1)

    ## imma give you some error checking
    ## this is ugly because it could be there but we can't access it

    if ((Test-Path -Path $testpath1 -ErrorAction SilentlyContinue) -eq $true) {

        ## if the path exists here's what we'll do

        ## get a count of all the file modified in the last 90 days

        $count = (Get-ChildItem -Path $testpath1 `
                ## -Recurse
                ## uncomment this if you want recurse or depth
            | Where-Object {
                $_.LastWriteTime -gt (Get-Date).AddDays(-90)
            }
        ).Count

        ## now that we have a count we can test if the count is less than than 1 (0)
        ## that means no files in these folder were modified in the last 90 days

        if ($count -lt 1) {

            ####
            ##
            ## this is the area where we can take action on the 
            ## folders/files that have not been modified in the 
            ## last 90 days 
            ## you might delete them or just log them somewbere
            ##
            ####

            Write-Verbose -Message 'no file modified in the last 90 days'

            ####
            ## this is your original deletion pipeline
            ##Get-WmiObject -Class Win32_userprofile | Where-Object {($_.LocalPath -match "$account") -and (!$_.special)} | Remove-WmiObject -whatif
            ##i have not tested this. be careful.
            ####
        }

        else {

            Write-Verbose -Message ('{0} files have been modified in the last 90 days! We do not want delete this.' -f $count)

            ####
            ## 
            ## these is the area where we can take action if the
            ## files/folder HAVE been modified recently
            ## we would NOT want to delete these files
            ##
            ####
        }
    }
    ## do some stuff before ending the for each loop
    ## maybe write our changes somewhere permanent
}

再次感谢“又一个鼠标受害者”对脚本的帮助。我已针对我的环境稍微更改了脚本

$VerbosePreference = 'Continue'
$ExcludedUsers="Public","default","defaultuser0","public","administrator"
$path = "$Env:SystemDrive\users"

## getting the name of the users
## this returns the filtered results below
$useraccounts = Get-ChildItem -Path $path -Exclude $ExcludedUsers | Where-Object {$_.lastwritetime -lt (Get-Date).AddDays(-30)}

## $useraccounts returns

<#

Directory: /Users

UnixMode   User             Group                 LastWriteTime           Size Name
--------   ----             -----                 -------------           ---- ----
drwxr-x--- jacoby         staff                5/2/2022 19:04           1056 jacoby
drwxrwxrwt root             wheel               3/26/2022 00:21            128 Shared

#>

## $useraccounts.name returns

<#

PS > $useraccounts.name

jacoby
Shared

#>

## if we use get-childitem | get-member we can see that we have access to a lot of
## properties returned like the .name value

#### we don't need any of this
####$sort = $useraccounts | ForEach-Object {$_.Name}
#####$removeaccounts = $sort -join '|'

## ok let's do something here
## for each account in my list
foreach ($account in $useraccounts)
{

    ## let's write some info so we know what's happening
    Write-Verbose -Message ('currently working with {0}' -f $account)

    ## we want to check moditfication time of folder so we gotta see if it exists
    ## we want to test c:\users\ the current account \ appdata\local
    ## $account.FullName gives us c:\users\accountname so we just need to add the rest

    $testpath1 = $account.FullName + '\appdata\local'
    Write-Verbose -Message ('we generated the path {0}' -f $testpath1)

    ## imma give you some error checking
    ## this is ugly because it could be there but we can't access it

    if ((Test-Path -Path $testpath1 -ErrorAction SilentlyContinue) -eq $true)
    {

        ## if the path exists here's what we'll do

        ## get a count of all the file modified in the last 30 days

        $count = (Get-ChildItem -Path $testpath1 | Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-30) }).Count

        ## now that we have a count we can test if the count is less than than 1 (0)
        ## that means no files in these folders were modified in the last 30 days

        if ($count -lt 1) {

            ####
            ##
            ## this is the area where we can take action on the
            ## folders/files that have not been modified in the
            ## last 30 days
            ## you might delete them or just log them somewbere
            ##
            ####

            Write-Verbose -Message 'no file modified in the last 30 days'

            ####
            ## this is your original deletion pipeline
            #Get-WmiObject -Class Win32_userprofile | Where-Object {($_.LocalPath -contains "$account") -and (!$_.special)} | Remove-WmiObject -whatif
            ##i have not tested this. be careful.
            ####
        }

        else {

            Write-Verbose -Message ('{0} files have been modified in the last 30 days! We do not want delete this.' -f $count)

            ####
            ##
            ## these is the area where we can take action if the
            ## files/folder HAVE been modified recently
            ## we would NOT want to delete these files
            ##
            ####
        }
    }
    ## do some stuff before ending the for each loop
    ## maybe write our changes somewhere permanent
}

我首先将 $env:HomeDrive 更改为 $env:SystemDrive 因为我的环境设置不同。我还添加了一个 $ExcludeUsers,这样它就不会获取管理员或其他系统用户配置文件文件夹。由于您所做的更改,Remove-WmiObject 适用于 Users 文件夹中的多个配置文件,并且我能够通过 运行 此脚本一次删除 20 多个配置文件。出于某种原因,我想不通,-match 不再有效。它不会将 $account 视为完整的本地路径,因此我将其更改为 -contains,这对我来说似乎已经足够了。对于其他人,请务必在使用前彻底测试脚本。这是一个非常强大的脚本。