Admin Rights: You need to run the below with admin rights for it to work. Launch Visual Studio with admin rights (right click shortcut
and go run as adminstrator).
Retrieve Per-User Installations: Didn't have time to clean this up properly, it is quite "dog's breakfast" in terms of mixing all kinds of string types and I smeared it together from github.com snippets, but this seems to work to find the per-user installations for a specified user SID:
#include "pch.h"
#include <windows.h>
#include "msi.h" // Windows Installer
#include <atlstr.h> // ATL CString
#pragma comment (lib, "msi.lib")
int main()
{
//
// Admin rights required!
//
UINT result = 0;
DWORD dwIndex = 0;
TCHAR szInstalledProductCode[39] = { 0 };
TCHAR szSid[128] = { 0 };
DWORD cchSid;
MSIINSTALLCONTEXT dwInstalledContext;
DWORD cchProductName = MAX_PATH + 1;
WCHAR* lpProductName = new WCHAR[cchProductName];
// Fake, sample SID. Replace:
CString userSID = _T("S-1-5-21-6780625448-452764730-4189743271-1542");
while (ERROR_SUCCESS == (result = MsiEnumProductsEx(NULL, userSID, MSIINSTALLCONTEXT_USERMANAGED | MSIINSTALLCONTEXT_USERUNMANAGED, dwIndex, szInstalledProductCode, &dwInstalledContext, szSid, &cchSid)))
{
UINT uiReturn = MsiGetProductInfoEx(szInstalledProductCode, userSID, dwInstalledContext, INSTALLPROPERTY_INSTALLEDPRODUCTNAME, lpProductName, &cchProductName);
MessageBox(NULL, _T("Product Code: ") + (CString)szInstalledProductCode + _T("\r\n\r\nProduct Name: ") + lpProductName, _T("Product Name:"), MB_OK);
dwIndex++;
}
return 0;
}
Procedure: You need to do a few things before the above has any hope of working.
- Just create a Visual C++ console project. I used Visual Studio 2017.
- Determine what the user SID is for the account whose per-user packages you want to retrieve. You can use
whoami /user
from the command line as explained here: How to get active session user SID?
- Change the
CString userSID = "S-1-5-21-etc..."
line to have the user SID in question retrieved from your system.
In order to get the list of user SIDs from the system I am not sure what to do. If you have a good approach please share.
There are methods and properties available for VBScripting as well that I tried, but I was not able to retrieve other user's packages. I probably just lacks a few parameters, I am not sure.