In my workplace, our helpdesk has a need for the ability to quickly and easily delete user profiles remotely. I did a little tinkering with wbemtest and found I could call the Delete() method on any of the WMI objects returned by the query “SELECT * FROM Win32_UserProfile.” It will properly delete the profile’s associated files and registry keys the same way that the windows native GUI tools do it. The problem with the native tool however, is that you need to be logged in to use it. It is fairly slow and clunky, and you can only select one profile at a time for deletion. This accounts for a lot of wasted time. So I took what I learned and created a little vbs script that made some WMI calls and deleted profiles. This worked great, but the help desk needs the ability to selectively choose which profiles get deleted through some form of user interface. I wanted the simplest possible solution that required no dependencies. (.NET, AutoIT DLL’s, etc). I found the best way to do that was to make an HTA application.
The first version of my profile cleanup HTA was very basic but served its purpose well. The problem was everything was done using synchronous WMI calls. I’ve recently been playing with a lot of Node.js to understand this whole “non-blocking IO” asynchronous programming methodology, and it got me wondering if I could do the same with this HTA application. It’s not difficult to find examples online for creating WMI queries and calling methods asynchronously, but getting them to play nice in the HTA application proved to be a challenge. At least for me : ).
One problem I had was certain things only worked using jScript, while other things only worked using VBscript. Fortunately I found a way to use both and reference functions in both languages from either language. The next problem I had was finding a way to reference the “WbemScripting.SWbemSink” object within HTA. The way I found to do it was by referencing the object by its class ID like so:
<object id="oSink" classid="clsid:75718C9A-F029-11D1-A1AC-00C04FB6C223"></object>
My first attempts at improving the UI was to make the function calls using the setTimeout javascript function but that didn’t seem to change anything. To prevent the windows from freezing I had to do everything asynchronously within WMI. I’m including links to both versions of the application. The old version should really only be used for educational purposes for developers interested in a before and after demonstration of asynchronous WMI vs standard synchronous WMI. The second version works quite well and is safe to use in production. Just be sure you don’t accidentally delete some important data in a user’s profile. Any comments, suggestions, improvements or questions are welcome!