Delen via


Generatie-id van virtuele machine

Windows 8 en Windows Server 2012 introduceren de mogelijkheid voor software die wordt uitgevoerd op een virtuele machine om te detecteren dat er een time shift-gebeurtenis heeft plaatsgevonden. Time shift-gebeurtenissen kunnen optreden als gevolg van een toepassing van een momentopname van een virtuele machine of het herstellen van een back-up van een virtuele machine. Zie het white paper Virtual Machine Generation IDvoor meer informatie over deze functionaliteit.

Voorwaarden

Als u de generatie-id van de virtuele machine wilt gebruiken vanuit een virtuele machine, moet uw virtuele machine voldoen aan het volgende.

  • De virtuele machine moet worden uitgevoerd op een hypervisor die ondersteuning implementeert voor generatie-id's van virtuele machines. Dit zijn momenteel de volgende:

    • Windows 8
    • Windows Server 2012
    • Microsoft Hyper-V Server 2012
  • Op de virtuele machine moet een gastbesturingssysteem worden uitgevoerd dat ondersteuning biedt voor de generatie-id van de virtuele machine. Dit zijn momenteel de volgende.

    De volgende besturingssystemen hebben systeemeigen ondersteuning voor de generatie-id van de virtuele machine.

    • Windows 8
    • Windows Server 2012

    Het volgende besturingssysteem kan worden gebruikt als gastbesturingssysteem als de Hyper-V integratieservices van Windows 8 of Windows Server 2012 zijn geïnstalleerd.

    • Windows Server 2008 R2 met Service Pack 1 (SP1)
    • Windows 7 met Service Pack 1 (SP1)
    • Windows Server 2008 met Service Pack 2 (SP2)
    • Windows Server 2003 R2
    • Windows Server 2003 met Service Pack 2 (SP2)
    • Windows Vista met Service Pack 2 (SP2)
    • Windows XP met Service Pack 3 (SP3)

De generatie-id van de virtuele machine verkrijgen

Voer de volgende stappen uit om programmatisch de generatie-id van de virtuele machine te verkrijgen.

Notitie

Het volgende moet worden uitgevoerd met beheerders- of systeembeheerdersbevoegdheden om correct te kunnen functioneren.

 

  1. Voeg het headerbestand 'vmgenerationcounter.h' toe aan uw app. Het headerbestand bevat de volgende definities:

    DEFINE_GUID(
        GUID_DEVINTERFACE_VM_GENCOUNTER,
        0x3ff2c92b, 
        0x6598, 
        0x4e60, 
        0x8e, 
        0x1c, 
        0x0c, 
        0xcf, 
        0x49, 
        0x27, 
        0xe3, 
        0x19);
    
    #define VM_GENCOUNTER_SYMBOLIC_LINK_NAME L"VmGenerationCounter"
    
    #define IOCTL_VMGENCOUNTER_READ CTL_CODE( \
        FILE_DEVICE_ACPI, \
        0x1, METHOD_BUFFERED, \
        FILE_READ_ACCESS | FILE_WRITE_ACCESS)
    
    typedef struct _VM_GENCOUNTER
    {
        ULONGLONG GenerationCount;
        ULONGLONG GenerationCountHigh;
    } VM_GENCOUNTER, *PVM_GENCOUNTER;
    
  2. Open een ingang naar het apparaat \\.\VmGenerationCounter met behulp van de functie CreateFile. U kunt de PnP-manager ook gebruiken om de apparaatinterface te gebruiken GUID_DEVINTERFACE_VM_GENCOUNTER ({3ff2c92b-6598-4e60-8e1c-0ccf4927e319}). Deze objecten zijn niet aanwezig als de app niet wordt uitgevoerd op een virtuele machine.

  3. Verzend de IOCTL_VMGENCOUNTER_READ IOCTL naar het stuurprogramma om de generatie-id op te halen.

    De IOCTL_VMGENCOUNTER_READ IOCTL werkt in een van de twee modi, pollingen gebeurtenisgestuurde.

    Als u de IOCTL wilt uitgeven in de pollingmodus, verzendt u de IOCTL met een invoerbuffer van nul lengte. Als reactie hierop haalt het stuurprogramma de huidige generatie-id op, schrijft deze naar de uitvoerbuffer en voltooit het de IOCTL.

    Als u de IOCTL wilt uitgeven in de gebeurtenisgestuurde modus, dient u de IOCTL in met een invoerbuffer die een bestaande generatie-id bevat. Als reactie hierop wacht het stuurprogramma totdat de huidige generatie-id verschilt van de generatie-id die is doorgegeven. Wanneer de generatie-id wordt gewijzigd, schrijft het stuurprogramma de huidige generatie-id naar de uitvoerbuffer en wordt de IOCTL voltooid.

    In beide modi wordt de indeling en lengte van de uitvoerbuffer bepaald door de VM_GENCOUNTER structuur.

    De pollingmodus wordt ondersteund op alle hierboven vermelde gastbesturingssystemen. Gebeurtenisgestuurde modus wordt alleen ondersteund op Windows Vista met SP2, Windows Server 2008 met SP2 en latere besturingssystemen. Op eerdere besturingssystemen mislukt de IOCTL met de foutcode ERROR_NOT_SUPPORTED wanneer deze wordt uitgegeven in de gebeurtenisgestuurde modus.

    Het is mogelijk dat de generatie-id verandert tussen de tijd die door het stuurprogramma wordt opgehaald en de tijd waarop de IOCTL is voltooid. Dit kan ertoe leiden dat de client-app verouderde gegevens ontvangt. Om dit te voorkomen, kan de client-app de gebeurtenisgestuurde modus gebruiken om ervoor te zorgen dat deze uiteindelijk meer te weten komt over updates van de generatie-id. Door de huidige id van de client-app als invoer te gebruiken, voorkomt gebeurtenisgestuurde modus mogelijke racevoorwaarden die ervoor zorgen dat de beller meldingen mist.

In het volgende codevoorbeeld ziet u hoe u de bovenstaande acties uitvoert om de generatie-id van de virtuele machine op te halen.

Notitie

De volgende code moet worden uitgevoerd met beheerders- of systeembeheerdersbevoegdheden om correct te kunnen functioneren.

 

HRESULT GetVmCounter(bool fWaitForChange)
{
    BOOL success = FALSE;
    DWORD error = ERROR_SUCCESS;
    VM_GENCOUNTER vmCounterOutput = {0};
    DWORD size = 0;
    HANDLE handle = INVALID_HANDLE_VALUE;
    HRESULT hr = S_OK;

    handle = CreateFile(
        L"\\\\.\\" VM_GENCOUNTER_SYMBOLIC_LINK_NAME,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);

    if (handle == INVALID_HANDLE_VALUE)
    {
        error = GetLastError();

        wprintf(
            L"Unable to open device %s. Error code = %d.", 
            VM_GENCOUNTER_SYMBOLIC_LINK_NAME, 
            error);

        hr = HRESULT_FROM_WIN32(error);

        goto Cleanup;
    }

    /*
    Call into the driver. 

    Because the 4th parameter to DeviceIoControl (nInBufferSize) is zero, this 
    is a polling request rather than an event-driven request.
    */
    success = DeviceIoControl(
        handle,
        IOCTL_VMGENCOUNTER_READ,
        NULL,
        0,
        &vmCounterOutput,
        sizeof(vmCounterOutput),
        &size,
        NULL);

    if (!success)
    {
        error = GetLastError();

        wprintf(L"Call IOCTL_VMGENCOUNTER_READ failed with %d.", error);

        hr = HRESULT_FROM_WIN32(error);

        goto Cleanup;
    }

    wprintf(
        L"VmCounterValue: %I64x:%I64x",
        vmCounterOutput.GenerationCount,
        vmCounterOutput.GenerationCountHigh);

    if (fWaitForChange)
    {
        /*
        Call into the driver again in event-driven mode. DeviceIoControl won't 
        return until the generation identifier has changed.
        */
        success = DeviceIoControl(
            handle,
            IOCTL_VMGENCOUNTER_READ,
            &vmCounterOutput,
            sizeof(vmCounterOutput),
            &vmCounterOutput,
            sizeof(vmCounterOutput),
            &size,
            NULL);

        if (!success)
        {
            error = GetLastError();

            wprintf(L"Call IOCTL_VMGENCOUNTER_READ failed with %d.", error);

            hr = HRESULT_FROM_WIN32(error);

            goto Cleanup;
        }

        wprintf(
            L"VmCounterValue changed to: %I64x:%I64x",
            vmCounterOutput.GenerationCount,
            vmCounterOutput.GenerationCountHigh);
    }

Cleanup:

    if (handle != INVALID_HANDLE_VALUE)
    {
        CloseHandle(handle);
    }

    return hr;
};

Bepalen of er een time shift-gebeurtenis heeft plaatsgevonden

Nadat u de generatie-id van de virtuele machine hebt verkregen, moet u deze opslaan voor toekomstig gebruik. Voordat uw app een tijdgevoelige bewerking uitvoert, zoals het doorvoeren van een database, moet u de generatie-id opnieuw verkrijgen en deze vergelijken met de opgeslagen waarde. Als de id is gewijzigd, betekent dit dat er een time shift-gebeurtenis is opgetreden en dat uw app op de juiste wijze moet handelen.