Sdílet prostřednictvím


Vytvoření prostředku DSC s jednou instancí

Poznámka

Tento článek popisuje osvědčený postup pro definování prostředku DSC, který umožňuje pouze jednu instanci v konfiguraci DSC. K tomu není integrovaná funkce DSC. To se může v budoucnu změnit.

Existují situace, kdy nechcete, aby se prostředek DSC v konfiguraci DSC používal vícekrát. Například v předchozí implementaci prostředku xTimeZone DSC mohla konfigurace DSC volat prostředek DSC vícekrát a nastavit časové pásmo na jiné nastavení v každém bloku prostředků DSC:

Configuration SetTimeZone {
    param (
        [String[]]$NodeName = $env:COMPUTERNAME
    )

    Import-DSCResource -ModuleName xTimeZone

    Node $NodeName {
         xTimeZone TimeZoneExample {
            TimeZone = 'Eastern Standard Time'
         }

         xTimeZone TimeZoneExample2 {
            TimeZone = 'Pacific Standard Time'
         }
    }
}

Důvodem je způsob, jakým fungují vlastnosti klíče prostředku DSC. Prostředek DSC musí mít aspoň jednu vlastnost Key . Instance prostředku DSC se považuje za jedinečnou, pokud je jedinečná kombinace hodnot všech jeho klíčových vlastností.

V předchozí implementaci měl prostředek xTimeZone DSC pouze jednu vlastnost – TimeZone, což byl klíč. Z tohoto důvodu se ukázková konfigurace DSC zkompilovala a spustila bez upozornění. Každý z xTimeZone bloků prostředků DSC byl považován za jedinečný. To způsobilo, že se konfigurace DSC opakovaně použila na systém a přejížděla časové pásmo tam a zpět.

Aby se zajistilo, že konfigurace DSC může nastavit časové pásmo pro systém pouze jednou, aktualizoval se prostředek DSC a přidal druhou vlastnost IsSingleInstance, která se stala vlastností Key . IsSingleInstance byla omezena na jednu hodnotu , Yes. Původní schéma MOF pro prostředek DSC bylo:

[ClassVersion("1.0.0.0"), FriendlyName("xTimeZone")]
class xTimeZone : OMI_BaseResource
{
    [Key, Description("Specifies the TimeZone.")] String TimeZone;
};

Aktualizované schéma MOF pro prostředek DSC:

[ClassVersion("1.0.0.0"), FriendlyName("xTimeZone")]
class xTimeZone : OMI_BaseResource
{
    [Key, Description("Specifies the resource is a single instance, the value must be 'Yes'"), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance;
    [Required, Description("Specifies the TimeZone.")] String TimeZone;
};

Implementace prostředku DSC se aktualizovala tak, aby používala nový parametr. Změnila se takto:

function Get-TargetResource
{
    [CmdletBinding()]
    [OutputType([Hashtable])]
    param
    (
        [parameter(Mandatory = $true)]
        [ValidateSet('Yes')]
        [String]
        $IsSingleInstance,

        [parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $TimeZone
    )

    #Get the current TimeZone
    $CurrentTimeZone = Get-TimeZone

    $returnValue = @{
        TimeZone = $CurrentTimeZone
        IsSingleInstance = 'Yes'
    }

    #Output the target resource
    $returnValue
}

function Set-TargetResource
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)]
        [ValidateSet('Yes')]
        [String]
        $IsSingleInstance,

        [parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $TimeZone
    )

    #Output the result of Get-TargetResource function.
    $CurrentTimeZone = Get-TimeZone

    Write-Verbose -Message "Replace the System Time Zone to $TimeZone"

    try
    {
        if($CurrentTimeZone -ne $TimeZone)
        {
            Write-Verbose -Verbose "Setting the TimeZone"
            Set-TimeZone -TimeZone $TimeZone
        }
        else
        {
            Write-Verbose -Verbose "TimeZone already set to $TimeZone"
        }
    }
    catch
    {
        $ErrorMsg = $_.Exception.Message
        Write-Verbose -Verbose $ErrorMsg
    }
}


function Test-TargetResource
{
    [CmdletBinding()]
    [OutputType([Boolean])]
    param
    (
        [parameter(Mandatory = $true)]
        [ValidateSet('Yes')]
        [String]
        $IsSingleInstance,

        [parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $TimeZone
    )

    #Output from Get-TargetResource
    $CurrentTimeZone = Get-TimeZone

    if($TimeZone -eq $CurrentTimeZone)
    {
        return $true
    }
    else
    {
        return $false
    }
}

Function Get-TimeZone {
    [CmdletBinding()]
    param()

    & tzutil.exe /g
}

Function Set-TimeZone {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [System.String]
        $TimeZone
    )

    try
    {
        & tzutil.exe /s $TimeZone
    }
    catch
    {
        $ErrorMsg = $_.Exception.Message
        Write-Verbose $ErrorMsg
    }
}

Export-ModuleMember -Function *-TargetResource

Všimněte si, že vlastnost TimeZone už není Key vlastnost. Pokud se konfigurace DSC pokusí nastavit časové pásmo dvakrát (se dvěma různými xTimeZone bloky s různými hodnotami TimeZone ), při pokusu o kompilaci konfigurace DSC dojde k chybě:

Write-Error:
Line |
 289 |          Test-ConflictingResources $keywordName $canonicalizedValue $k …
     |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | A conflict was detected between resources '[xTimeZone]TimeZoneExample (C:\code\dsc\DscExample.ps1::9::10::xTimeZone)' and '[xTimeZone]TimeZoneExample2 (C:\code\dsc\DscExample.ps1::14::10::xTimeZone)' in node 'DESKTOP-KFLGVVP'. Resources have identical key properties but there are differences in the following non-key properties: 'TimeZone'. Values 'Eastern Standard Time' don't match values 'Pacific Standard Time'. Please update these property values so that they are identical in both cases.
InvalidOperation: Errors occurred while processing configuration 'SetTimeZone'.