0

I have been stumped on this for today. I have a script that deletes remote user profiles by providing a computername to it, and it will make a listing out of the folders in C:\users to choose from based off their ADUC name. What I'm having trouble with, is my exclude parameter as it only seems to take only one argument. I'd rather not use Get-ChildItem against a UNC path to avoid a speed performance hit.

I have tried so many things already that I will skip on typing it here to save space. Can someone smarter than me help me out here?

#This is the where I would be passing the multiple "users" to exclude.
#Tried ArgumentList instead with no luck either.
            [array]$User_List = Invoke-Command -ScriptBlock { 
                                    Get-ChildItem -Path "C:\Users" -Exclude Public, Default*, $Using:Exclude | 
                                    Sort-Object -Property LastWriteTime -Descending } -Session $PSSession 

Can't help, but feel like i am missing something. I would just like to be able to provide a list of users (folder names) to exclude.

  • Delete-UserProfile -ComputerName LocalHost #works
  • Delete-UserProfile -ComputerName LocalHost -Exclude UserOne #works
  • Delete-UserProfile -ComputerName LocalHost -Exclude UserOne, Usertwo #Doesnt Work.

Heres the full script:

Function Delete-UserProfile{
[cmdletbinding(SupportsShouldProcess)]
    Param(
        [Parameter(Mandatory=$false,
                   ValueFromPipeLine=$true,
                   ValueFromPipeLineByPropertyName=$true)]
        [Alias('Comp','CN','NetBIOSName')]
        [String[]]$ComputerName,
        
        [Parameter(Mandatory=$false)]
        $Exclude = $env:USERNAME )


Begin {

    if ($null -eq $ComputerName) {

        $ComputerName = Read-Host -Prompt "Enter Computer Name"
        $ComputerName = $ComputerName -split ","

    }

}


Process{
    
    Foreach($Computer in $ComputerName){
        Try{
            $PSSession  = New-PSSession -ComputerName $Computer -ErrorAction Stop 
            $CIMSession = New-CimSession -ComputerName $Computer -ErrorAction Stop 

            [array]$User_List = Invoke-Command -ScriptBlock { 
                                    Get-ChildItem -Path "C:\Users" -Exclude Public, Default*, $Using:Exclude | 
                                    Sort-Object -Property LastWriteTime -Descending } -Session $PSSession 

[array]$userinfo1 = foreach ($user in $User_List.name) {
      $userinfo = (net user $user /domain | Select-String "Full Name" -ErrorAction SilentlyContinue) -replace "Full Name                    ", "" 2>&1 | Out-String -Stream
        if ($userinfo.Length -lt 4) { "NO DISPLAY NAME in ADUC" }
            elseif($LASTEXITCODE -eq 2) { "ACCOUNT NOT in ADUC" }
            elseif($LASTEXITCODE -eq 0) { $userinfo }
                else { "Error occured" }
                }
 
     $(for($i=0; $i -lt $User_List.Count; $i++){
        [pscustomobject]@{
                'User Display Name    ' = "${i}: $($userinfo1[$i])"
                '   Name   '            = $User_List[$i].name
                'Last Modified'         = $User_List[$i].LastWriteTime
                'Profile Size '         = Try{ 
                                                $ProfilePath = $User_List[$i].FullName 
                                                $Profile_Sum = Invoke-Command -ScriptBlock {
                                                        Get-ChildItem -Path $Using:ProfilePath -Recurse |
                                                                Where-Object {$_.PSParentPath -match "Documents|Desktop|Music|Videos|Downloads|Links|Pictures|Favorites|Contacts"} | 
                                                                Measure-Object -Property length -Sum |
                                                                Select-Object -ExpandProperty Sum } -Session $PSSession
                                                                    if($Profile_Sum -lt 1048576){ "  {0:N2}" -f ($Profile_Sum / 1KB) + " KB" }
                                                                    elseif($Profile_Sum -gt 1048576 -and $Profile_Sum -lt 1073741824){ "  {0:N2}" -f ($Profile_Sum / 1MB) + " MB" }
                                                                    elseif($Profile_Sum -gt 1073741824){ "  {0:N2}" -f ($Profile_Sum / 1GB) + " GB" } #Profile Size
                                            } Catch { "$($Error[0].Exception.Message.Split('.')[2].Trim())!" }
                                        }
                                    } ) | Out-Host

Write-Warning "Ensure user profiles are no longer active and/or, have profiles be backed-up!"
Write-Host "Press 'Q' to quit. `nPress 'B' to backup profile. `nSeparate #'s with a comma (1, 2, 3)."
$ii     = Read-Host -Prompt "Enter Number of user(s) to Delete"
$index  = $ii.Trim() -split ","
    if([String]::IsNullOrEmpty($index) -eq $true) { "Null string"; Break }
    elseif($index.ToLower() -like "q*") {"Q was selected. Stopping script."; Break } 
    elseif($index.ToLower() -like "b*") {"B was selected. Stopping script. `nRunning PFL-UserBackUp. . . `n"; PFL-UserBackUp -Computer $Computer; Break }
    
    " "    
    "     Following Profiles will be Deleted:"
    "     ------------------------------------"
        foreach($i in $index) { "$($i.trim()): $($userinfo1[$i])" }
    " "

$Confirm = Read-Host -Prompt "Are you sure you want to continue? [Y/N]"
    if($Confirm.ToLower().TrimStart() -like "n*" -or $Confirm.ToLower() -like "q*"){Break} 
    if([String]::IsNullOrEmpty($Confirm.Trim()) -eq $true) { "Null string"; Break }

        foreach($i in $index) {
            [PSCustomObject] @{
                    "Deleting User(S)"  = $userinfo1[$i]
                    "   Name   "        = $User_List[$i].name
                    "Deletion Status"   = Try{
                                            if($PSCmdlet.ShouldProcess($Computer, "Removing User Profile: $($userinfo1[$i])")){
                                              for($l=0; $l -lt $index.Count;$l++){
                                                Get-CimInstance -ClassName Win32_UserProfile -CimSession $CIMSession | 
                                                    Where-Object { $_.LocalPath.split('\')[-1] -eq $User_List[$i].name } |
                                                    Remove-CimInstance
                                                
                                                $Percent_Complete = ($l /$index.count) * 100  
                                                Write-Progress `
                                                    -Activity "Removing $($index.count) Profiles" `
                                                    -Status "Deleting user: $($userinfo1[$i])" `
                                                    -PercentComplete $Percent_Complete }
        
                                            $Profile_Path = $User_List[$i].FullName 
                                            $TestPath     = Invoke-Command -ScriptBlock { Test-Path $Using:Profile_Path } -Session $PSSession
                                                if($TestPath -eq $false) { "   DELETED" }
                                                elseif($TestPath -eq $true) { 
                                                    Invoke-Command -ScriptBlock { Remove-Item -Path $Using:Profile_Path -Recurse -Force } -Session $PSSession
                                                    $TestPath2 = Invoke-Command -ScriptBlock { Test-Path -Path $Using:Profile_Path } -Session $PSSession 
                                                        if($TestPath2 -eq $false) { "   DELETED" }
                                                        elseif($TestPath2 -eq $true) { CMD.exe /C RMDir /S /Q "\\$Computer\C$\Users\$($User_List[$i].name)" 
                                                            $TestPath3 = Invoke-Command -ScriptBlock { Test-Path -Path $Using:Profile_Path } -Session $PSSession
                                                                if($TestPath3 -eq $false) { "   DELETED" }
                                                                    Else { "Unable To Delete" }
                                                        }        
                                                }
                                            }
                                        } Catch { "Error occurred! :(" }
            }
        }
            } Catch [System.Management.Automation.Remoting.PSRemotingTransportException] {
                "Unable to connect to PC: $Computer `nError: $($Error[0].Exception.Message.Split('.')[2].Trim())!"
                $IP = Test-Connection -ComputerName $Computer -Count 1 -ErrorAction SilentlyContinue | 
                        Select-Object -ExpandProperty IPV4Address | 
                        Select-Object -ExpandProperty IPAddressToString
                            if($IP -EQ $True) { "IPAddress: $IP" }
                                Else { "IPAddress: Unable to get IP." } 

            } Catch [Microsoft.Management.Infrastructure.CimException] {
                "Unable to establish CIM Session on PC: $Computer `n$($Error[0].Exception.Message.Split('.')[2].Trim())!"

            } Finally {
                if($PSSession) { Get-PSSession | Remove-PSSession }
                if($CIMSession) { Get-CimSession | Remove-CimSession }
            }
        }
    }
} 

Note:

Besides the current issue im posting about, the script itself does work. Feel free to provide feedback on it! - take it easy on me tho lol, still learning -

Abraham Zinala
  • 4,267
  • 3
  • 9
  • 24
  • Idk why, but my formatting keeps getting lost when I try editing it. So ignore the out of place closing braces `}`. They *should* align with the opening brace. – Abraham Zinala Jun 03 '21 at 02:17
  • @Mklement0, it doesn't. Lol sorry, I'm confused. It's not like I'm targeting ones that match a certain name with wild cards, I know the exact name of the ones I want to exclude. Unless it still applies to that? Lemme look at the link again. – Abraham Zinala Jun 03 '21 at 02:25
  • 1
    Whatever you pass to `-Include` / `-Exclude` is interpreted as a wildcard expression, including strings that do not include wildcard metacharacters; the latter are then simply matched by case-insensitive string comparison. However, what matters is that `Get-ChildItem -Path "C:\Users" -Exclude ` - unexpectedly - matches the elements of `` _against the name `Users` in`C:\Users`_ rather than against the names of the files and directories _inside_ `C:\Users`. – mklement0 Jun 03 '21 at 02:39
  • 3
    I believe that it is the fact that you are passing in string, string, array to -Exclude. I don't think it likes that `-Exclude Public, Default*, $Using:Exclude`. I tried this myself `Get-ChildItem -Path C:\temp\* -Exclude 'value1', 'value2', @('value3', 'value4')` and I get `Get-ChildItem: Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Exclude'. Specified method is not supported.` – Daniel Jun 03 '21 at 02:43
  • 2
    `dir .\* -Exclude ('sql_error_test' + @('get_true.ps1', 'testing.ps1'))` works though so try `-Exclude ('Public', 'Default*' + $Using:Exclude)` – Daniel Jun 03 '21 at 02:46
  • 2
    Good point, @Daniel: I missed the array aspect; putting it all together, it should be: `Get-ChildItem -Path C:\Users\* -Exclude ('Public', 'Default*' + $Using:Exclude)` – mklement0 Jun 03 '21 at 02:47
  • 2
    Oh man, I didn't even take that into consideration. Didn't realize I was passing an array, to another. That did it. Thank you gents. – Abraham Zinala Jun 03 '21 at 02:51

0 Answers0