A customer observed that the Last Used On column in the Programs and Features control panel doesn’t appear by default, and if they turn it on, the column is simply blank. The customer wanted to confirm this behavior and asked if there was a way to obtain the Last Used On information by some other means.
I thought it was odd that the customer asked us to confirm what they were seeing. “When I hold my arms above my head, my shoulder hurts. Can you confirm that?” Um, it’s your shoulder. We can’t tell you how your shoulder feels.
I’m guessing that what they wanted was not a confirmation that their eyes were not deceiving them, but rather a confirmation that the behavior is intentional.
And yes, it is intentional.
The Last Used On information was always a guess, and a really dodgy one at that. As we noted earlier, if the application itself does not provide the information, the Programs and Features control panel runs some really coarse heuristics to find the program, consisting mostly of matching words in the program name in the Programs and Features control panel against the words in the program name in the Start menu.
There is no way to provide Last Used On information in the application registration (which makes sense since that is a dynamic concept not know at registration time), so for the Last Used On property, the system is always guessing.
The heuristic is bad, and it eventually was recognized as so laughably bad that it simply wasn’t worth trying.
The column still exists in case there are programs which programmatically extract data from the Programs and Features control panel. They will still have a column to manipulate, but the column never contains any useful information.
The customer insisted upon an alternative mechanism that gave them the Last Used On information. I got the impression that they use this information to decide which programs their employees are using.
I guess if you want to know for real when a program is run, you can turn on AppLocker auditing. But the Programs and Features control panel doesn’t try any more.
Shouldn’t it be practical to do a better job with UWP/MSIX apps?
Windows Installer still has MsiUseFeature and MsiGetFeatureUsage. I suppose this tracking is not integrated with Programs and Features, then.
User Access Logging (UAL) is a newer scheme but I don’t think there is any documented way to correlate the arguments of UalRegisterProduct with subkeys of the Uninstall key.
If an app wanted to, could it still write this information? Or is this column purely legacy now, just to avoid crashing apps that seek this info?
Explorer always calculated it on the fly. There’s nowhere to “write” to override the calculation, or to force Explorer to report a specific value instead of returning nothing. (It’s not like there’s a registry key that generates code.)
I was thinking more along the lines of could an app have a line of code during its startup routine to write the current date to this field rather than Explorer calculate it.
Since the Uninstall key is in HKEY_LOCAL_MACHINE, updating the field would require elevation.
Riiiight, forgot about that being in HKLM. That also explains our asset management tool listing all app usage as “unknown”. Seems like back in the day, the developers thought it would be handy to copy that information to the asset management tool. Now it’s just another blank column as well.
Well, there COULD be a “last time this app was used” key in a place that didn’t require elevation. (It might have to store the last time *this user* used this app; I’m not sure what all keys are there for unelevated updating.) And the Control Panel could consult this key to show the Last Used time. But I doubt any of this is worth the effort.
Did it use the UserAssist key? The shell writes a entry there every time it launches something so one would think it would be reasonably accurate. Mapping from uninstaller to application is still a issue but a uninstall value could be added that points to the executable. MSI could do this automatically for things with just a single .exe.