A common ask is how much space is needed to store user state data captured by USMT. This is an important question to answer so that you know how space you may potentially need when capturing user data to the network in traditional Replace scenario task sequences. It’s not an easy question to necessarily answer because of a lot of variables. Gathering the data from all of your systems could also prove tricky. Fortunately, there is a fairly straight-forward way to get this done using USMT’s built-in space estimate ability and by extending ConfigMgr’s Hardware Inventory. Of course, I did this all for the customer as detailed below.
Script Update - January 9, 2019
The Steps
Step 1: Use USMT to estimate the space needed
USMT’s scanstate has a /p switch that will generate an XML file with estimated space required to capture the user data (much emphasis on estimated).
Step 2: Store USMT’s space estimate in WMI
Consume the XML file grabbing the space estimate and store it in a custom WMI namespace and class.
Step 3: Configure hardware inventory to gather the data
Very easy to do via the GUI in ConfigMgr 2012. Not too difficult to do in 2007 either but you must edit the sms_def.mof file. Note that for data already in WMI, there is no need to touch configuration.mof.
Step 4: Report on the data
Use your favorite mechanism report on the data including (WQL) queries, SQL queries, or reports.
The Script
Steps 1 and 2 above are in a fairly straight-forward script called USMT-Estimate.vbs. This script runs scanstate.exe with the /p (space estimate) option using the default MigApp.xml and MigDocs.xml configuration files. By default, the script also uses the scanstate uel option and sets it to 90 days – this option causes scanstate to only consider user profiles for users that have logged in within the last number of specified days (90 in this case by default).
scanstate outputs an XML file with estimates in it to the %temp% directory called scanstate.xml. The script grabs the results from this file, creates a new namespace in WMI (if it doesn’t already exist) called ITLocal under root, creates a new class called USMT-Estimate in this namespace (if it doesn’t already exist), and then creates an instance/object of this class with the space estimate (in MB) and a date/time stamp.
USMT Estimate script: Get it on GitHub
Script Use
To use the script, place it in the root of your USMT 4 package (at the same level as the x86 and amd64 folders) and update your DP(s). Create a program that runs with admin privileges that runs the following command line:
cscript.exe USMT-Estimate.vbs |
Deploy. That’s it really.
Check
scanstate will produce a log file in %temp% called scanstate.log so you can check it if you suspect something wonky has happened.
There are a lot of ways to check if the data is being populated into WMI, but my favorite is PowerShell (and it should be yours also). On a system where the script has run, this is easily done using two simply PowerShell commands:
1
2
|
$usmt_estimate = gwmi -namespace rootITLocal -class USMT_Estimate $usmt_estimate |
Get-WMIObject has a –computer parameter to connect to remote systems also and of course you can use all of the power of PowerShell. Other possible ways to review the data in WMI include WBemTest, CIMStudio, and wmic, to name a few.
Script Customization
If you have custom configuration files, you can run those instead (or in addition to the default ones) by using the /xml option making sure to also specify any default configuration files that you would like to use also (comma separated):
cscript USMT-Estimate.vbs /xml:MigApps.xml,MigDocs.xml,MyCustom.xml |
The script looks for all scanstate XML configuration files in either the x86 or amd64 subfolder of the USMT package source files folder so place any custom configuration files you have into one or both of these directories based on your expected usage.
To change or remove this or add other options, update the ScanStateOptions variable on line 9 of the script. The complete set of options is listed at http://technet.microsoft.com/en-us/library/cc749015(v=WS.10).aspx.
Data Gathering
This is step 3 from above and is the easy part in ConfigMgr 2012. First, run the script (either manually or through a deployment) on at least one system first though so that ConfigMgr can find information about the new class.
Navigate to Overview –> Site Configuration –> Client Settings in the Administration workspace. Create a new set of client settings or edit an existing set (just like with Group Policies, it is highly recommended that you don’t edit the Default Client Settings and instead create and deploy your own as needed).
In the Hardware Inventory section, click on the Set Classes … button.
In the resulting Hardware Inventory Classes dialog, click Add…
In the Add Hardware Inventory Class dialog, click Connect…
In the Connect to Windows Management Instrumentation (WMI) dialog, enter the Computer name for the system where you’ve already successfully run the script and rootITlocal for the WMI namespace. Supply alternate credentials if necessary to connect to the system specified and click Connect.
This will (eventually) return showing the one and only class in this namespace: USMT_Estimate. Check the checkbox next to this class and then click Edit… at the bottom.
In the Class qualifiers dialog, Change the Display name to USMT Estimate (without the underscore). Leave all of the Units as None and click OK four times.
That’s it. The next time the clients update their machine policy, they will be informed of this change and the next hardware inventory cycle after this they will collect the data from this class (if it’s been populated by the script). You can check on this by looking in InventoryAgent.log on the client:
If you’re stuck on ConfigMgr 2007, you should be able to just add this snippet to your sms_def.mof file:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[ SMS_Report (TRUE), SMS_Group_Name ("USMT_Estimate"), SMS_Class_ID ("MICROSOFT|USMT_ESTIMATE|1.0"), Namespace ("root\ITLocal") ] class USMT_Estimate : SMS_Class_Template { [ SMS_Report (TRUE), key ] String GUID; [ SMS_Report (TRUE) ] DateTime DateTime; [ SMS_Report (TRUE) ] UInt32 SizeEstimate; }; |
I have not explicitly tested this on 2007 but there’s no reason this shouldn’t work.
Once ConfigMgr has gathered the data, you’ll be able to see it in a variety of places:
Resource Explorer
Query Wizard
SQL Server
Reporting
I didn’t explicitly create any reports so I’ll leave that as an exercise for you and your gangnam style reporting skillz.
There is an bug in the VBScript (line 32). I had to edit it because it was not correctly identifying the bit version. If the environment variable does not exist, then ExpandEnvironmentStrings() returns the string you sent it.
‘ Per MSDN http://msdn.microsoft.com/en-us/library/dy8116cf(v=VS.84).aspx
If g_WshShell.ExpandEnvironmentStrings(“%ProgramFiles(x86)%”) = “%ProgramFiles(x86)%” Then
architecture = “x86”
Else
architecture = “amd64”
End If
Hi Phil,
Thanks! I knew about the bug, but neglected fixing it 🙁
Thanks to your small change though, the show can go on — I’ve updated the download with your small change 🙂 Thanks again.
Hi, I don’t have SCCM here. Therefore how can I use this script without SCCM ?.
We are just going to use MDT 2012 in our deployment solution.
Any help is much appreciated.
I really have no idea. The whole point is capturing and reporting on this info before the migration. If you don’t have ConfigMgr in place, how do you expect to gather the info?
Thank you for this.
I noticed the WMI entries do not over write themselves. Is this by design and if so, is there a simple way to modify it so it overwrite the old data?
Thanks again
My main thinking was that this could be run multiple times on a system over time and the results compared. Yes, that could have still been done using the history view, but I like having all of the data in a single view. Yes it can be modified fairly quickly if you are familiar with WMI and VBScript. What’s the reason for wanting this though?
Hi Jason,
Great post. Got here through your other post on gathering inventory on SQL instances.
One thing I want to comment on. Not sure if this is changed behaviour – I’m running SCCM 2012 R2 SP1 CU1 – but I could only add the WMI class in the hardware inventory classes for the Default Client Settings. All of my custom client settings have the Add… button greyed out.
It wasn’t a problem to add the class though. I’ll go through my actions step by step for others to follow.
In Default Client Settings, I went to Hardware Inventory, Set Classes…, Add…, Connect…, which is where I entered the name of my test machine and the custom WMI namespace created through your script. The SQLInstance class now showed up at the top of the list. I clicked Cancel, not OK, and confirmed that I did not want to save changes.
Going back to my custom client settings, I was now able to find and select the SQLInstance class in the list, even though I canceled out of the dialog earlier. This has prevented me making any changes to the Default Client Settings.
That’s it. Thanks again for sharing your script and methods. It’s helped me along nicely!
Merlin
You must add all hardware inventory class changes to the default settings first — you don’t have to check/select it there, just add it there. After adding it there you’ll be able to select it in any of your custom client settings packages.
We learn something every day 🙂
Thanks Jason
You’re welcome.
Easy example for those of you who want to remove the past history from wmi. Add the sub to the end of the script and call it from the main.
Sub ClearWMIClass()
Dim objWMI
On Error Resume Next
Set objWMI = GetObject(“winmgmts:\\.\Root\” & CUSTOM_NAMESPACE)
objWMI.Delete DATA_CLASS
Err.Clear
End Sub
For those of us who aren’t entirely familiar with VB scripting, what exactly do you mean by “call it from the main?” I’ve added the logic you posted to the end of the script, but the historical presence of the runs are still there.
He’s referring to the main sub in the script: add this new sub to the script and call this new sub from the main sub. See https://www.go4expert.com/articles/subroutines-in-vbscript-t4098/ for a nice tutorial on subs.
Hello,
The script returns this results, any idea why? when I run the command on its own i get diffrent result.
15003283456
14941429387
14949020160
14956694528
14972045312
15003283456
15066578944
15194636288
15455649792
15987179520
17097949184
19349372928
23910678528
33214693376
152110268
Thanks,
Hi Jason, I tried your script, but getting error,
PS E:\User State Migration Tool\x86> cscript.exe USMT-Estimate.vbs
Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.
E:\User State Migration Tool\x86\USMT-Estimate.vbs(68, 2) (null): The system cannot find the file specified.
and the 68,2 is g_WshShell.Run commandLine, 0, True
Can you give more details if you have time?
Thanks in advance.
You’ve placed the script in the wrong folder. As noted, it needs to be at the same level as the x86 and amd64 folders and not within one of them.
Having the same issue and validated that it is in the correct directory. Any ideas on how to get around this?
Hi Luke,
What folder exactly did you place the script in? It needs to be in the same folder as the x86 and amd64 folders and not within one of them.
After some additional review, it looks like the script did not account for spaces in folder/path names. This generally shouldn’t be an issue when run from a ConfigMgr package set to download and execute as none of the sub-folders in the USMT folder have spaces in them; however, if run manually or another level of folders is introduced in the path containing spaces in their names, a file not found error will be thrown. I’ve updated the script to account for this. Please re-download and try again.