powershellwmiuser-profilewmi-query

Remove-WmiObject - Delete User Profiles


Here is the code to remove user profiles remotely with the following constraints/rules:

########## List of accounts/Student profiles older than 21 days and not test accounts to be deleted  #######################



foreach ($computer in (Get-Content e:\cleanupscript\scripts\ComputerList.csv)) {


if(Test-Connection -ComputerName $computer -count 1){
    $userfolders = Get-ChildItem "\\$computer\C$\users\"  | Select-Object -ExpandProperty Name
}


#The list of accounts, which profiles must not be deleted
$ExcludedUsers ="Public","administrator","csimg",”DefaultAppPool”, "ksnproxy", "test1","test2","test3","test4","test5","test6","test7","test8","test9","test10","test11","test12","test13","test14","test15","test16","test17","test18","test19","test20","test21","test22","test23","test24","test25","test26","test27","test28","test29","test30","test31","test32","test33","test34","test35","test36","test37","test38","test39","test40","test41","test42","test43","test44","test45","test46","test47","test48","test49","test50","test51","test52","test53","test54","test55","test56","test57","test58","test59","test60","test61","test62","test63","test64","test65","test66","test67","test68","test69","test70","test71","test72","test73","test74","test75","test76","test77","test78","test79","test80","test81","test82","test83","test84","test85"



        $StudentsProfiles = Get-WmiObject -ComputerName $computer -Class Win32_UserProfile | 
            Select-Object   PSComputerName,
                            Sid, 
                            LocalPath, 
                            @{Label='LastUseTime';Expression={$_.ConvertToDateTime($_.LastUseTime)} } |
                        
            
            Where-Object -FilterScript {![System.String]::IsNullOrWhiteSpace($_.LastUseTime)} |
            Where-Object -FilterScript {!($_.LocalPath -eq "C:\Windows\ServiceProfiles\ksnproxy")} |
            Where-Object -FilterScript {!($ExcludedUsers -like ($_.LocalPath.Replace("C:\Users\","")))} |
            Sort-Object -Property {($_.LastUseTime)} |
            Select-Object -First 3 |
         

foreach ($StudentsProfile in $StudentsProfiles)
{

    #Write-Host $StudentsProfile.LocalPath, $computer,  $StudentsProfile.LastUseTime,  "profile existing” -ForegroundColor Red

    
    if (!($ExcludedUsers -like ($StudentsProfile.LocalPath.Replace("C:\Users\",""))))
    {     
        $StudentsProfile | Remove-WmiObject 
        Write-Host $computer, $StudentsProfile.LocalPath, $StudentsProfile.LastUseTime,  "profile deleted” -ForegroundColor Magenta
    }
          
}
Remove-WmiObject : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the 
input and its properties do not match any of the parameters that take pipeline input.
At line:1 char:7
+ $st | Remove-WmiObject -Authentication Connect
+       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (@{PSComputerNam...-07 6:49:46 AM}:PSObject) [Remove-WmiObject], ParameterBindingException
    + FullyQualifiedErrorId : InputObjectNotBound,Microsoft.PowerShell.Commands.RemoveWmiObject

Solution

  • As an aside: The CIM cmdlets (e.g., Get-CimInstance) superseded the WMI cmdlets (e.g., Get-WmiObject) in PowerShell v3 (released in September 2012). Therefore, the WMI cmdlets should be avoided, not least because PowerShell (Core) (v6+), where all future effort will go, doesn't even have them anymore. Note that WMI still underlies the CIM cmdlets, however. For more information, see this answer.

    Therefore, piping the objects in collection $StudentsProfiles to Remove-WmiObject causes the error you saw: the input objects are of the wrong type.


    Solution:

    Omit the Select-Object PSComputerName, ... call and limit the pipeline to mere filtering (Where-Object calls, the Select-Object call with -Last) and sorting commands, neither of which change the identity of the input objects:

    Using a streamlined version of your pipeline:

    $StudentsProfiles = Get-WmiObject -ComputerName $computer -Class Win32_UserProfile | 
      Where-Object -FilterScript {
        $_.LastUseTime -and 
          $_.LocalPath -ne "C:\Windows\ServiceProfiles\ksnproxy" -and
            (Split-Path -Leaf $_.LocalPath) -notin $ExcludedUsers
      } |
        Sort-Object LastUseTime |
          Select-Object -First 3
    

    Note: $_.ConvertToDateTime($_.LastUseTime) - i.e. explicit conversion to [datetime] - isn't actually needed:

    As an aside: The preferred CIM cmdlets have an advantage over the WMI cmdlets in this respect: they represent timestamps directly as [datetime] - no conversion needed.