Home > database >  Remove-WmiObject - Delete User Profiles
Remove-WmiObject - Delete User Profiles

Time:11-21

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

CodePudding user response:

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.

  • When Remove-WmiObject receives input from the pipeline, it expects input objects of type System.Management.ManagementObject, which bind to its -InputObject parameter.

  • By contrast, your $StudentsProfiles variable does not contain objects of this type, because you've applied Select-Object with property names to the original Get-WmiObject call, which creates objects of a general purpose type, [pscustomobject], that is unrelated to the type of the input objects, and simply contains the specified properties with values copied from the input object's properties of the same name.

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:

  • To test if the value is non-empty (non-null), $_.LastUseTime - which is a string representing a timestamp, can be used as-is, because interpreting $null or '' (empty string) as a Boolean results in $false, whereas any nonempty string yields $true.

  • Similarly, LastUseTime can be passed to Sort-Object to sort by this property value directly, because the string representation of the timestamp - e.g. '20211110143544.500000-300' - is constructed in a way that lexical sorting is equivalent to chronological sorting.

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.

  • Related