Escrevendo um recurso personalizado de DSC com classes do PowerShellWriting a custom DSC resource with PowerShell classes

Aplica-se a: Windows Windows PowerShell 5.0Applies To: Windows Windows PowerShell 5.0

Com a introdução de classes do PowerShell no Windows PowerShell 5.0, já é possível definir um recurso de DSC criando uma classe.With the introduction of PowerShell classes in Windows PowerShell 5.0, you can now define a DSC resource by creating a class. A classe define o esquema e a implementação do recurso; portanto, não há necessidade de criar um arquivo MOF separado.The class defines both the schema and the implementation of the resource, so there is no need to create a separate MOF file. A estrutura de pastas para um recurso baseado em classe também é mais simples, pois uma pasta DSCResources não é necessária.The folder structure for a class-based resource is also simpler, because a DSCResources folder is not necessary.

Em um recurso de DSC baseado em classes, o esquema é definido como propriedades da classe que pode ser modificado com atributos para especificar o tipo de propriedade...In a class-based DSC resource, the schema is defined as properties of the class which can be modified with attributes to specify the property type.. O recurso é implementado pelos métodos Get (), Set() e Test () (equivalentes às funções Get-TargetResource, Set-TargetResource e Test-TargetResource em um recurso de script).The resource is implemented by Get(), Set(), and Test() methods (equivalent to the Get-TargetResource, Set-TargetResource, and Test-TargetResource functions in a script resource.

Neste tópico, criaremos um recurso simples chamado FileResource, que gerencia um arquivo em um caminho especificado.In this topic, we will create a simple resource named FileResource that manages a file in a specified path.

Para obter mais informações sobre recursos de DSC, consulte Criar recursos personalizados de configuração de estado desejado do Windows PowerShellFor more information about DSC resources, see Build Custom Windows PowerShell Desired State Configuration Resources

Observação: não há suporte para coleções genéricas em recursos baseados em classe.Note: Generic collections are not supported in class-based resources.

Estrutura de pastas para um recurso de classeFolder structure for a class resource

Para implementar um recurso personalizado de DSC com uma classe do PowerShell, crie a seguinte estrutura de pastas.To implement a DSC custom resource with a PowerShell class, create the following folder structure. A classe é definida em MyDscResource.psm1 e o manifesto de módulo é definido em MyDscResource.psd1.The class is defined in MyDscResource.psm1 and the module manifest is defined in MyDscResource.psd1.

$env:ProgramFiles\WindowsPowerShell\Modules (folder)
    |- MyDscResource (folder)
        |- MyDscResource.psm1 
           MyDscResource.psd1 

Criar a classeCreate the class

A palavra-chave class é utilizada para criar uma classe do PowerShell.You use the class keyword to create a PowerShell class. Para especificar que uma classe é um recurso de DSC, use o atributo DscResource().To specify that a class is a DSC resource, use the DscResource() attribute. O nome da classe é o nome do recurso de DSC.The name of the class is the name of the DSC resource.

[DscResource()]
class FileResource {
}

Declarar propriedadesDeclare properties

O esquema do recurso de DSC é definido como propriedades da classe.The DSC resource schema is defined as properties of the class. Declaramos três propriedades da seguinte maneira.We declare three properties as follows.

[DscProperty(Key)]
[string]$Path

[DscProperty(Mandatory)]
[Ensure] $Ensure

[DscProperty(Mandatory)]
[string] $SourcePath

[DscProperty(NotConfigurable)]
[Nullable[datetime]] $CreationTime

Observe que as propriedades são modificadas por atributos.Notice that the properties are modified by attributes. O significado dos atributos é o seguinte:The meaning of the attributes is as follows:

  • DscProperty(Key): a propriedade é obrigatória.DscProperty(Key): The property is required. A propriedade é uma chave.The property is a key. Os valores de todas as propriedades marcadas como chaves devem se combinar para identificar exclusivamente uma instância de recursos dentro de uma configuração.The values of all properties marked as keys must combine to uniquely identify a resource instance within a configuration.
  • DscProperty(Mandatory): a propriedade é obrigatória.DscProperty(Mandatory): The property is required.
  • DscProperty(NotConfigurable): a propriedade é somente leitura.DscProperty(NotConfigurable): The property is read-only. As propriedades marcadas com esse atributo não podem ser definidas por uma configuração, mas são preenchidas pelo método Get () quando presentes.Properties marked with this attribute cannot be set by a configuration, but are populated by the Get() method when present.
  • DscProperty(): a propriedade é configurável, mas não é obrigatória.DscProperty(): The property is configurable, but it is not required.

As propriedades $Path e $SourcePath são ambas cadeias de caracteres.The $Path and $SourcePath properties are both strings. O $CreationTime é uma propriedade DateTime.The $CreationTime is a DateTime property. A propriedade $Ensure é um tipo de enumeração definido da seguinte maneira.The $Ensure property is an enumeration type, defined as follows.

enum Ensure 
{ 
    Absent 
    Present 
}

Implementando os métodosImplementing the methods

Os métodos Get(), Set() e Test() são análogos às funções Get-TargetResource, Set-TargetResource e Test-TargetResource em um recurso de script.The Get(), Set(), and Test() methods are analogous to the Get-TargetResource, Set-TargetResource, and Test-TargetResource functions in a script resource.

Esse código também inclui a função CopyFile (), uma função auxiliar que copia o arquivo de $SourcePath para $Path.This code also includes the CopyFile() function, a helper function that copies the file from $SourcePath to $Path.


    <#
        This method is equivalent of the Set-TargetResource script function.
        It sets the resource to the desired state.
    #>
    [void] Set()
    {
        $fileExists = $this.TestFilePath($this.Path)

        if ($this.ensure -eq [Ensure]::Present)
        {
            if(-not $fileExists)
            {
                $this.CopyFile()
            }
        }
        else
        {
            if ($fileExists)
            {
                Write-Verbose -Message "Deleting the file $($this.Path)"
                Remove-Item -LiteralPath $this.Path -Force
            }
        }
    }

    <#
        This method is equivalent of the Test-TargetResource script function.
        It should return True or False, showing whether the resource
        is in a desired state.
    #>
    [bool] Test()
    {
        $present = $this.TestFilePath($this.Path)

        if ($this.Ensure -eq [Ensure]::Present)
        {
            return $present
        }
        else
        {
            return -not $present
        }
    }

    <#
        This method is equivalent of the Get-TargetResource script function.
        The implementation should use the keys to find appropriate resources.
        This method returns an instance of this class with the updated key
         properties.
    #>
    [FileResource] Get()
    {
        $present = $this.TestFilePath($this.Path)

        if ($present)
        {
            $file = Get-ChildItem -LiteralPath $this.Path
            $this.CreationTime = $file.CreationTime
            $this.Ensure = [Ensure]::Present
        }
        else
        {
            $this.CreationTime = $null
            $this.Ensure = [Ensure]::Absent
        }

        return $this
    }

    <#
        Helper method to check if the file exists and it is file
    #>
    [bool] TestFilePath([string] $location)
    {
        $present = $true

        $item = Get-ChildItem -LiteralPath $location -ErrorAction Ignore

        if ($item -eq $null)
        {
            $present = $false
        }
        elseif ($item.PSProvider.Name -ne "FileSystem")
        {
            throw "Path $($location) is not a file path."
        }
        elseif ($item.PSIsContainer)
        {
            throw "Path $($location) is a directory path."
        }

        return $present
    }

    <#
        Helper method to copy file from source to path
    #>
    [void] CopyFile()
    {
        if (-not $this.TestFilePath($this.SourcePath))
        {
            throw "SourcePath $($this.SourcePath) is not found."
        }

        [System.IO.FileInfo] $destFileInfo = New-Object -TypeName System.IO.FileInfo($this.Path)

        if (-not $destFileInfo.Directory.Exists)
        {
            Write-Verbose -Message "Creating directory $($destFileInfo.Directory.FullName)"

            <#
                Use CreateDirectory instead of New-Item to avoid code
                to handle the non-terminating error
            #>
            [System.IO.Directory]::CreateDirectory($destFileInfo.Directory.FullName)
        }

        if (Test-Path -LiteralPath $this.Path -PathType Container)
        {
            throw "Path $($this.Path) is a directory path"
        }

        Write-Verbose -Message "Copying $($this.SourcePath) to $($this.Path)"

        # DSC engine catches and reports any error that occurs
        Copy-Item -LiteralPath $this.SourcePath -Destination $this.Path -Force
    }

O arquivo completoThe complete file

Segue o arquivo de classe completo.The complete class file follows.

enum Ensure
{
    Absent
    Present
}

<#
   This resource manages the file in a specific path.
   [DscResource()] indicates the class is a DSC resource
#>

[DscResource()]
class FileResource
{
    <#
       This property is the fully qualified path to the file that is
       expected to be present or absent.

       The [DscProperty(Key)] attribute indicates the property is a
       key and its value uniquely identifies a resource instance.
       Defining this attribute also means the property is required
       and DSC will ensure a value is set before calling the resource.

       A DSC resource must define at least one key property.
    #>
    [DscProperty(Key)]
    [string]$Path

    <#
        This property indicates if the settings should be present or absent
        on the system. For present, the resource ensures the file pointed
        to by $Path exists. For absent, it ensures the file point to by
        $Path does not exist.

        The [DscProperty(Mandatory)] attribute indicates the property is
        required and DSC will guarantee it is set.

        If Mandatory is not specified or if it is defined as
        Mandatory=$false, the value is not guaranteed to be set when DSC
        calls the resource.  This is appropriate for optional properties.
    #>
    [DscProperty(Mandatory)]
    [Ensure] $Ensure

    <#
       This property defines the fully qualified path to a file that will
       be placed on the system if $Ensure = Present and $Path does not
        exist.

       NOTE: This property is required because [DscProperty(Mandatory)] is
        set.
    #>
    [DscProperty(Mandatory)]
    [string] $SourcePath

    <#
       This property reports the file's create timestamp.

       [DscProperty(NotConfigurable)] attribute indicates the property is
       not configurable in DSC configuration.  Properties marked this way
       are populated by the Get() method to report additional details
       about the resource when it is present.

    #>
    [DscProperty(NotConfigurable)]
    [Nullable[datetime]] $CreationTime

    <#
        This method is equivalent of the Set-TargetResource script function.
        It sets the resource to the desired state.
    #>
    [void] Set()
    {
        $fileExists = $this.TestFilePath($this.Path)
        if ($this.ensure -eq [Ensure]::Present)
        {
            if (-not $fileExists)
            {
                $this.CopyFile()
            }
        }
        else
        {
            if ($fileExists)
            {
                Write-Verbose -Message "Deleting the file $($this.Path)"
                Remove-Item -LiteralPath $this.Path -Force
            }
        }
    }

    <#
        This method is equivalent of the Test-TargetResource script function.
        It should return True or False, showing whether the resource
        is in a desired state.
    #>
    [bool] Test()
    {
        $present = $this.TestFilePath($this.Path)

        if ($this.Ensure -eq [Ensure]::Present)
        {
            return $present
        }
        else
        {
            return -not $present
        }
    }

    <#
        This method is equivalent of the Get-TargetResource script function.
        The implementation should use the keys to find appropriate resources.
        This method returns an instance of this class with the updated key
         properties.
    #>
    [FileResource] Get()
    {
        $present = $this.TestFilePath($this.Path)

        if ($present)
        {
            $file = Get-ChildItem -LiteralPath $this.Path
            $this.CreationTime = $file.CreationTime
            $this.Ensure = [Ensure]::Present
        }
        else
        {
            $this.CreationTime = $null
            $this.Ensure = [Ensure]::Absent
        }

        return $this
    }

    <#
        Helper method to check if the file exists and it is file
    #>
    [bool] TestFilePath([string] $location)
    {
        $present = $true

        $item = Get-ChildItem -LiteralPath $location -ea Ignore
        if ($item -eq $null)
        {
            $present = $false
        }
        elseif ($item.PSProvider.Name -ne "FileSystem")
        {
            throw "Path $($location) is not a file path."
        }
        elseif ($item.PSIsContainer)
        {
            throw "Path $($location) is a directory path."
        }

        return $present
    }

    <#
        Helper method to copy file from source to path
    #>
    [void] CopyFile()
    {
        if (-not $this.TestFilePath($this.SourcePath))
        {
            throw "SourcePath $($this.SourcePath) is not found."
        }

        [System.IO.FileInfo] $destFileInfo = new-object System.IO.FileInfo($this.Path)
        if (-not $destFileInfo.Directory.Exists)
        {
            Write-Verbose -Message "Creating directory $($destFileInfo.Directory.FullName)"

            <#
                Use CreateDirectory instead of New-Item to avoid code
                 to handle the non-terminating error
            #>
            [System.IO.Directory]::CreateDirectory($destFileInfo.Directory.FullName)
        }

        if (Test-Path -LiteralPath $this.Path -PathType Container)
        {
            throw "Path $($this.Path) is a directory path"
        }

        Write-Verbose -Message "Copying $($this.SourcePath) to $($this.Path)"

        # DSC engine catches and reports any error that occurs
        Copy-Item -LiteralPath $this.SourcePath -Destination $this.Path -Force
    }
} # This module defines a class for a DSC "FileResource" provider.

Criar um manifestoCreate a manifest

Para disponibilizar um recurso baseado em classes para o mecanismo de DSC, você precisa incluir uma declaração DscResourcesToExport no arquivo de manifesto que instrui o módulo para exportar recursos.To make a class-based resource available to the DSC engine, you must include a DscResourcesToExport statement in the manifest file that instructs the module to export the resource. Nosso manifesto tem essa aparência:Our manifest looks like this:

@{

# Script module or binary module file associated with this manifest.
RootModule = 'MyDscResource.psm1'

DscResourcesToExport = 'FileResource'

# Version number of this module.
ModuleVersion = '1.0'

# ID used to uniquely identify this module
GUID = '81624038-5e71-40f8-8905-b1a87afe22d7'

# Author of this module
Author = 'Microsoft Corporation'

# Company or vendor of this module
CompanyName = 'Microsoft Corporation'

# Copyright statement for this module
Copyright = '(c) 2014 Microsoft. All rights reserved.'

# Description of the functionality provided by this module
# Description = ''

# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '5.0'

# Name of the Windows PowerShell host required by this module
# PowerShellHostName = ''
} 

Testar o recursoTest the resource

Depois de salvar a classe e os arquivos de manifesto na estrutura de pastas, conforme descrito anteriormente, você pode criar uma configuração que use o novo recurso.After saving the class and manifest files in the folder structure as described earlier, you can create a configuration that uses the new resource. Para obter informações sobre como executar uma configuração DSC, consulte Impondo configurações.For information about how to run a DSC configuration, see Enacting configurations. A configuração a seguir verificará se o arquivo em c:\test\test.txt existe e, em caso negativo, copia o arquivo de c:\test.txt (você deve criar c:\test.txt antes de executar a configuração).The following configuration will check to see whether the file at c:\test\test.txt exists, and, if not, copies the file from c:\test.txt (you should create c:\test.txt before you run the configuration).

Configuration Test
{
    Import-DSCResource -module MyDscResource
    FileResource file
    {
        Path = "C:\test\test.txt"
        SourcePath = "c:\test.txt"
        Ensure = "Present"
    } 
}
Test
Start-DscConfiguration -Wait -Force Test

Dando suporte a PsDscRunAsCredentialSupporting PsDscRunAsCredential

Observação: PsDscRunAsCredential tem suporte no PowerShell 5.0 e posterior.Note: PsDscRunAsCredential is supported in PowerShell 5.0 and later.

A propriedade PsDscRunAsCredential pode ser usada no bloco de recurso Configurações DSC para especificar que o recurso deve ser executado em um conjunto de credenciais específico.The PsDscRunAsCredential property can be used in DSC configurations resource block to specify that the resource should be run under a specified set of credentials. Para obter mais informações, veja Executando o DSC com as credenciais do usuário.For more information, see Running DSC with user credentials.

Solicitar ou desautorizar PsDscRunAsCredential para o recursoRequire or disallow PsDscRunAsCredential for your resource

O atributo DscResource() usa um parâmetro opcional RunAsCredential.The DscResource() attribute takes an optional parameter RunAsCredential. Esse parâmetro usa um dos três valores:This parameter takes one of three values:

  • Optional O PsDscRunAsCredential é opcional para as configurações que chamam esse recurso.Optional PsDscRunAsCredential is optional for configurations that call this resource. Este é o valor padrão.This is the default value.
  • Mandatory O PsDscRunAsCredential deve ser usado para qualquer configuração que chame esse recurso.Mandatory PsDscRunAsCredential must be used for any configuration that calls this resource.
  • NotSupported As configurações que chamam este recurso não podem usar o PsDscRunAsCredential.NotSupported Configurations that call this resource cannot use PsDscRunAsCredential.
  • Default Igual a Optional.Default Same as Optional.

Por exemplo, use o seguinte atributo para especificar que o recurso personalizado não dá suporte ao uso de PsDscRunAsCredential:For example, use the following attribute to specify that your custom resource does not support using PsDscRunAsCredential:

[DscResource(RunAsCredential=NotSupported)]
class FileResource {
}

Acessar o contexto do usuárioAccess the user context

Para acessar o contexto do usuário de dentro de um recurso personalizado, você pode usar a variável automática $global:PsDscContext.To access the user context from within a custom resource, you can use the automatic variable $global:PsDscContext.

Por exemplo, o código a seguir escreveria o contexto do usuário em que o recurso está em execução para o fluxo de saída detalhada:For example the following code would write the user context under which the resource is running to the verbose output stream:

if (PsDscContext.RunAsUser) {
    Write-Verbose "User: $global:PsDscContext.RunAsUser";
}

Consulte TambémSee Also

ConceitosConcepts

Criar recursos personalizados de configuração de estado desejado do Windows PowerShellBuild Custom Windows PowerShell Desired State Configuration Resources