Field notes: delprof2 shutdown script

A new twist on a familiar tale is the best way to describe this post! Recently we’d noticed quite a few of our first-gen SSD machines (60GB drives) were running low on disk space, particularly in open-access areas where lots of different users were logging on.


didn’t think I’d be seeing you again…

This probably comes as no surprise to most education network admins as it’s something we used to deal with in the days of small HDDs but became almost irrelevant as larger local drives became the norm. To some extent history has repeated itself with SSD drives and we have no such problems with our newer Samsung Evo 120GB drives.

That said a solution still needed to be found for the machines with the 60GB drives. The first port of call was the easy option, enable automatic profile cleanup via GPO after a set period of days:

Computer Configuration > Policies > Administrative Templates > System/User Profiles > Delete user profiles older than a specified number of days on system restart

A bit more thought required

However after thinking about it for a couple of seconds it’s not that easy…

Our domain structure  places the Active Directory objects into OUs based on their location (room). Nothing unusual there. However what we don’t know based on OU alone is whether the machine is a classroom PC or one that lives in a staffroom \ office.

This information is very important because our Office 365 Outlook cache, amongst other per-user profile customisations needs to stay persistent and the last thing we want is to wipe staff profiles if the user has been away for a week on holiday!

With that in mind I seemed to have two choices

  1. Alter the OU structure to split machines into class and admin
    This would take a fair bit of administration and ongoing maintenance so wasn’t keen on this option
  2. Find a way to add some logic to the profile cleanup process
    Give the process some intelligence and get it to decide what to do by looking at the machine type

Registry key

registryOne of the sections in my custom imaging scripts asks the technician what the intended role of the machine is when they start the imaging process (name and location are done at the same time).

This information then goes into a custom registry key I create in HKLM\Software\HCFHE\WorkstationType for future reference.

Then the lightbulb moment: I can use that registry key as the identifier for the profile cleanup. First thought is can I add a WMI filter on the GPO… computer says no (or not easily at least)

Ref: https://social.technet.microsoft.com/Forums/fr-FR/5cd1b80a-2f90-4d46-bf65-dba52dcf0c56/how-to-make-wmifilter-that-looks-for-a-registrykey-or-filefolder?forum=winserverGP

Time for some scripting

By this point I’d decided that the GPO on its own wasn’t going to give me enough flexibility so I decided to go down the scripting route instead. First things first, we need a tool to run the profile cleanup, time to dip into my list of handy utilities for the excellent (and free) delprof2:

https://helgeklein.com/free-tools/delprof2-user-profile-deletion-tool/

Not only does it do a thorough job of cleaning profiles but it’s also very flexible in terms of specifying which profiles to clean and runs very nicely from a script 🙂

The script needs to do a couple of things:

  1. Check a registry key for the machine type ADMIN, CLASS (or an invalid value) and proceed \ quit accordingly
  2. Run the delprof2 tool with appropriate switches
  3. Write output to the Windows Event Log

For some reason I went for VBScript rather than PowerShell this time around. After a bit of research some very handy links turned up some code snippets to use. All credit to the authors for creating and putting them out there for re-use.

The second snippet is particularly useful, having worked with Linux for a while now I was yearning for a Windows equivalent to the “tee” command and very glad that the code below does the same job!

Check if value exists in the Registry (TechNet)
Save output of command to a variable (StackOverflow)
Write to Event Log (StackOverflow)

The end result

I’ve included a generalised version of the script below. As always grab the code from my OneDrive public folder to avoid any copy \ paste issues.

  • replace REMOVEME with the prefix of accounts to remove i.e. match something consistent in your student account numbers. You can have multiple /id: switches if you have a couple of different patterns to match
  • replace LEAVEME with accounts you want to exclude e.g. accounts you may have created for specialist use with profiles that you don’t want to be removed
  • You can have multiple /id and /ed switches if you have a range of different account name patterns to match
  • change any other delprof2 parameters as required (the example below removes inactive profiles over 7 days old)
  • the use of & vbCrLf after each line of output from delprof2 gives a nicely formatted Event Log entry, otherwise everything ends up on one long line!
Const HKEY_LOCAL_MACHINE = &H80000002

strComputer = "."
Set objRegistry = GetObject("winmgmts:\\" & _ 
    strComputer & "\root\default:StdRegProv")
 
strKeyPath = "SOFTWARE\HCFHE"
strValueName = "WorkstationType"
objRegistry.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue

Set shell = CreateObject("WScript.Shell")

If IsNull(strValue) Then
		shell.LogEvent 4, "Machine type registry key not found, exiting without performing profile cleanup"
		wscript.quit
		
ElseIf strValue="CLASS" Then
		'wscript.Echo "The registry key exists, the type is " & strValue
		
		Dim objShell
		Set objShell = WScript.CreateObject( "WScript.Shell" )
		Dim strCMD 
		strCMD = """\\yourdomain.tld\netlogon\delprof\DelProf2.exe""" & " /u /d:7 /id:REMOVEME* /ed:LEAVEME*"
		'wscript.echo strCMD
		'objShell.Run(strCMD)

		Set objExecObject = objShell.Exec(strCMD)
		strText = ""

		Do While Not objExecObject.StdOut.AtEndOfStream
			strText = strText & objExecObject.StdOut.ReadLine() & vbCrLf
		Loop
		
		shell.LogEvent 4, "Machine type is " & strValue & " - student profile cleanup has been performed" & vbCrLf & strText
		Set objShell = Nothing
		wscript.quit
		
ElseIf strValue="ADMIN" Then
		shell.LogEvent 4, "Machine type is " & strValue & " - profile cleanup not required"
		wscript.quit
		
Else 
		shell.LogEvent 4, "Machine type is unexpected value " & strValue & ", exiting without performing profile cleanup"
		wscript.quit
	
End If

The output in the Event Viewer then looks something like this…

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: