Bestimmen des Installationskontexts

Eine Anwendung kann die Funktionen MsiEnumProducts oder MsiEnumProductsEx aufrufen, um die auf dem System installierten oder angekündigten Produkte aufzulisten. Diese Funktion kann alle Produkte auflisten, die im Installationskontext pro Computer installiert sind. Sie kann die Produkte aufzählen, die im benutzerspezifischen Kontext für die aktuellen Benutzer*innen installiert sind. Die Anwendung kann Informationen zum Kontext dieser Produkte abrufen, indem sie die Funktionen MsiGetProductInfoEx oder MsiGetProductInfo aufruft.

Der Windows Installer kann Produkte so installieren, dass sie mit erweiterten Berechtigungen (Systemrechten) für Benutzer*innen ohne Administratorrechte ausgeführt werden. Dies erfordert die Berechtigung eines Administratorbenutzers bzw. einer Administratorbenutzerin. Mit erhöhten Rechten installierte Produkte werden als „verwaltet“ bezeichnet. Alle Produkte, die pro Computer installiert werden, sind verwaltet. Pro Benutzer installierte Produkte werden nur verwaltet, wenn ein lokaler System-Agent mit angenommener Benutzeridentität eine Ankündigung durchführt. Dies ist die Methode, die bei einer Softwarebereitstellung über Gruppenrichtlinien verwendet wird. Benutzerspezifische Anwendungen, die installiert werden, während die AlwaysInstallElevated-Richtlinien festgelegt sind, werden nicht als verwaltet betrachtet. Durch den Aufruf von MsiIsProductElevated kann eine Anwendung überprüfen, ob ein bestimmtes Produkt verwaltet wird.

Das folgende Beispiel zeigt, wie eine Anwendung den Kontext mithilfe von MsiEnumProducts, MsiGetProductInfo und MsiIsProductElevated ermittelt.

#ifndef UNICODE
#define UNICODE
#endif //UNICODE

#ifndef _WIN32_MSI
#define _WIN32_MSI 200
#endif //_WIN32_MSI

#include <stdio.h>
#include <windows.h>
#include <msi.h>
#pragma comment(lib, "msi.lib")

const int cchGUID = 38;

UINT DetermineContextForAllProducts()
{
    WCHAR wszProductCode[cchGUID+1] = {0};
    WCHAR wszAssignmentType[10] = {0};
    DWORD cchAssignmentType = 
            sizeof(wszAssignmentType)/sizeof(wszAssignmentType[0]);
    DWORD dwIndex = 0;

    DWORD cchProductName = MAX_PATH;
    WCHAR* lpProductName = new WCHAR[cchProductName];
    if (!lpProductName)
    {
        return ERROR_OUTOFMEMORY;
    }

    UINT uiStatus = ERROR_SUCCESS;

    // enumerate all visible products
    do
    {
        uiStatus = MsiEnumProducts(dwIndex,
                          wszProductCode);
        if (ERROR_SUCCESS == uiStatus)
        {
            cchAssignmentType = 
                sizeof(wszAssignmentType)/sizeof(wszAssignmentType[0]);
            BOOL fPerMachine = FALSE;
            BOOL fManaged = FALSE;

            // Determine assignment type of product
            // This indicates whether the product
            // instance is per-user or per-machine
            if (ERROR_SUCCESS == 
                MsiGetProductInfo(wszProductCode,INSTALLPROPERTY_ASSIGNMENTTYPE,wszAssignmentType,&cchAssignmentType))
            {
                if (L'1' == wszAssignmentType[0])
                    fPerMachine = TRUE;
            }
            else
            {
                // This halts the enumeration and fails. Alternatively the error
                // could be logged and enumeration continued for the
                // remainder of the products
                uiStatus = ERROR_FUNCTION_FAILED;
                break;
            }

            // determine the "managed" status of the product.
            // If fManaged is TRUE, product is installed managed
            // and runs with elevated privileges.
            // If fManaged is FALSE, product installation operations
            // run as the user.
            if (ERROR_SUCCESS != MsiIsProductElevated(wszProductCode,
                                         &fManaged))
            {
                // This halts the enumeration and fails. Alternatively the error
                // could be logged and enumeration continued for the
                // remainder of the products
                uiStatus = ERROR_FUNCTION_FAILED;
                break;
            }

            // obtain the user friendly name of the product
            UINT uiReturn = MsiGetProductInfo(wszProductCode,INSTALLPROPERTY_PRODUCTNAME,lpProductName,&cchProductName);
            if (ERROR_MORE_DATA == uiReturn)
            {
                // try again, but with a larger product name buffer
                delete [] lpProductName;

                // returned character count does not include
                // terminating NULL
                ++cchProductName;

                lpProductName = new WCHAR[cchProductName];
                if (!lpProductName)
                {
                    uiStatus = ERROR_OUTOFMEMORY;
                    break;
                }

                uiReturn = MsiGetProductInfo(wszProductCode,INSTALLPROPERTY_PRODUCTNAME,lpProductName,&cchProductName);
            }

            if (ERROR_SUCCESS != uiReturn)
            {
                // This halts the enumeration and fails. Alternatively the error
                // could be logged and enumeration continued for the
                // remainder of the products
                uiStatus = ERROR_FUNCTION_FAILED;
                break;
            }

            // output information
            wprintf(L" Product %s:\n", lpProductName);
            wprintf(L"\t%s\n", wszProductCode);
                        wprintf(L"\tInstalled %s %s\n", 
                fPerMachine ? L"per-machine" : L"per-user",
                fManaged ? L"managed" : L"non-managed");
        }
        dwIndex++;
    }
    while (ERROR_SUCCESS == uiStatus);

    if (lpProductName)
    {
        delete [] lpProductName;
        lpProductName = NULL;
    }

    return (ERROR_NO_MORE_ITEMS == uiStatus) ? ERROR_SUCCESS : uiStatus;
}

MsiEnumProducts

MsiGetProductInfo

MsiGetProductInfoEx

MsiIsProductElevated

Installieren eines Pakets mit erhöhten Rechten für Nicht-Administrator*innen

Ankündigen einer mit erhöhten Rechten zu installierenden benutzerspezifischen Anwendung

Installationskontext