Remove profiles with Power Shell help

Comments

22 comments

  • Stephen Valdinger

    Sure can. Couple questions:

     

    Is the profile(s) you want to keep consistent across all the machines? How stale do you want the account to be before the profile is removed?

    0
    Comment actions Permalink
  • Jason Szost

    Yes. the profiles I want to spare, I want to spare on all machines. As for staleness, 30 days is good enough for me, but I would like to ability to change it and re-run the PS Script. Obviously if it is set to 30 days and I re-run to at 60 days that wouldn't bring those profiles back. I would most likely it would be fewer days.

    0
    Comment actions Permalink
  • Stephen Valdinger

    Alrighty. That's enough to go on. Give me about an hour or so to research/write/test and I'll post back!

    0
    Comment actions Permalink
  • Jason Szost

    Thank you so much Stephen.

    0
    Comment actions Permalink
  • Stephen Valdinger

    No problem man. I've currently got the logic to pull all accounts in that are 30 days or older from lastlogintime. Working out the logic to translate SID > Username so it's friendly.

     

    This will require a little work on your part I imagine since of course SIDs are unique and only you will know which SIDs you want to keep. 

    Stay tuned!

    0
    Comment actions Permalink
  • Jason Szost

    Thanks for the update.

    0
    Comment actions Permalink
  • Stephen Valdinger

    Alright, I'm pretty damn close here. Just trying to do a little cleanup and testing before I ship this thing off. 

     

    Once you have the script, pay close attention to the code comments. Instructions will be inside them.

    0
    Comment actions Permalink
  • Jason Szost

    Thank you.

    0
    Comment actions Permalink
  • Stephen Valdinger

    This is what I have so far. I'm still wresting with a .Remove() method. Supposedly that call should work, but it isn't so I've taken it out so you can execute this code and see what it is doing so far. basically it will look at the machine, and list out all profiles that aren't part of the NT stack, though this is easily modified for others as well:

    $profile = Get-WmiObject -Class win32_userprofile | Select LastUseTime, SID
    $profile.PSBase | Get-Member


    Foreach($p in $profile){

     

    $SID = $p.SID

    $objSID = New-Object System.Security.Principal.SecurityIdentifier($SID)
    $objUser = $objSID.Translate([System.Security.Principal.NTAccount])


    If($objUser.Value -notmatch "NT AUTHORITY" -and $objUser.Value -notmatch "NT SERVICE"){


    Write-Host "Resolved user name:" $objUser.Value


    }

    }

     

     

    Jason Hanks: If you're reading this, if you could shoot this code to Mr. Powell that would be sweet. He may have the method laying around in his head that I can use to do the actual remove. So far my google-fu is failing me.

    This is tested on Powershell v5, so bear that in mind.

     

    0
    Comment actions Permalink
  • Jason Szost

    I second the request for the Corgi god to look at the code lol. Thank you so much for this much help Stephen. I cant begin to thank you enough.

    0
    Comment actions Permalink
  • Kris Powell

    Corgi god? Hah! I love it.  Side note: corgi's are awesome.

    But! Getting back to the task at hand, I think I may have narrowed down what may be happening.

    I believe the method that you're searching for is .Delete(). It appears as though $profile contains PSCustomObjects. Try dropping the Select-Object portion and then looking at the psbase for the individual objects stored in $profile.

    For example, we'll see the .Delete() method with these two examples (single object and all objects):

    $profile = Get-WmiObject -Class Win32_userprofile
    $profile[0].psbase | Get-Member

    Or

    $profile = Get-WmiObject -Class Win32_userprofile
    $profile | ForEach-Object {$_.psbase | Get-Member}

     

    To illustrate this even further, we could take a look at the type of each of the objects:

    $profile = Get-WmiObject -Class Win32_userprofile | Select LastUseTime, SID
    $profile | Foreach-Object {$_.GetType()}

    You may notice that they are all PSCustomObjects and will not include the proper method that we're looking for. If we drop the Select-Object bit, we'll see a different type for each object:

    $profile2 = Get-WmiObject -Class Win32_userprofile
    $profile2 | Foreach-Object {$_.GetType()}

    I hope that's helpful. Best of luck with the remaining portion of your script!

    Cheers,

     

    0
    Comment actions Permalink
  • Stephen Valdinger

    Stupid question time: How did you get your code to format like that? Everytime I put code in here it looks like a steaming pile of corgi poo. Is there a special wrapper I can put around the text, or a certain indent to use?

     

    P.S. Thanks for the insight. I was playing around with the PSBase and Get-Type stuff on my own to figure it out and came up with pretty much the same conclusion. 

    I'm going to have to handle this in such a way that I'm using an object with the .Delete() method available to it.

    0
    Comment actions Permalink
  • Kris Powell

    Sadly, since the forum posts use rich text, there's no super easy markdown. :(

     However, it's fairly straightforward to get the effect that I have, you just need to modify the html directly. 

    If you click the html button in the little toolbar, it'll have the html direct edit window.

     

    In that window, I simply wrap my code with <pre></pre> tags.

    Here's my code wrapped with <pre></pre> tags

     

    Voila! No more corgi poo! ;)

    0
    Comment actions Permalink
  • Stephen Valdinger

    I bet it's a rights assignment thing, I don't have the HTML button unfortunately. Just Bold, Italic, Underline, Strikethrough, and Bullet/Numbered lists. 

     

    Bummer! Oh well. I'll live with it!

    0
    Comment actions Permalink
  • Jason Szost

    I am out for half a day and miss all this. I am going to get caught up and see what results I can get. My PS skills are very very bad but I have to start somewhere.  Thank you both so much for all your help.

    0
    Comment actions Permalink
  • David Mattox

    Jason - did the script work for you?  I have this sme issue across the campus on labs and libraries. THANKS

    0
    Comment actions Permalink
  • Jason Szost

    I honestly dont remember David. This past summer we had a whole department turn over and I am the only original one left. I am lucky if I remember what i had for lunch yesterday. I will try and look back at my notes to see what if any luck i did or didn't have.

    0
    Comment actions Permalink
  • Stephen Valdinger

    Let me know too. I totally forgot that I wrote this little tidbit. I can lend a hand if needed.

    0
    Comment actions Permalink
  • David Mattox

    Totally understand and thanks for the response.  Trying to make the delprof2 work per PDQ recommendations.  Thanks again and good luck

     

    0
    Comment actions Permalink
  • Aileen Nhomi

    I used this script with modifications for my environment

    https://gallery.technet.microsoft.com/scriptcenter/Delete-user-profiles-over-05348eef

    0
    Comment actions Permalink
  • Stephen Valdinger

    Here, I forgot I discovered this tidbit. I looked at a package I created for auto-login of lab machines. The package I created to revert the changes deletes the profile of the account we use to autologin with.

    Here's that code:

     

    Get-CimInstance win32_userprofile | Where { $_.localpath -match "useraccountname" } | Remove-CimInstance

     

    Note, this has to be run as administrator for the Remove-CimInstance to work, but the beauty of the Powershell Step in PDQ is that it does :)

    0
    Comment actions Permalink
  • Stephen Valdinger

    I couldn't help myself. Here, have a function:

     

    Function Remove-UserProfile{
       <#
            .SYNOPSIS
                Removes specified user profile from a local or remote machine using Invoke-Command
       #>
        Param(
            [cmdletBinding()]
            [parameter(
                    Mandatory,
                    Position=1)]
                    [string]
                    $Username,
            [parameter(
                    Mandatory=$false,
                    Position=0)]
                    [array]
                    $Computername
            )
        
        If($Computername -ne '')
        {
            Foreach($computer in $Computername)
                {
                    Try
                        {
                            Get-CimInstance -Computername $Computer win32_userprofile |
                            Where-Object { $_.localpath -match "$Username" } |
                            Remove-CimInstance
                        }
                    
                    Catch
                        {
                            $_.Exception.Message
                        
                        }
                }#end foreach
        }#end if
        
        Else
            {
            
            Get-CimInstance win32_userprofile | Where-Object { $_.localpath -match "$Username" } | Remove-CimInstance
            
            }#end else
    }
    

     

    0
    Comment actions Permalink

Please sign in to leave a comment.