diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/APT/examples/manage-packages-with-apt.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/APT/examples/manage-packages-with-apt.md index a63f22b..b1ec689 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/APT/examples/manage-packages-with-apt.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/APT/examples/manage-packages-with-apt.md @@ -1,7 +1,7 @@ --- description: > Demonstrates how to manage packages with the DSC.PackageManagement/Apt resource -ms.date: 07/03/2025 +ms.date: 06/30/2025 ms.topic: reference title: Manage packages with APT --- @@ -23,8 +23,8 @@ dsc resource test --resource DSC.PackageManagement/Apt --input '{"packageName":" When the package is not installed, DSC returns the following result. > [!NOTE] -> Note that the version and source values can differ depending on your system's package -> repositories and available package versions. +> Note that the version and source values can differ depending on your system's package repositories +> and available package versions. ```yaml desiredState: @@ -41,7 +41,8 @@ differingProperties: ## Ensure a package is installed -To ensure the system is in the desired state, use the [dsc resource set][01] command. +To ensure the system is in the desired state, use the [dsc resource set][01] +command. ```bash dsc resource set --resource DSC.PackageManagement/Apt --input '{"packageName":"nginx"}' diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/APT/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/APT/index.md index 532925d..17ae400 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/APT/index.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/APT/index.md @@ -1,6 +1,6 @@ --- description: DSC.PackageManagement/Apt resource reference documentation -ms.date: 07/03/2025 +ms.date: 06/30/2025 ms.topic: reference title: DSC.PackageManagement/Apt --- @@ -118,8 +118,8 @@ IsWriteOnly : false -Defines the name of the package to query or install. This property is required and serves as the -key for uniquely identifying the package. +Defines the name of the package to query or install. This property is required and serves as the key +for uniquely identifying the package. ### _exist @@ -136,10 +136,10 @@ DefaultValue : true -The `_exist` canonical resource property determines whether a package should exist. When the value -for `_exist` is `true`, the resource installs the package if it doesn't exist. When the value for -`_exist` is `false`, the resource removes or uninstalls the package if it does exist. The default -value for this property when not specified for an instance is `true`. +The `_exist` canonical resource property determines whether a package should exist. When the +value for `_exist` is `true`, the resource installs the package if it doesn't exist. When +the value for `_exist` is `false`, the resource removes or uninstalls the package if it does exist. +The default value for this property when not specified for an instance is `true`. ### version diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/Brew/examples/install-a-package-with-brew.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/Brew/examples/install-a-package-with-brew.md new file mode 100644 index 0000000..13c1aa2 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/Brew/examples/install-a-package-with-brew.md @@ -0,0 +1,85 @@ +--- +description: > + Demonstrates how to install a package with the DSC.PackageManagement/Brew resource +ms.date: 07/03/2025 +ms.topic: reference +title: Install a package with Brew +--- + +# Install a package with Brew + +This example demonstrates how to use the `DSC.PackageManagement/Brew` resource to install a package +on macOS systems using Brew. + +## Test if package is installed + +The following snippet shows how you can use the resource with the [dsc resource test][00] command +to check whether the `node` package exists. + +```bash +dsc resource test --resource DSC.PackageManagement/Brew --input '{"packageName":"node"}' +``` + +When the package is not installed, DSC returns the following result. + +```yaml +desiredState: + packageName: node +actualState: + _exist: false + packageName: node + version: "" +inDesiredState: false +differingProperties: + - _exist +``` + +## Ensure a package is installed + +To ensure the system is in the desired state, use the [dsc resource set][01] +command. + +```bash +dsc resource set --resource DSC.PackageManagement/Brew --input '{"packageName":"node"}' +``` + +When the resource installs the package, DSC returns the following result: + +```yaml +beforeState: + packageName: "node" + version: "" + _exist: false +afterState: + _exist: true + packageName: node + version: "24.3.0" +changedProperties: +- _exist +- version +``` + +> [!NOTE] +> Note that the version can differ depending on your system's package repositories +> and available package versions. + +You can test the instance again to confirm that the package exists: + +```bash +dsc resource test --resource DSC.PackageManagement/Brew --input '{"packageName":"node"}' +``` + +```yaml +desiredState: + packageName: node +actualState: + _exist: true + packageName: node + version: "24.3.0" +inDesiredState: true +differingProperties: [] +``` + + +[00]: ../../../../../cli/resource/test.md +[01]: ../../../../../cli/resource/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/Brew/examples/remove-a-package.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/Brew/examples/remove-a-package.md new file mode 100644 index 0000000..72ed992 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/Brew/examples/remove-a-package.md @@ -0,0 +1,83 @@ +--- +description: > + Demonstrates how to remove a package with the DSC.PackageManagement/Brew resource +ms.date: 07/03/2025 +ms.topic: reference +title: Remove a package with Brew +--- + +# Remove a package with Brew + +This example demonstrates how to use the `DSC.PackageManagement/Brew` resource to remove a package +on macOS systems using Brew. + +## Test if package is installed + +The following snippet shows how you can use the resource with the [dsc resource test][00] command +to check whether the `node` package doesn't exist. + +```bash +dsc resource test --resource DSC.PackageManagement/Brew --input '{"packageName":"node","_exist":false}' +``` + +When the package is installed, DSC returns the following result. + +```yaml +desiredState: + packageName: node + _exist: false +actualState: + _exist: true + packageName: node + version: "24.3.0" +inDesiredState: false +differingProperties: + - _exist +``` + +## Ensure a package is removed + +To ensure the system is in the desired state, use the [dsc resource set][01] +command. + +```bash +dsc resource set --resource DSC.PackageManagement/Brew --input '{"packageName":"node","_exist":false}' +``` + +When the resource removes the package, DSC returns the following result: + +```yaml +beforeState: + packageName: "node" + version: "24.3.0" + _exist: true +afterState: + _exist: false + packageName: node + version: "" +changedProperties: +- _exist +- version +``` + +You can test the instance again to confirm that the package has been removed: + +```bash +dsc resource test --resource DSC.PackageManagement/Brew --input '{"packageName":"node","_exist":false}' +``` + +```yaml +desiredState: + packageName: node + _exist: false +actualState: + _exist: false + packageName: node + version: "" +inDesiredState: true +differingProperties: [] +``` + + +[00]: ../../../../../cli/resource/test.md +[01]: ../../../../../cli/resource/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/Brew/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/Brew/index.md new file mode 100644 index 0000000..4e0a15a --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/DSC/PackageManagement/Brew/index.md @@ -0,0 +1,205 @@ +--- +description: DSC.PackageManagement/Brew resource reference documentation +ms.date: 07/03/2025 +ms.topic: reference +title: DSC.PackageManagement/Brew +--- + +# DSC.PackageManagement/Brew + +## Synopsis + +Manage packages using Homebrew on macOS systems. + +> [!IMPORTANT] +> The `DSC.PackageManagement/Brew` resource is a proof-of-concept example +> for use with DSC. Don't use it in production. + +## Metadata + +```yaml +Version : 0.1.0 +Kind : resource +Tags : [macOS, brew, PackageManagement] +Author : Microsoft +``` + +## Instance definition syntax + +```yaml +resources: + - name: + type: DSC.PackageManagement/Brew + properties: + # Required properties + packageName: string + # Instance properties + _exist: boolean + version: string +``` + +## Description + +The `DSC.PackageManagement/Brew` resource enables you to idempotently manage packages using Homebrew +on macOS systems. The resource can: + +- Install packages +- Uninstall packages +- Check if a package is installed +- Verify the version of an installed package + +## Requirements + +- A macOS system with Homebrew installed +- Administrative privileges may be required for certain package operations + +## Capabilities + +The resource has the following capabilities: + +- `get` - You can use the resource to retrieve the actual state of an instance. +- `set` - You can use the resource to enforce the desired state for an instance. +- `export` - You can use the resource to export the current state of the system. + +This resource uses the synthetic test functionality of DSC to determine whether an instance is in +the desired state. For more information about resource capabilities, see +[DSC resource capabilities][00]. + +## Examples + +1. [Install a package with Brew][04] - Shows how to install a package using + `DSC.PackageManagement/Brew` resource. +1. [Remove a package][05] - Shows how to uninstall a package. + +## Properties + +The following list describes the properties for the resource. + +- **Required properties:** The following properties are always + required when defining an instance of the resource. An instance that doesn't define each of these + properties is invalid. For more information, see the "Required resource properties" section in + [DSC resource properties][01] + + - [packageName](#packagename) - The name of the package to query or install. + +- **Key properties:** The following properties uniquely identify an + instance. If two instances of a resource have the same values for their key properties, the + instances are conflicting. For more information about key properties, see the "Key resource + properties" section in [DSC resource properties][02]. + + - [packageName](#packagename) (required) - The name of the package to query or install. + +- **Instance properties:** The following properties are optional. + They define the desired state for an instance of the resource. + + - [_exist](#_exist) - Defines whether the package should exist. + - [version](#version) - The version of the package to install. + +### packageName + +
Expand for packageName property metadata + +```yaml +Type : string +IsRequired : true +IsKey : true +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines the name of the package to query or install. This property is required and serves as the key +for uniquely identifying the package in the Homebrew package repository. + +### _exist + +
Expand for _exist property metadata + +```yaml +Type : boolean +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +DefaultValue : true +``` + +
+ +The `_exist` canonical resource property determines whether a package should exist. When the +value for `_exist` is `true`, the resource installs the package if it doesn't exist. When +the value for `_exist` is `false`, the resource removes or uninstalls the package if it does exist. +The default value for this property when not specified for an instance is `true`. + +### version + +
Expand for version property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines the version of the package to install. If not specified, the latest available version will +be installed. + +## Instance validating schema + +The following snippet contains the JSON Schema that validates an instance of the resource. The +validating schema only includes schema keywords that affect how the instance is validated. All +non validating keywords are omitted. + +```json +{ + "type": "object", + "required": ["packageName"], + "additionalProperties": false, + "properties": { + "packageName": { + "type": "string" + }, + "version": { + "type": "string" + }, + "_exist": { + "type": "boolean" + } + } +} +``` + +## Exit codes + +The resource returns the following exit codes from operations: + +- [0](#exit-code-0) - Success +- [1](#exit-code-1) - Invalid parameter + +### Exit code 0 + +Indicates the resource operation completed without errors. + +### Exit code 1 + +Indicates the resource operation failed due to an invalid parameter. When the resource returns this +exit code, it also emits an error message with details about the invalid parameter. + +## See also + +- [DSC.PackageManagement/Apt resource][03] +- [For more information about Homebrew][06] + + +[00]: ../../../../../concepts/resources/capabilities.md +[01]: ../../../../../concepts/resources/properties.md#required-resource-properties +[02]: ../../../../../concepts/resources/properties.md#key-resource-properties +[03]: ../APT/index.md +[04]: ./examples/install-a-package-with-brew.md +[05]: ./examples/remove-a-package.md +[06]: https://brew.sh/ diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/PowerShell/examples/configure-a-machine.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/PowerShell/examples/configure-a-machine.md new file mode 100644 index 0000000..f21c30e --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/PowerShell/examples/configure-a-machine.md @@ -0,0 +1,235 @@ +--- +description: > + Example showing how to configure a machine using multiple class-based PowerShell DSC resources + with the Microsoft.Adapter/PowerShell adapter in a DSC configuration document. + +ms.date: 03/23/2026 +ms.topic: reference +title: Configure a machine with the PowerShell adapter +--- + +# Configure a machine with the PowerShell adapter + +This example shows how to use the `Microsoft.Adapter/PowerShell` adapter to configure a machine +using multiple class-based PowerShell DSC resources in a single configuration document. These +examples use the `Microsoft.WinGet.DSC/WinGetPackage` resource from the **Microsoft.WinGet.DSC** +module to ensure several packages are installed. + +## Definition + +The following configuration document defines multiple `Microsoft.WinGet.DSC/WinGetPackage` +instances. + +Save the following YAML as `dev-tools.dsc.yaml`: + +```yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +parameters: + ensureTools: + type: string + defaultValue: Present + allowedValues: + - Present + - Absent +resources: +- name: Windows Terminal + type: Microsoft.WinGet.DSC/WinGetPackage + properties: + Id: Microsoft.WindowsTerminal + Ensure: "[parameters('ensureTools')]" +- name: Visual Studio Code + type: Microsoft.WinGet.DSC/WinGetPackage + properties: + Id: Microsoft.VisualStudioCode + Ensure: "[parameters('ensureTools')]" +``` + +## Setup + +This example installs the WinGet software packages for the Windows Terminal and Visual Studio Code. +The output in this example shows the behavior when these packages aren't already installed on the +system. + +This example depends on the **Microsoft.WinGet.DSC** PowerShell module at version `1.12.440`. To +install the module, open a PowerShell session and invoke the following command: + +```powershell +Install-PSResource -Name Microsoft.WinGet.DSC -Version 1.12.440 +``` + +> [!WARNING] +> Uninstalling and reinstalling software may have unintentional side effects related to how that +> software behaves, especially if uninstalling the software removes all previously defined +> configuration for it. + +To ensure that the packages aren't installed, invoke the following commands: + +```powershell +winget uninstall --id Microsoft.WindowsTerminal +winget uninstall --id Microsoft.VisualStudioCode +``` + +## Test the configuration + +To see whether the system is in the desired state, use the [`dsc config test`][01] command on the +configuration document. + +```powershell +dsc config test --file dev-tools.dsc.yaml +``` + +DSC reports the results for each instance, showing which packages need to be installed. For this +example, neither package shows as installed: + +```yaml +executionInformation: + # Elided for brevity +metadata: + # Elided for brevity +results: +- executionInformation: + duration: PT8.0298239S + metadata: + Microsoft.DSC: + duration: PT8.0298239S + name: Windows Terminal + type: Microsoft.WinGet.DSC/WinGetPackage + result: + desiredState: + Id: Microsoft.WindowsTerminal + Ensure: Present + actualState: + Version: null + MatchOption: EqualsCaseInsensitive + UseLatest: false + InstallMode: Silent + Id: Microsoft.WindowsTerminal + Ensure: Absent + Source: '' + _inDesiredState: false + inDesiredState: false + differingProperties: + - Ensure +- executionInformation: + duration: PT7.6445836S + metadata: + Microsoft.DSC: + duration: PT7.6445836S + name: Visual Studio Code + type: Microsoft.WinGet.DSC/WinGetPackage + result: + desiredState: + Id: Microsoft.VisualStudioCode + Ensure: Present + actualState: + UseLatest: false + Version: null + Source: '' + Ensure: Absent + Id: Microsoft.VisualStudioCode + MatchOption: EqualsCaseInsensitive + InstallMode: Silent + _inDesiredState: false + inDesiredState: false + differingProperties: + - Ensure +messages: [] +hadErrors: false +``` + +## Apply the configuration + +Use the [`dsc config set`][02] command to install any packages that aren't already present: + +```powershell +dsc config set --file dev-tools.dsc.yaml +``` + +```yaml +executionInformation: + # Elided for brevity +metadata: + # Elided for brevity +results: +- executionInformation: + duration: PT34.4280028S + metadata: + Microsoft.DSC: + duration: PT34.4280028S + name: Windows Terminal + type: Microsoft.WinGet.DSC/WinGetPackage + result: + beforeState: + InstallMode: Silent + UseLatest: false + Source: '' + Id: Microsoft.WindowsTerminal + Ensure: Absent + Version: null + MatchOption: EqualsCaseInsensitive + afterState: + Version: 1.24.10921.0 + UseLatest: true + Source: winget + InstallMode: Silent + Ensure: Present + MatchOption: EqualsCaseInsensitive + Id: Microsoft.WindowsTerminal + changedProperties: + - Version + - UseLatest + - Source + - Ensure +- executionInformation: + duration: PT11.6464059S + metadata: + Microsoft.DSC: + duration: PT11.6464059S + name: Visual Studio Code + type: Microsoft.WinGet.DSC/WinGetPackage + result: + beforeState: + UseLatest: false + Ensure: Absent + Id: Microsoft.VisualStudioCode + MatchOption: EqualsCaseInsensitive + InstallMode: Silent + Source: '' + Version: null + afterState: + Id: Microsoft.VisualStudioCode + MatchOption: EqualsCaseInsensitive + Source: winget + Version: 1.119.0 + InstallMode: Silent + Ensure: Present + UseLatest: true + changedProperties: + - Source + - Version + - Ensure + - UseLatest +messages: [] +hadErrors: false +``` + +DSC installed both of the missing packages and reports that the state of each instance was changed +during the `set` operation. + +## Remove the packages + +To uninstall the packages, override the `ensureTools` parameter when applying the configuration: + +```powershell +$params = @{ + parameters = @{ + ensureTools = 'Absent' + } +} | ConvertTo-Json -Compress + +dsc config --parameters $params set --file dev-tools.dsc.yaml +``` + + +[01]: ../../../../../cli/config/test.md +[02]: ../../../../../cli/config/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/PowerShell/examples/invoke-a-resource.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/PowerShell/examples/invoke-a-resource.md new file mode 100644 index 0000000..18452dd --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/PowerShell/examples/invoke-a-resource.md @@ -0,0 +1,173 @@ +--- +description: > + Example showing how to invoke a class-based PowerShell DSC resource using the + Microsoft.Adapter/PowerShell adapter. +ms.date: 03/23/2026 +ms.topic: reference +title: Invoke a resource with the PowerShell adapter +--- + +# Invoke a resource with the PowerShell adapter + +This example shows how to use the `Microsoft.Adapter/PowerShell` adapter to invoke a class-based +PowerShell DSC (PSDSC) resource. These examples use the `Microsoft.WinGet.DSC/WinGetPackage` +resource from the **Microsoft.WinGet.DSC** module to check whether Windows Terminal is installed. + +## Setup + +This example installs the WinGet software package for the Windows terminal. The output in this +example shows the behavior when this package isn't already installed on the system. + +This example depends on the **Microsoft.WinGet.DSC** PowerShell module at version `1.12.440`. To +install the module, open a PowerShell session and invoke the following command: + +```powershell +Install-PSResource -Name Microsoft.WinGet.DSC -Version 1.12.440 +``` + +> [!WARNING] +> Uninstalling and reinstalling software may have unintentional side effects related to how that +> software behaves, especially if uninstalling the software removes all previously defined +> configuration for it. + +To ensure that the packages aren't installed, invoke the following command: + +```powershell +winget uninstall --id Microsoft.WindowsTerminal +``` + +## Discover available adapted PSDSC resources + +To show available adapted PSDSC resources, use the [`dsc resource list`][01] command with the +[`--adapter`][02] option as `Microsoft.Adapter/PowerShell`: + +```powershell +dsc resource list --adapter Microsoft.Adapter/PowerShell +``` + +```console +Type Kind Version Capabilities RequireAdapter Description +-------------------------------------------------------------------------------------------------------------------------------------------- +Microsoft.PowerToys.Configure/PowerToysConfigure Resource 0.85.1 gs--t---- Microsoft.Adapter/PowerShell The module enabl… +Microsoft.Windows.Developer/AdvancedNetworkSharingSetting Resource 0.4.0 gs--t---- Microsoft.Adapter/PowerShell DSC Resource for +Microsoft.Windows.Developer/DeveloperMode Resource 0.4.0 gs--t---- Microsoft.Adapter/PowerShell DSC Resource for +Microsoft.Windows.Developer/EnableDarkMode Resource 0.4.0 gs--t---- Microsoft.Adapter/PowerShell DSC Resource for +Microsoft.Windows.Developer/EnableLongPathSupport Resource 0.4.0 gs--t---- Microsoft.Adapter/PowerShell DSC Resource for +Microsoft.Windows.Developer/EnableRemoteDesktop Resource 0.4.0 gs--t---- Microsoft.Adapter/PowerShell DSC Resource for +Microsoft.Windows.Developer/FirewallRule Resource 0.4.0 gs--t---- Microsoft.Adapter/PowerShell DSC Resource for +Microsoft.Windows.Developer/NetConnectionProfile Resource 0.4.0 gs--t---- Microsoft.Adapter/PowerShell DSC Resource for +Microsoft.Windows.Developer/OsVersion Resource 0.4.0 gs--t---- Microsoft.Adapter/PowerShell DSC Resource for +Microsoft.Windows.Developer/PowerPlanSetting Resource 0.4.0 gs--t---- Microsoft.Adapter/PowerShell DSC Resource for +Microsoft.Windows.Developer/ShowSecondsInClock Resource 0.4.0 gs--t---- Microsoft.Adapter/PowerShell DSC Resource for +Microsoft.Windows.Developer/Taskbar Resource 0.4.0 gs--t---- Microsoft.Adapter/PowerShell DSC Resource for +Microsoft.Windows.Developer/UserAccessControl Resource 0.4.0 gs--t---- Microsoft.Adapter/PowerShell DSC Resource for +Microsoft.Windows.Developer/WindowsCapability Resource 0.4.0 gs--t---- Microsoft.Adapter/PowerShell DSC Resource for +Microsoft.Windows.Developer/WindowsExplorer Resource 0.4.0 gs--t---- Microsoft.Adapter/PowerShell DSC Resource for +Microsoft.WinGet.DSC/WinGetAdminSettings Resource 1.12.440 gs--t---- Microsoft.Adapter/PowerShell PowerShell Modul… +Microsoft.WinGet.DSC/WinGetPackage Resource 1.12.440 gs--t---- Microsoft.Adapter/PowerShell PowerShell Modul… +Microsoft.WinGet.DSC/WinGetPackageManager Resource 1.12.440 gs--t---- Microsoft.Adapter/PowerShell PowerShell Modul… +Microsoft.WinGet.DSC/WinGetSource Resource 1.12.440 gs--t---- Microsoft.Adapter/PowerShell PowerShell Modul… +Microsoft.WinGet.DSC/WinGetUserSettings Resource 1.12.440 gs--t---- Microsoft.Adapter/PowerShell PowerShell Modul… +``` + +## Test whether an instance is in the desired state + +You can use the [`dsc resource test`][03] command to invoke the `test` operation for a resource +without authoring a configuration document. + +The following snippet invokes the `Microsoft.WinGet.DSC/WinGetPackage` PSDSC resource to check +whether the Windows Terminal package is installed: + +```powershell +$resource = 'Microsoft.WinGet.DSC/WinGetPackage' +$instance = @{ + Id = 'Microsoft.WindowsTerminal' + Ensure = 'Present' +} | ConvertTo-Json -Compress + +dsc resource test --resource $resource --input $instance +``` + +When the package isn't installed, DSC returns the following result: + +```yaml +desiredState: + Id: Microsoft.WindowsTerminal + Ensure: Present +actualState: + Id: Microsoft.WindowsTerminal + InstallMode: Silent + Version: null + Ensure: Absent + MatchOption: EqualsCaseInsensitive + Source: '' + UseLatest: false + _inDesiredState: false +inDesiredState: false +differingProperties: +- Ensure +``` + +The `inDesiredState` field is `false` and `differingProperties` shows that `Ensure` differs between +the desired state and the actual state. + +## Set an instance to the desired state + +Use the [`dsc config set`][04] command to enforce the desired state for the resource instance: + +```powershell +$resource = 'Microsoft.WinGet.DSC/WinGetPackage' +$instance = @{ + Id = 'Microsoft.WindowsTerminal' + Ensure = 'Present' +} | ConvertTo-Json -Compress + +dsc resource set --resource $resource --input $instance +``` + +When the resource installs the package, DSC returns the following result: + +```yaml +beforeState: + Ensure: Absent + UseLatest: false + InstallMode: Silent + Version: null + Id: Microsoft.WindowsTerminal + MatchOption: EqualsCaseInsensitive + Source: '' +afterState: + Version: 1.24.10921.0 + MatchOption: EqualsCaseInsensitive + Ensure: Present + Id: Microsoft.WindowsTerminal + UseLatest: true + InstallMode: Silent + Source: winget +changedProperties: +- Version +- Ensure +- UseLatest +- Source +``` + +## Cleanup + +To remove the installed package, define the desired state for the `Ensure` property as `Absent` and +invoke the `dsc resource set` command again: + +```powershell +$resource = 'Microsoft.WinGet.DSC/WinGetPackage' +$instance = @{ + Id = 'Microsoft.WindowsTerminal' + Ensure = 'Absent' +} | ConvertTo-Json -Compress + +dsc resource set --resource $resource --input $instance +``` + + +[01]: ../../../../../cli/resource/list.md +[02]: ../../../../../cli/resource/list.md#--adapter +[03]: ../../../../../cli/resource/test.md +[04]: ../../../../../cli/resource/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/PowerShell/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/PowerShell/index.md new file mode 100644 index 0000000..49790b6 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/PowerShell/index.md @@ -0,0 +1,201 @@ +--- +description: Microsoft.Adapter/PowerShell resource adapter reference documentation +ms.date: 03/23/2026 +ms.topic: reference +title: Microsoft.Adapter/PowerShell +--- + +# Microsoft.Adapter/PowerShell + +## Synopsis + +Adapter for resources implemented as PowerShell DSC classes. + +## Metadata + +```yaml +Version: 0.1.0 +Kind: adapter +Tags: [linux, windows, macos, pwsh, powershell] +Executable: pwsh +MinimumDSCVersion: 3.2.0 +``` + +## Adapted resource instance definition syntax + +### Implicitly required adapter syntax + +```yaml +- name: + type: / + properties: # adapted resource properties + : +``` + +### Explicitly required adapter syntax + +```yaml +- name: + type: / + properties: # adapted resource properties + : + directives: + requireAdapter: Microsoft.Adapter/PowerShell +``` + +## Description + +The `Microsoft.Adapter/PowerShell` adapter resource enables you to use PowerShell Desired State +Configuration (PSDSC) resources in DSC. The adapter discovers and invokes PSDSC resources +implemented as PowerShell classes compatible with PowerShell. + +The adapter manages the PSDSC resources in PowerShell (`pwsh`), not Windows PowerShell +(`powershell.exe`). To use MOF-based PSDSC resources or PSDSC resources that require Windows +PowerShell, use the [Microsoft.Adapter/WindowsPowerShell][01] adapter. + +This adapter doesn't use the **PSDesiredStateConfiguration** module. You don't need to install the +**PSDesiredStateConfiguration** module to use PSDSC resources in DSC through this adapter. + +> [!NOTE] +> This adapter replaces the deprecated [Microsoft.DSC/PowerShell][02] adapter. +> +> In earlier versions of DSC, adapted resources were nested inside a parent adapter resource using +> the `properties.resources` array. Starting in DSC 3.2, each adapted resource is listed directly +> in the configuration document's `resources` array. +> +> You can use the [`requireAdapter` directive][03] to explicitly indicate that the instance should +> use this adapter. When you don't specify the `requireAdapter` directive, DSC invokes the adapted +> resource through the first adapter that indicates it can invoke the resource. + +### PowerShell resource adapter cache + +The process for discovering the PowerShell resources available to the adapter can be +time-consuming. To improve performance, the adapter caches PowerShell resources and modules during +discovery. If the cache doesn't exist during discovery, the adapter creates it. + +The location of the cache depends on your operating system. The following table defines the path +for each platform. + +| Platform | Path | +| :------: | :----------------------------------------| +| Linux | `$HOME/.dsc/PSAdapterCache.json` | +| macOS | `$HOME/.dsc/PSAdapterCache.json` | +| Windows | `%LOCALAPPDATA%\dsc\PSAdapterCache.json` | + +The adapter versions the cache. The current version is `2`. If the version of the cache on a +machine differs from the current version, the adapter refreshes the cache. + +The adapter checks whether the cache is stale on each run and refreshes it if: + +- The `PSModulePath` environmental variable is updated. +- Any module is added or removed from the `PSModulePath`. +- Any related file in a cached PSDSC resource module has been updated since the cache was written. + The adapter watches the `LastWriteTime` property of module files with the following extensions: + `.ps1`, `.psd1`, and `.psm1`. + +You can directly call the adapter script to clear the cache with the **Operation** parameter value +set to `ClearCache`: + +```powershell +$adapterScript = dsc resource list Microsoft.Adapter/PowerShell | + ConvertFrom-Json | + Select-Object -ExpandProperty directory | + Join-Path -ChildPath 'psDscAdapter\powershell.resource.ps1' + +& $adapterScript -Operation ClearCache +``` + +## Requirements + +- This adapter is available on Linux, macOS, and Windows systems. +- Using this adapter requires a supported version of PowerShell. + + DSC invokes the adapter as a + PowerShell script. For more information about installing PowerShell, see + [Install PowerShell on Windows, Linux, and macOS][04]. +- This adapter only supports PSDSC resources implemented as PowerShell classes. + + To use PSDSC resources in DSC that aren't defined as PowerShell classes, + use the [`Microsoft.Adapter/WindowsPowerShell`][01] adapter. + +## Capabilities + +The resource adapter has the following capabilities: + +- `get` - Retrieve the actual state of an adapted DSC resource instance. +- `set` - Enforce the desired state for an adapted DSC resource instance. +- `test` - Determine whether an adapted DSC resource instance is in the desired state. +- `export` - Discover and enumerate adapted DSC resource instances available on the system. +- `list` - List available Windows PowerShell DSC resources that can be used as adapted DSC + resources. + +## Examples + +- [Invoke a resource with the PowerShell adapter][05] +- [Configure a machine with the PowerShell adapter][06] + +## Adapted resource instances + +Define adapted resource instances directly in the configuration document's `resources` array. + +To explicitly indicate that DSC should use this adapter for the resource instance, define the +`requireAdapter` directive as `Microsoft.Adapter/PowerShell`. When you don't specify the +`requireAdapter` directive, DSC invokes the adapted resource through the first adapter that +indicates it can invoke the resource. + +Adapted resource instances are defined identically to non-adapted resource instances in a +configuration document with the following exceptions: + +1. The fully qualified type name (`type` field) for the adapted instance is defined by the adapter. + This adapter uses the following syntax for determining the fully qualified type name of a PSDSC + resource: + + ```Syntax + / + ``` + + For example, if a PowerShell module named **TailspinToys** has a class-based PSDSC resource named + `TSToy`, the fully qualified type name for that resource is `TailspinToys/TSToy`. + + For more information about type names in DSC, see + [DSC Resource fully qualified type name schema reference][07]. + +1. The `properties` field for the instance is validated at runtime when the adapter tries to invoke + the adapted PSDSC resource instance. This adapter doesn't support static linting for adapted + instance properties in a configuration document. + + Each property name must be a configurable property of the PSDSC resource. The property name + isn't case sensitive. The value for each property must be valid for that property. If you + specify an invalid property name or value, the adapter raises an error when it tries to invoke + the resource. + +## Exit codes + +The resource uses the following exit codes to report success and errors: + +- `0` - Success +- `1` - Error + +### Exit code 0 + +Indicates the resource operation completed without errors. + +### Exit code 1 + +Indicates the resource operation failed because the underlying DSC resource method didn't succeed. +When the adapter returns this exit code, it also emits an error message with details about the +failure. + +## See also + +- [Microsoft.Adapter/WindowsPowerShell][01] +- [Microsoft.DSC/PowerShell][02] (deprecated) + + +[01]: ../WindowsPowerShell/index.md +[02]: ../../DSC/PowerShell/index.md +[03]: ../../../../schemas/config/resource.md#requireadapter +[04]: /powershell/scripting/install/installing-powershell +[05]: examples/invoke-a-resource.md +[06]: examples/configure-a-machine.md +[07]: ../../../../schemas/definitions/resourceType.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/WindowsPowerShell/examples/manage-a-windows-service.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/WindowsPowerShell/examples/manage-a-windows-service.md new file mode 100644 index 0000000..fd226f5 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/WindowsPowerShell/examples/manage-a-windows-service.md @@ -0,0 +1,310 @@ +--- +description: > + Example showing how to manage a Windows service using the PSDesiredStateConfiguration module + with the Microsoft.Adapter/WindowsPowerShell adapter in a DSC configuration document. + +ms.date: 08/13/2026 +ms.topic: reference +title: Manage a Windows service with the Windows PowerShell adapter +--- + +# Manage a Windows service with the Windows PowerShell adapter + +This example shows how to use the `Microsoft.Adapter/WindowsPowerShell` adapter with the +`PSDesiredStateConfiguration/Service` adapted PSDSC resource to manage a Windows service. These +examples manage the `Spooler` print spooler service. + +> [!NOTE] +> Run this example in an elevated PowerShell session with `dsc.exe` version `3.2.0` or later. + +## Definition + +The following configuration document defines a single `PSDesiredStateConfiguration/Service` +instance. It expects the `Spooler` service to be set to startup automatically. + +```yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +directives: + securityContext: elevated +resources: +- name: Spooler service + type: PSDesiredStateConfiguration/Service + directives: + requireAdapter: Microsoft.Adapter/WindowsPowerShell + properties: + Name: Spooler + StartupType: Automatic +``` + +Copy the configuration document and save it as `spooler.dsc.yaml`. + +## Setup + +This example modifies the `Spooler` service. The example assumes that the service is currently +running and set to require manual startup. + +To put your system into the starting state for this example, run the following PowerShell command: + +```powershell +Get-Service Spooler | ForEach-Object -Process { + if ($_.StartType -ne 'Manual') { + $_ | Set-Service -StartupType Manual + } + if ($_.Status -ne 'Running') { + $_ | Start-Service + } +} + +Get-Service Spooler | Format-Table -Property Name, Status, StartType +``` + +You should get output from the final `Get-Service` command that shows the service is in the +expected state for the example: + +```console +Name Status StartType +---- ------ --------- +Spooler Running Manual +``` + +## Test whether a service is running + +To see whether the system is in the desired state, use the [`dsc config test`][01] command on the +configuration document. + +```powershell +dsc config test --file spooler.dsc.yaml +``` + +When the service has a different startup type, DSC returns the following result: + +```yaml +executionInformation: + duration: PT424.3956473S + endDatetime: 2026-05-07T10:30:10.621622500-05:00 + executionType: actual + operation: test + securityContext: elevated + startDatetime: 2026-05-07T10:23:06.225975200-05:00 + version: 3.3.0-preview.1 +metadata: + Microsoft.DSC: + duration: PT424.395627S + endDatetime: 2026-05-07T10:30:10.621602200-05:00 + executionType: actual + operation: test + securityContext: elevated + startDatetime: 2026-05-07T10:23:06.225975200-05:00 + version: 3.3.0-preview.1 +results: +- executionInformation: + duration: PT95.7531029S + metadata: + Microsoft.DSC: + duration: PT95.7531029S + name: Spooler service + type: PSDesiredStateConfiguration/Service + result: + desiredState: + Name: Spooler + StartupType: Automatic + actualState: + Status: null + Description: This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers. + DisplayName: Print Spooler + ResourceId: null + PsDscRunAsCredential: null + Name: Spooler + Credential: null + PSComputerName: localhost + ConfigurationName: null + Ensure: null + DependsOn: null + SourceInfo: null + BuiltInAccount: LocalSystem + StartupType: Manual + State: Running + ModuleVersion: '1.1' + ModuleName: PSDesiredStateConfiguration + Path: C:\WINDOWS\System32\spoolsv.exe + Dependencies: + - RPCSS + - http + _inDesiredState: false + inDesiredState: false + differingProperties: + - StartupType +messages: [] +hadErrors: false +``` + +The `inDesiredState` field is `false` and `differingProperties` shows that `StartupType` differs. + +## Ensure a service is running with automatic startup + +Use the [`dsc config set`][02] command to configure the service: + +```powershell +dsc config set --file spooler.dsc.yaml +``` + +When the resource configures the service, DSC returns the following result: + +```yaml +executionInformation: + duration: PT282.1686621S + endDatetime: 2026-05-07T13:38:50.583007700-05:00 + executionType: actual + operation: set + securityContext: elevated + startDatetime: 2026-05-07T13:34:08.414345600-05:00 + version: 3.3.0-preview.1 +metadata: + Microsoft.DSC: + duration: PT282.1686429S + endDatetime: 2026-05-07T13:38:50.582988500-05:00 + executionType: actual + operation: set + securityContext: elevated + startDatetime: 2026-05-07T13:34:08.414345600-05:00 + version: 3.3.0-preview.1 +results: +- executionInformation: + duration: PT180.7721614S + metadata: + Microsoft.DSC: + duration: PT180.7721614S + name: Spooler service + type: PSDesiredStateConfiguration/Service + result: + beforeState: + Status: null + Description: This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers. + DisplayName: Print Spooler + ResourceId: null + PsDscRunAsCredential: null + Name: Spooler + Credential: null + PSComputerName: localhost + ConfigurationName: null + Ensure: null + DependsOn: null + SourceInfo: null + BuiltInAccount: LocalSystem + StartupType: Manual + State: Running + ModuleVersion: '1.1' + ModuleName: PSDesiredStateConfiguration + Path: C:\WINDOWS\System32\spoolsv.exe + Dependencies: + - RPCSS + - http + afterState: + Status: null + Description: This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers. + DisplayName: Print Spooler + ResourceId: null + PsDscRunAsCredential: null + Name: Spooler + Credential: null + PSComputerName: localhost + ConfigurationName: null + Ensure: null + DependsOn: null + SourceInfo: null + BuiltInAccount: LocalSystem + StartupType: Automatic + State: Running + ModuleVersion: '1.1' + ModuleName: PSDesiredStateConfiguration + Path: C:\WINDOWS\System32\spoolsv.exe + Dependencies: + - RPCSS + - http + changedProperties: + - StartupType +messages: [] +hadErrors: false +``` + +Run the test again to confirm the service is now configured correctly: + +```powershell +dsc config test --file spooler.dsc.yaml +``` + +```yaml +executionInformation: + duration: PT188.0880439S + endDatetime: 2026-05-07T13:49:04.563267-05:00 + executionType: actual + operation: test + securityContext: elevated + startDatetime: 2026-05-07T13:45:56.475223100-05:00 + version: 3.3.0-preview.1 +metadata: + Microsoft.DSC: + duration: PT188.0880252S + endDatetime: 2026-05-07T13:49:04.563248300-05:00 + executionType: actual + operation: test + securityContext: elevated + startDatetime: 2026-05-07T13:45:56.475223100-05:00 + version: 3.3.0-preview.1 +results: +- executionInformation: + duration: PT94.8140892S + metadata: + Microsoft.DSC: + duration: PT94.8140892S + name: Spooler service + type: PSDesiredStateConfiguration/Service + result: + desiredState: + Name: Spooler + StartupType: Automatic + actualState: + Status: null + Description: This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers. + DisplayName: Print Spooler + ResourceId: null + PsDscRunAsCredential: null + Name: Spooler + Credential: null + PSComputerName: localhost + ConfigurationName: null + Ensure: null + DependsOn: null + SourceInfo: null + BuiltInAccount: LocalSystem + StartupType: Automatic + State: Running + ModuleVersion: '1.1' + ModuleName: PSDesiredStateConfiguration + Path: C:\WINDOWS\System32\spoolsv.exe + Dependencies: + - RPCSS + - http + _inDesiredState: true + inDesiredState: true + differingProperties: [] +messages: [] +hadErrors: false +``` + +## Cleanup + +To stop the service and set startup type to manual, use the [`dsc resource set`][03] command: + +```powershell +dsc resource set PSDesiredStateConfiguration/Service --input @' +Name: Spooler +State: Stopped +StartupType: Manual +'@ +``` + + +[01]: ../../../../../cli/config/test.md +[02]: ../../../../../cli/config/set.md +[03]: ../../../../../cli/resource/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/WindowsPowerShell/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/WindowsPowerShell/index.md new file mode 100644 index 0000000..115f2df --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Adapter/WindowsPowerShell/index.md @@ -0,0 +1,210 @@ +--- +description: Microsoft.Adapter/WindowsPowerShell resource adapter reference documentation +ms.date: 03/23/2026 +ms.topic: reference +title: Microsoft.Adapter/WindowsPowerShell +--- + +# Microsoft.Adapter/WindowsPowerShell + +## Synopsis + +Adapter for resources implemented as binary, script, or PowerShell classes in Windows PowerShell. + +## Metadata + +```yaml +Version: 0.1.0 +Kind: adapter +Tags: [windows, powershell] +Executable: powershell +MinimumDSCVersion: 3.2.0 +``` + +## Adapted resource instance definition syntax + +### Implicitly required adapter syntax + +```yaml +- name: + type: / + properties: # adapted resource properties + : +``` + +### Explicitly required adapter syntax + +```yaml +- name: + type: / + properties: # adapted resource properties + : + directives: + requireAdapter: Microsoft.Adapter/WindowsPowerShell +``` + +## Description + +The `Microsoft.Adapter/WindowsPowerShell` adapter resource enables you to use PowerShell Desired +State Configuration (PSDSC) resources in DSC. The adapter discovers and invokes PSDSC resources +compatible with Windows PowerShell and PSDSC version `1.1`. + +The adapter manages the PSDSC resources in Windows PowerShell (`powershell.exe`), not PowerShell +(`pwsh`). To use class-based PSDSC resources in PowerShell, use the +[Microsoft.Adapter/PowerShell][01] adapter. + +This adapter uses the **PSDesiredStateConfiguration** module v1.1. This module is built-in when +you install Windows and is located in +`%SystemRoot%\System32\WindowsPowerShell\v1.0\Modules`. + +> [!NOTE] +> This adapter replaces the deprecated [Microsoft.Windows/WindowsPowerShell][02] adapter. +> +> In earlier versions of DSC, adapted resources were nested inside a parent adapter resource using +> the `properties.resources` array. Starting in DSC 3.2, each adapted resource is listed directly +> in the configuration document's `resources` array. +> +> You can use the [`requireAdapter` directive][03] to explicitly indicate that the instance should +> use this adapter. When you don't specify the `requireAdapter` directive, DSC invokes the adapted +> resource through the first adapter that indicates it can invoke the resource. + +### Windows PowerShell resource adapter cache + +The process for discovering the Windows PowerShell resources available to the adapter can be +time-consuming. To improve performance, the adapter caches Windows PowerShell resources and modules +during discovery. If the cache doesn't exist during discovery, the adapter creates it. + +The following table defines the cache path for the Windows platform. + +| Platform | Path | +| :------: | :---------------------------------------------- | +| Windows | `%LOCALAPPDATA%\dsc\WindowsPSAdapterCache.json` | + +The adapter versions the cache. The current version is `1`. If the version of the cache on a +machine differs from the current version, the adapter refreshes the cache. + +The adapter checks whether the cache is stale on each run and refreshes it if: + +- The `PSModulePath` environmental variable is updated. +- Any module is added or removed from the `PSModulePath`. +- Any related file in a cached PSDSC resource module has been updated since the cache was written. + The adapter watches the `LastWriteTime` property of module files with the following extensions: + `.ps1`, `.psd1`, and `.psm1`. + +You can directly call the adapter script to clear the cache with the **Operation** parameter value +set to `ClearCache`: + +```powershell +$adapterScript = dsc resource list Microsoft.Adapter/WindowsPowerShell | + ConvertFrom-Json | + Select-Object -ExpandProperty directory | + Join-Path -ChildPath 'psDscAdapter\powershell.resource.ps1' + +& $adapterScript -Operation ClearCache +``` + +## Requirements + +- This adapter is only available on Windows. +- The process security context must be elevated. + + For PSDSC 1.1, invoking DSC resources requires the process to run as Administrator. Attempting to + invoke the resources in a non-elevated context fails. +- Windows PowerShell Desired State Configuration (PSDSC) depends on WinRM. If WinRM isn't setup on + the machine, invoking PSDSC resources through the adapter will raise an error. + + You can use the [`Enable-PSRemoting` cmdlet][04] in an elevated Windows PowerShell session to + enable WinRM. +- PowerShell modules exposing PSDSC resources for use with this adapter must be installed in one of + the following locations: + + - `%PROGRAMFILES%\WindowsPowerShell\Modules` + - `%SystemRoot%\System32\WindowsPowerShell\v1.0\Modules` + + PSDSC 1.1 only finds PSDSC resources when the module containing them is installed in the machine + scope. Modules containing PSDSC resources in the user scope or another non-default location + aren't recognized by PSDSC 1.1 and can't be invoked through this adapter. + +## Capabilities + +The resource adapter has the following capabilities: + +- `get` - Retrieve the actual state of an adapted DSC resource instance. +- `set` - Enforce the desired state for an adapted DSC resource instance. +- `test` - Determine whether an adapted DSC resource instance is in the desired state. +- `export` - Discover and enumerate adapted DSC resource instances available on the system. +- `list` - List available Windows PowerShell DSC resources that can be used as adapted DSC + resources. + +> [!NOTE] +> The `export` capability is only available for class-based PSDSC resources. Script-based and +> binary PSDSC resources don't support the export operation. + +## Examples + +- [Manage a Windows service with the WindowsPowerShell adapter][05] + +## Adapted resource instances + +Define adapted resource instances directly in the configuration document's `resources` array. + +To explicitly indicate that DSC should use this adapter for the resource instance, define the +`requireAdapter` directive as `Microsoft.Adapter/WindowsPowerShell`. When you don't specify the +`requireAdapter` directive, DSC invokes the adapted resource through the first adapter that +indicates it can invoke the resource. + +Adapted resource instances are defined identically to non-adapted resource instances in a +configuration document with the following exceptions: + +1. The fully qualified type name (`type` field) for the adapted instance is defined by the adapter. + This adapter uses the following syntax for determining the fully qualified type name of a PSDSC + resource: + + ```Syntax + / + ``` + + For example, if a PowerShell module named **TailspinToys** has a script-based PSDSC resource + named `TSToy`, the fully qualified type name for that resource is `TailspinToys/TSToy`. + + For more information about type names in DSC, see + [DSC Resource fully qualified type name schema reference][06]. + +1. The `properties` field for the instance is validated at runtime when the adapter tries to invoke + the adapted PSDSC resource instance. This adapter doesn't support static linting for adapted + instance properties in a configuration document. + + Each property name must be a configurable property of the PSDSC resource. The property name + isn't case sensitive. The value for each property must be valid for that property. If you + specify an invalid property name or value, the adapter raises an error when it tries to invoke + the resource. + +## Exit codes + +The adapter resource returns the following exit codes from operations: + +- [0](#exit-code-0) - Success +- [1](#exit-code-1) - Error + +### Exit code 0 + +Indicates the resource operation completed without errors. + +### Exit code 1 + +Indicates the resource operation failed because the underlying DSC resource method or +`Invoke-DscResource` call didn't succeed. When the adapter returns this exit code, it also emits +an error message with details about the failure. + +## See also + +- [Microsoft.Adapter/PowerShell][01] +- [Microsoft.Windows/WindowsPowerShell][02] (deprecated) + + +[01]: ../PowerShell/index.md +[02]: ../../Windows/WindowsPowerShell/index.md +[03]: ../../../../schemas/config/resource.md#requireadapter +[04]: /powershell/module/microsoft.powershell.core/enable-psremoting?view=powershell-5.1&preserve-view=true +[05]: examples/manage-a-windows-service.md +[06]: ../../../../schemas/definitions/resourceType.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Debug/echo/examples/basic-echo-example.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Debug/echo/examples/basic-echo-example.md index 72a7ee7..bcf1329 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Debug/echo/examples/basic-echo-example.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Debug/echo/examples/basic-echo-example.md @@ -1,6 +1,6 @@ --- description: Demonstrates basic usage of the Microsoft.DSC.Debug/Echo resource -ms.date: 07/03/2025 +ms.date: 06/22/2025 ms.topic: reference title: Basic echo example --- @@ -33,11 +33,10 @@ differingProperties: [] ``` > [!NOTE] -> The `Microsoft.DSC.Debug/Echo` resource always returns `inDesiredState: true` because it's a test -> resource designed to echo back values. -> -> It doesn't actually check or enforce anything on the system - it simply returns whatever value -> you provide as output. +> The `Microsoft.DSC.Debug/Echo` resource always returns `inDesiredState: true` because it's a +> test resource designed to echo back values. +> It doesn't actually check or enforce anything on the system - it simply returns whatever value you +> provide as output. ## Using the get capability @@ -61,8 +60,8 @@ actualState: ## Using the set capability -The `Microsoft.DSC.Debug/Echo` resource's `set` capability simply accepts a value and echoes it -back without modifying anything: +The `Microsoft.DSC.Debug/Echo` resource's `set` capability simply accepts a value and echoes +it back without modifying anything: ```powershell $instance = @{ diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Debug/echo/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Debug/echo/index.md index a5b0170..f3af201 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Debug/echo/index.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Debug/echo/index.md @@ -1,6 +1,6 @@ --- description: Microsoft.DSC.Debug/Echo resource reference documentation -ms.date: 07/03/2025 +ms.date: 06/22/2025 ms.topic: reference title: Microsoft.DSC.Debug/Echo --- @@ -54,10 +54,11 @@ The resource has the following capabilities: - `get` - You can use the resource to retrieve the actual state of an instance. - `set` - You can use the resource to enforce the desired state for an instance. -- `test` - You can use the resource to check if the actual state matches the desired state for an - instance. +- `test` - You can use the resource to check if the actual state matches the desired state + for an instance. -For more information about resource capabilities, see [DSC resource capabilities][01]. +For more information about resource capabilities, see +[DSC resource capabilities][01]. > [!NOTE] > Invoking any operation on this resource doesn't affect the system. @@ -73,8 +74,8 @@ For more information about resource capabilities, see [DSC resource capabilities The following list describes the properties for the resource. - **Required properties:** The following property is always - required when defining an instance of the resource. An instance that doesn't define this property - is invalid. For more information, see the "Required resource properties" section in + required when defining an instance of the resource. An instance that doesn't define this + property is invalid. For more information, see the "Required resource properties" section in [DSC resource properties][02] - [output](#output) - The value to be echoed back by the resource. @@ -114,8 +115,8 @@ following types: ## Instance validating schema The following snippet contains the JSON Schema that validates an instance of the resource. The -validating schema only includes schema keywords that affect how the instance is validated. All non -validating keywords are omitted. +validating schema only includes schema keywords that affect how the instance is validated. All +non validating keywords are omitted. ```json { @@ -166,4 +167,4 @@ validating keywords are omitted. [01]: ../../../../../../concepts/resources/capabilities.md [02]: ../../../../../../concepts/resources/properties.md#required-resource-properties [03]: ../../../../../../concepts/resources/properties.md#key-resource-properties -[04]: ../../../osinfo/index.md +[04]: ../../../../Microsoft/OSInfo/index.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Include/examples/include-a-configuration-file.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Include/examples/include-a-configuration-file.md new file mode 100644 index 0000000..6bbe2f8 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Include/examples/include-a-configuration-file.md @@ -0,0 +1,111 @@ +--- +description: >- + Demonstrates how to include a configuration document from a file with the Microsoft.DSC/Include + resource and pass it a parameters file. +ms.date: 07/24/2026 +ms.topic: reference +title: Include a configuration file +--- + +# Include a configuration file + +This example demonstrates how to use the `Microsoft.DSC/Include` resource to compose a configuration +from a separate configuration document on disk, and how to supply that document with a parameters +file. + +## Author the nested configuration document + +First, author the configuration document that you want to include. This document defines a parameter +named `osFamily` and uses it to check the operating system with the `Microsoft/OSInfo` resource. +Save it as `osinfo.dsc.yaml`. + +```yaml +# osinfo.dsc.yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +parameters: + osFamily: + type: string + defaultValue: Windows + allowedValues: + - Windows + - Linux + - macOS +resources: + - name: os + type: Microsoft/OSInfo + properties: + family: "[parameters('osFamily')]" +``` + +## Author the parameters file + +Next, author the parameters file that supplies a value for the `osFamily` parameter. Save it next to +the configuration document as `osinfo.parameters.yaml`. + +```yaml +# osinfo.parameters.yaml +parameters: + osFamily: macOS +``` + +## Include the configuration and parameters + +Finally, author the parent configuration document. The `Microsoft.DSC/Include` instance references +the configuration document with the `configurationFile` property and the parameters file with the +`parametersFile` property. Because the paths are relative, DSC resolves them against the parent +document's directory. + +```yaml +# main.dsc.yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: + - name: os info + type: Microsoft.DSC/Include + properties: + configurationFile: osinfo.dsc.yaml + parametersFile: osinfo.parameters.yaml +``` + +Invoke the [dsc config get][01] command against the parent document to retrieve the state of the +included resources. + +```powershell +dsc config get --file ./main.dsc.yaml +``` + +DSC resolves the included configuration, applies the `osFamily` value from the parameters file, and +returns the result of the nested `Microsoft/OSInfo` instance. On a macOS machine, the output is +similar to the following YAML: + +```yaml +results: +- name: os info + type: Microsoft.DSC/Include + result: + - name: os + type: Microsoft/OSInfo + result: + actualState: + $id: https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json + family: macOS + version: 15.5.0 + bitness: 64 + architecture: arm64 +messages: [] +hadErrors: false +``` + +> [!TIP] +> To run the included configuration with its default parameter values instead, omit the +> `parametersFile` property. The nested document then uses the `defaultValue` defined for each of +> its parameters. + +## See also + +- [Microsoft.DSC/Include resource](../index.md) +- [Include inline configuration content](./include-inline-configuration-content.md) +- [Microsoft/OSInfo resource][02] + + +[01]: ../../../../../cli/config/get.md +[02]: ../../../../Microsoft/OSInfo/index.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Include/examples/include-inline-configuration-content.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Include/examples/include-inline-configuration-content.md new file mode 100644 index 0000000..9a6fd26 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Include/examples/include-inline-configuration-content.md @@ -0,0 +1,94 @@ +--- +description: >- + Demonstrates how to embed a configuration document and its parameters inline with the + Microsoft.DSC/Include resource. +ms.date: 07/24/2026 +ms.topic: reference +title: Include inline configuration content +--- + +# Include inline configuration content + +This example demonstrates how to use the `Microsoft.DSC/Include` resource to embed a configuration +document and its parameters directly in the parent document. Use inline content when you want to +keep a self-contained configuration in a single file rather than referencing separate files on +disk. + +## Embed the configuration and parameters + +Author the parent configuration document. Instead of referencing files, the `Microsoft.DSC/Include` +instance defines the nested configuration with the `configurationContent` property and the parameter +values with the `parametersContent` property. Both properties accept YAML or JSON as text. The +following example uses YAML block scalars (`|`) to keep the nested documents readable. + +```yaml +# main.dsc.yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: + - name: os info + type: Microsoft.DSC/Include + properties: + configurationContent: | + $schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json + parameters: + osFamily: + type: string + defaultValue: Windows + allowedValues: + - Windows + - Linux + - macOS + resources: + - name: os + type: Microsoft/OSInfo + properties: + family: "[parameters('osFamily')]" + parametersContent: | + parameters: + osFamily: macOS +``` + +Invoke the [dsc config get][01] command against the parent document to retrieve the state of the +included resources. + +```powershell +dsc config get --file ./main.dsc.yaml +``` + +DSC parses the inline configuration, applies the `osFamily` value from the inline parameters, and +returns the result of the nested `Microsoft/OSInfo` instance. On a macOS machine, the output is +similar to the following YAML: + +```yaml +results: +- name: os info + type: Microsoft.DSC/Include + result: + - name: os + type: Microsoft/OSInfo + result: + actualState: + $id: https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json + family: macOS + version: 15.5.0 + bitness: 64 + architecture: arm64 +messages: [] +hadErrors: false +``` + +> [!TIP] +> Inline content is convenient for small configurations and for generating configurations +> programmatically. For larger or reusable configurations, reference a file with the +> `configurationFile` property instead. For that approach, see +> [Include a configuration file](./include-a-configuration-file.md). + +## See also + +- [Microsoft.DSC/Include resource](../index.md) +- [Include a configuration file](./include-a-configuration-file.md) +- [Microsoft/OSInfo resource][02] + + +[01]: ../../../../../cli/config/get.md +[02]: ../../../../Microsoft/OSInfo/index.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Include/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Include/index.md new file mode 100644 index 0000000..1091092 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Include/index.md @@ -0,0 +1,277 @@ +--- +description: Microsoft.DSC/Include resource reference documentation +ms.date: 07/24/2026 +ms.topic: reference +title: Microsoft.DSC/Include +--- + +# Microsoft.DSC/Include + +## Synopsis + +Includes a nested configuration document, with optional parameters, into the current configuration. + +## Metadata + +```yaml +Version : 0.1.0 +Kind : importer +Tags : [Windows, Linux, MacOS] +Author : Microsoft +``` + +## Instance definition syntax + +```yaml +resources: + - name: + type: Microsoft.DSC/Include + properties: + # Specify the nested configuration with one of the following properties: + configurationFile: string # Path to a configuration document file. + configurationContent: string # Inline configuration document as text. + # Optionally specify parameters with one of the following properties: + parametersFile: string # Path to a parameters file. + parametersContent: string # Inline parameters as text. +``` + +## Description + +The `Microsoft.DSC/Include` resource lets you compose a configuration from more than one +configuration document. Instead of defining every resource instance in a single document, you can +author smaller documents and reference them from a parent document. When DSC processes an instance +of the `Microsoft.DSC/Include` resource, it resolves the nested configuration document, applies any +parameters you specify, and runs the operation against the nested resources as a group. + +Use the `Microsoft.DSC/Include` resource when you want to: + +- Reuse a common configuration document across multiple parent configurations. +- Split a large configuration into smaller, focused documents that are easier to maintain. +- Apply the same configuration with different parameter values in different contexts. + +You define the nested configuration in one of two mutually exclusive ways: + +- Reference a document on disk with the [configurationFile](#configurationfile) property. +- Embed the document inline as text with the [configurationContent](#configurationcontent) property. + +Similarly, you can optionally pass parameters to the nested document in one of two mutually +exclusive ways: + +- Reference a parameters file on disk with the [parametersFile](#parametersfile) property. +- Embed the parameters inline as text with the [parametersContent](#parameterscontent) property. + +Both the configuration and the parameters can be authored as either YAML or JSON. DSC detects the +format when it parses the content. + +> [!NOTE] +> This resource is installed with DSC itself on any systems. +> +> You can update this resource by updating DSC. When you update DSC, the updated version of this +> resource is automatically available. + +### Path resolution and security + +When you specify a relative path for the [configurationFile](#configurationfile) or +[parametersFile](#parametersfile) properties, DSC resolves the path against the directory of the +parent configuration document. DSC uses the `DSC_CONFIG_ROOT` environment variable to determine +that directory. When you invoke DSC with configuration content instead of a file on disk, DSC +resolves relative paths against the current working directory. + +For security, relative paths **can't** reference a parent directory. A path that contains a `..` +segment raises an error. To include a configuration outside of the parent document's directory, use +an absolute path or construct the path with a configuration function like [path()][05] or +[systemRoot()][06]. + +### Nested and repeated includes + +An included configuration document can itself contain instances of the `Microsoft.DSC/Include` +resource. DSC resolves each level of nesting in turn, so you can build a hierarchy of configuration +documents. You can also define more than one `Microsoft.DSC/Include` instance in the same document +to compose several configurations together. + +## Capabilities + +The resource has the following capabilities: + +- `get` - You can use the resource to retrieve the actual state of the nested resource instances. +- `set` - You can use the resource to enforce the desired state for the nested resource instances. +- `test` - You can use the resource to check whether the nested resource instances are in the + desired state. + +Because this resource is an [importer resource][03], it doesn't manage state directly. Instead, it +resolves the nested configuration document and DSC invokes the requested operation against the +resources defined in that document. + +For more information about resource capabilities, see [DSC resource capabilities][01]. + +## Examples + +1. [Include a configuration file][07] - Shows how to reference a configuration document and pass it + a parameters file. +1. [Include inline configuration content][08] - Shows how to embed a configuration document and its + parameters directly in the parent document. + +## Properties + +The following list describes the properties for the resource. + +- **Configuration properties:** You must define exactly one of + the following properties to specify the nested configuration document. An instance that defines + neither property, or both, is invalid. + + - [configurationFile](#configurationfile) - The path to a configuration document file. + - [configurationContent](#configurationcontent) - An inline configuration document as text. + +- **Parameter properties:** You can optionally define one of the + following properties to pass parameters to the nested configuration document. An instance that + defines both properties is invalid. + + - [parametersFile](#parametersfile) - The path to a parameters file. + - [parametersContent](#parameterscontent) - Inline parameters as text. + +### configurationFile + +
Expand for configurationFile property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines the path to the configuration document file to include. The file can be authored as YAML or +JSON. When you specify a relative path, DSC resolves it against the parent configuration document's +directory and the path can't reference a parent directory. For more information, see +[Path resolution and security](#path-resolution-and-security). + +Define either this property or [configurationContent](#configurationcontent), but not both. + +### configurationContent + +
Expand for configurationContent property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines the configuration document to include as inline text. The content can be authored as YAML or +JSON. Use this property when you want to keep the nested configuration in the same document rather +than referencing a separate file. + +Define either this property or [configurationFile](#configurationfile), but not both. + +### parametersFile + +
Expand for parametersFile property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines the path to a parameters file that supplies values for the parameters defined in the nested +configuration document. The file can be authored as YAML or JSON. When you specify a relative path, +DSC resolves it against the parent configuration document's directory and the path can't reference a +parent directory. For more information, see +[Path resolution and security](#path-resolution-and-security). + +Define either this property or [parametersContent](#parameterscontent), but not both. This property +is optional. When you don't specify parameters, the nested configuration uses the default value for +each of its parameters. + +### parametersContent + +
Expand for parametersContent property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines the parameters for the nested configuration document as inline text. The content can be +authored as YAML or JSON. Use this property when you want to keep the parameter values in the same +document rather than referencing a separate file. + +Define either this property or [parametersFile](#parametersfile), but not both. This property is +optional. When you don't specify parameters, the nested configuration uses the default value for +each of its parameters. + +## Instance validating schema + +The following snippet contains the JSON Schema that validates an instance of the resource. The +validating schema only includes schema keywords that affect how the instance is validated. All +non validating keywords are omitted. + +```json +{ + "type": "object", + "properties": { + "configurationFile": { + "title": "Configuration file", + "description": "The path to the configuration document file to include.", + "type": "string" + }, + "configurationContent": { + "title": "Configuration content", + "description": "The configuration document to include as inline text.", + "type": "string" + }, + "parametersFile": { + "title": "Parameters file", + "description": "The path to a parameters file for the included configuration.", + "type": "string" + }, + "parametersContent": { + "title": "Parameters content", + "description": "The parameters for the included configuration as inline text.", + "type": "string" + } + }, + "oneOf": [ + { "required": ["configurationFile"] }, + { "required": ["configurationContent"] } + ], + "not": { + "required": ["parametersFile", "parametersContent"] + }, + "additionalProperties": false +} +``` + +## See also + +- `Microsoft.DSC/Group` resource +- `Microsoft.DSC/Assertion` resource +- [Microsoft/OSInfo resource][11] +- [DSC configuration documents][04] +- [DSC resource capabilities][01] + + +[01]: ../../../../../concepts/resources/capabilities.md +[03]: ../../../../../concepts/resources/kinds.md +[04]: ../../../../../concepts/configuration-documents/overview.md +[05]: ../../../../schemas/config/functions/overview.md +[06]: ../../../../schemas/config/functions/overview.md +[07]: ./examples/include-a-configuration-file.md +[08]: ./examples/include-inline-configuration-content.md +[11]: ../../OSInfo/index.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/PowerShell/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/PowerShell/index.md index 19f7b13..ea49098 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/PowerShell/index.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/PowerShell/index.md @@ -1,6 +1,6 @@ --- description: Microsoft.DSC/PowerShell resource reference documentation -ms.date: 07/03/2025 +ms.date: 03/18/2025 ms.topic: reference title: Microsoft.DSC/PowerShell --- @@ -32,11 +32,8 @@ resources: - name: type: / properties: # adapted resource properties -``` - -## Implicit adapted instance definition syntax -```yaml +# Or from v3.1.0-preview.2 onwards resources: - name: type: / @@ -51,7 +48,7 @@ implemented as PowerShell classes. The adapter manages the PSDSC resources in PowerShell, not Windows PowerShell. To use MOF-based PSDSC resources or PSDSC resources that require Windows PowerShell, use the -[Microsoft.Windows/WindowsPowerShell](../../windows/windowspowershell/index.md) adapter. +[Microsoft.Windows/WindowsPowerShell](../../Windows/WindowsPowerShell/index.md) adapter. This adapter doesn't use the **PSDesiredStateConfiguration** module. You don't need to install the **PSDesiredStateConfiguration** module to use PSDSC resources in DSC through this adapter. @@ -98,7 +95,7 @@ $adapterScript = dsc resource list Microsoft.DSC/PowerShell | - Using this adapter requires a supported version of PowerShell. DSC invokes the adapter as a PowerShell script. For more information about installing PowerShell, see - [Install PowerShell on Windows, Linux, and macOS](/powershell/scripting/install/installing-powershell). + [Install PowerShell on Windows, Linux, and macOS][03]. ## Required properties @@ -201,7 +198,9 @@ The resource uses the following exit codes to report success and errors: ## See also -- [Microsoft.Windows/WindowsPowerShell](../../windows/WindowsPowerShell/index.md) +- [Microsoft.Windows/WindowsPowerShell][02] -[01]: ../../../../../concepts/resources/overview.md#test-operations +[01]: ../../../../schemas/definitions/resourceType.md +[02]: ../../Windows/WindowsPowerShell/index.md +[03]: /powershell/scripting/install/installing-powershell diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/configure-with-script.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/configure-with-script.md new file mode 100644 index 0000000..b6a2579 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/configure-with-script.md @@ -0,0 +1,310 @@ +--- +description: > + Example showing how to use the PowerShellScript resource in a DSC configuration + document. +ms.date: 05/10/2026 +ms.topic: reference +title: Configure a system with the PowerShellScript resource +--- + + + +# Configure a system with the PowerShellScript resource + +This example shows how you can use the [`Microsoft.DSC.Transitional/PowerShellScript`][01] resource +in a configuration both to invoke non-idempotent scripts and to idempotently manage a message of +the day file that doesn't have a specific DSC resource. + +## Definition + +The configuration document for this example defines two instances of the resource: + +1. The first instance, `Report processor info`, returns the number of processor cores and the + processor architecture from both `getScript` and `setScript`. This instance is informational + only - it doesn't modify the system. +1. The second instance, `Message of the Day`, idempotently manages a message of the day file. It + uses `input` to define the contents of the file and pulls the value for the input from the + `parameters` definition. It defines all three script properties: `getScript` to return the + actual state, `testScript` to determine if the instance is in the desired state, and `setScript` + to enforce the desired state. + + The `getScript` and `setScript` definitions return the same structured output representing the + state of the MOTD file to make monitoring how the instance modifies the system easier. All three + script definitions use the `Write-Verbose` cmdlet to emit informational messages about what the + instance is doing. In particular the messages from `testScript` describe whether and how the + file isn't in the desired state to address the limited information the script can surface in its + output. + +:::code language="yaml" source="psscript.config.dsc.yaml"::: + +Copy the configuration document and save it as `psscript.config.dsc.yaml`. + +## Get the current state + +To retrieve the current state of the system, use the [dsc config get][02] command on the +configuration document. + +```powershell +dsc --trace-level info config get --file ./psscript.config.dsc.yaml +``` + +```Messages + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Invoking get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + INFO Invoking get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + INFO PID : Checking for MOTD file at 'Temp:/example.motd' + INFO PID : MOTD file not found at 'Temp:/example.motd' +``` + +```yaml +executionInformation: + # Elided for brevity +metadata: + Microsoft.DSC: + # Elided for brevity +results: +- executionInformation: + duration: PT1.2985379S + metadata: + Microsoft.DSC: + duration: PT1.2985379S + name: Report processor info + type: Microsoft.DSC.Transitional/PowerShellScript + result: + actualState: + output: + - processorCount: 8 + processorArchitecture: X64 +- executionInformation: + duration: PT0.9556133S + metadata: + Microsoft.DSC: + duration: PT0.9556133S + name: Message of the Day + type: Microsoft.DSC.Transitional/PowerShellScript + result: + actualState: + output: + - filePath: Temp:/example.motd + exists: false +messages: [] +hadErrors: false +``` + +The command emitted messages to stderr and the result to stdout. The messages include informational +messages from `getScript` for the message of the day instance indicating that the script looked for +but did not find the MOTD file. + +The result includes structured output from both instances: + +- The processor report instance shows that the system has `8` cores and is an `X64` architecture. +- The message of the day instance shows that the expected MOTD file doesn't exist at + `Temp:/example.motd`. + +## Enforce the desired state + +To update the system to the desired state, use the [dsc config set][03] command on the +configuration document. + +```powershell +dsc --trace-level info config set --file ./psscript.config.dsc.yaml +``` + +```Messages + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + INFO PID : Checking for MOTD file at 'Temp:/example.motd' + INFO PID : MOTD file not found at 'Temp:/example.motd' + INFO PID : MOTD file not found at 'Temp:/example.motd', creating new file + INFO PID : MOTD file created at 'Temp:/example.motd', setting content + INFO diff: key 'motd' missing + INFO diff: key 'lastUpdated' missing + INFO diff: actual array missing expected item + INFO diff: arrays differ for 'output +``` + +```yaml +executionInformation: + # Elided for brevity +metadata: + Microsoft.DSC: + # Elided for brevity +results: +- executionInformation: + duration: PT2.1871641S + metadata: + Microsoft.DSC: + duration: PT2.1871641S + name: Report processor info + type: Microsoft.DSC.Transitional/PowerShellScript + result: + beforeState: + output: + - processorCount: 8 + processorArchitecture: X64 + afterState: + output: + - processorCount: 8 + processorArchitecture: X64 + changedProperties: [] +- executionInformation: + duration: PT1.708226S + metadata: + Microsoft.DSC: + duration: PT1.708226S + name: Message of the Day + type: Microsoft.DSC.Transitional/PowerShellScript + result: + beforeState: + output: + - exists: false + filePath: Temp:/example.motd + afterState: + output: + - exists: true + motd: Hello, friend! + filePath: Temp:/example.motd + lastUpdated: 2026-06-02T18:05:16.8811712-05:00 + changedProperties: + - output +messages: [] +hadErrors: false +``` + +As before, the message of the day instance surfaces informational messages. The messages show that +the MOTD file wasn't found and then the `setScript` reports that it is creating the file and +setting the content. + +It's easier to review the result data for each instance separately: + +- ```yaml + name: Report processor info + type: Microsoft.DSC.Transitional/PowerShellScript + result: + beforeState: + output: + - processorCount: 8 + processorArchitecture: X64 + afterState: + output: + - processorCount: 8 + processorArchitecture: X64 + changedProperties: [] + ``` + + The processor info report shows the same state for the system before and after the **Set** + operation. If the instance didn't define `setScript` then `afterState` would be an empty object + (`{}`) and the `changedProperties` field would report that `output` was modified. Providing + identical output for the `setScript` ensures that the result doesn't imply any system changes. + +- ```yaml + name: Message of the Day + type: Microsoft.DSC.Transitional/PowerShellScript + result: + beforeState: + output: + - exists: false + filePath: Temp:/example.motd + afterState: + output: + - exists: true + motd: Hello, friend! + filePath: Temp:/example.motd + lastUpdated: 2026-06-02T18:05:16.8811712-05:00 + changedProperties: + - output + ``` + + The result for the message of the day instance shows that `exists` changed from `false` to `true`. + The `afterState` also includes the `motd` property showing the newly-set MOTD and reports the + last updated time for the file. + +If you invoke the **Set** operation for the configuration again you should see that neither instance +modifies the system: + +```powershell +dsc --trace-level info config set --file ./psscript.config.dsc.yaml +``` + +```Messages + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + INFO PID : Checking for MOTD file at 'Temp:/example.motd' + INFO PID : MOTD file found at 'Temp:/example.motd', retrieving content and last updated time + INFO PID : MOTD file found at 'Temp:/example.motd', checking content + INFO PID : MOTD content matches desired value, no update needed +``` + +```yaml +executionInformation: + # Elided for brevity +metadata: + Microsoft.DSC: + # Elided for brevity +results: +- executionInformation: + duration: PT3.8028321S + metadata: + Microsoft.DSC: + duration: PT3.8028321S + name: Report processor info + type: Microsoft.DSC.Transitional/PowerShellScript + result: + beforeState: + output: + - processorCount: 8 + processorArchitecture: X64 + afterState: + output: + - processorCount: 8 + processorArchitecture: X64 + changedProperties: [] +- executionInformation: + duration: PT2.6216447S + metadata: + Microsoft.DSC: + duration: PT2.6216447S + name: Message of the Day + type: Microsoft.DSC.Transitional/PowerShellScript + result: + beforeState: + output: + - filePath: Temp:/example.motd + motd: Hello, friend! + exists: true + lastUpdated: 2026-06-03T08:46:38.0491245-05:00 + afterState: + output: + - motd: Hello, friend! + exists: true + lastUpdated: 2026-06-03T08:46:38.0491245-05:00 + filePath: Temp:/example.motd + changedProperties: [] +messages: [] +hadErrors: false +``` + +## Cleanup + +To return your system to its original state, invoke the following PowerShell command to remove the +MOTD file from the `Temp:/` folder: + +```powershell +Remove-Item -Path 'Temp:/example.motd' -Verbose +``` + + +[01]: ../index.md +[02]: ../../../../../../cli/config/get.md +[03]: ../../../../../../cli/config/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/invoke-with-input-data.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/invoke-with-input-data.md new file mode 100644 index 0000000..d665422 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/invoke-with-input-data.md @@ -0,0 +1,475 @@ +--- +description: > + Example showing how to pass input data to a PowerShellScript resource and access properties, + array elements, and nested values inside the script. +ms.date: 05/10/2026 +ms.topic: reference +title: Invoke the PowerShellScript resource with input data +--- + + + +# Invoke the PowerShellScript resource with input data + +These examples show how you can pass input data to the +[`Microsoft.DSC.Transitional/PowerShellScript` resource][01] and how to bind that data to your +script with a [`param()` statement][02]. + +> [!NOTE] +> The script parameter can use any valid parameter name, but the script must define exactly one +> parameter. Don't name the parameter `$input`, because `$input` is an automatic variable in +> PowerShell. + +## Input data types + +The following examples show how data input is bound to the parameters for a defined scriptblock +when the parameter isn't defined with a specific type. + +The data that the resource passes to a script is first converted from the JSON input that DSC sends +with the [`ConvertFrom-Json` cmdlet][03]. + +### Passing string input data + +When you define `input` as a string value, the parameter for the script is a `[string]` object. + +```powershell +$instance = @' +input: hello world +getScript: |- + param($inputData) + + [ordered]@{ + boundDataType = "[$($inputData.GetType().FullName)]" + boundDataValue = $inputData + } +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - boundDataType: '[System.String]' + boundDataValue: hello world +``` + +### Passing integer input data + +When you define `input` as an integer value, the parameter for the script is an `[Int64]` value. + +```powershell +$instance = @' +input: 10 +getScript: |- + param($inputData) + + [ordered]@{ + boundDataType = "[$($inputData.GetType().FullName)]" + boundDataValue = $inputData + } +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - boundDataType: '[System.Int64]' + boundDataValue: 10 +``` + +### Passing boolean input data + +When you define `input` as a boolean value, the parameter for the script is a `[Boolean]` value. + +```powershell +$instance = @' +input: true +getScript: |- + param($inputData) + + [ordered]@{ + boundDataType = "[$($inputData.GetType().FullName)]" + boundDataValue = $inputData + } +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - boundDataType: '[System.Boolean]' + boundDataValue: true +``` + +### Passing array input data + +When you define `input` as a string value, the parameter for the script is a `[Object[]]` array. +The items in the array are data types as emitted by the [`ConvertFrom-Json` cmdlet][03]. + +```powershell +$instance = @' +input: +- hello world +- 10 +- 1.23 +- true +- null +- nested: object +- - nested + - array +getScript: |- + param($inputData) + + $inputData | ForEach-Object -Begin { $i = 0 } -Process { + [ordered]@{ + boundDataItemIndex = $i + boundDataItemType = if ($null -eq $_) { + '$null' + } else { + "[$($_.GetType().FullName)]" + } + boundDataItemValue = $_ + } + $i++ + } +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - boundDataItemIndex: 0 + boundDataItemType: '[System.String]' + boundDataItemValue: hello world + - boundDataItemIndex: 1 + boundDataItemType: '[System.Int64]' + boundDataItemValue: 10 + - boundDataItemIndex: 2 + boundDataItemType: '[System.Double]' + boundDataItemValue: 1.23 + - boundDataItemIndex: 3 + boundDataItemType: '[System.Boolean]' + boundDataItemValue: true + - boundDataItemIndex: 4 + boundDataItemType: $null + boundDataItemValue: null + - boundDataItemIndex: 5 + boundDataItemType: '[System.Management.Automation.PSCustomObject]' + boundDataItemValue: + nested: object + - boundDataItemIndex: 6 + boundDataItemType: '[System.Object[]]' + boundDataItemValue: + - nested + - array +``` + +### Passing object input data + +When you define `input` as an object value, the parameter for the script is a `[pscustomobject]`. +The values for each property of the object are data types as emitted by the +[`ConvertFrom-Json` cmdlet][03]. + +```powershell +$instance = @' +input: + string: hello world + integer: 10 + number: 1.23 + boolean: true + "null": null + nestedObject: + foo: bar + nestedArray: + - nested + - array +getScript: |- + param($inputData) + + $inputData.psobject.Properties | ForEach-Object -Process { + [ordered]@{ + boundDataPropertyName = $_.Name + boundDataPropertyType = "[$($_.TypeNameOfValue)]" + boundDataPropertyValue = $_.Value + } + } +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - boundDataPropertyName: string + boundDataPropertyType: '[System.String]' + boundDataPropertyValue: hello world + - boundDataPropertyName: integer + boundDataPropertyType: '[System.Int64]' + boundDataPropertyValue: 10 + - boundDataPropertyName: number + boundDataPropertyType: '[System.Double]' + boundDataPropertyValue: 1.23 + - boundDataPropertyName: boolean + boundDataPropertyType: '[System.Boolean]' + boundDataPropertyValue: true + - boundDataPropertyName: 'null' + boundDataPropertyType: '[System.Object]' + boundDataPropertyValue: null + - boundDataPropertyName: nestedObject + boundDataPropertyType: '[System.Management.Automation.PSCustomObject]' + boundDataPropertyValue: + foo: bar + - boundDataPropertyName: nestedArray + boundDataPropertyType: '[System.Object[]]' + boundDataPropertyValue: + - nested + - array +``` + +## Casting input data + +When you define the parameters for a scriptblock, you can specify a type for the input data. The +script uses PowerShell's [parameter type conversion][04] to try to convert the input +data. If the type conversion is impossible for the input data, PowerShell raises an error and the +operation fails. + +The following example shows how you can convert the input data to a given type. In this case, it +converts every item in the input data into a `[datetime]` object. + +```powershell +$instance = @' +input: + - 2026-01-02 + - 01/20/2026 +getScript: |- + param([datetime[]]$inputData) + + $inputData | ForEach-Object { + [ordered]@{ + InputDate = $_ + NextDate = $_.AddDays(1) + } + } +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - InputDate: 2026-01-02T00:00:00 + NextDate: 2026-01-03T00:00:00 + - InputDate: 2026-01-20T00:00:00 + NextDate: 2026-01-21T00:00:00 +``` + +## Input related errors + +Passing input to a script has several requirements: + +1. The script property for the resource must use the `param()` statement to define exactly one + parameter. The parameter can use any valid parameter name except `$input`, which is an automatic + variable in PowerShell. +1. The `input` property for the resource must be defined with a non-null value. +1. If the `param()` statement defines a type for the input data, the value for the `input` property + of the instance must be convertible to that type. + +The resource raises an error and prevents the script from executing when any of these requirements +aren't met by the resource instance definition. + +### Error: input provided but script has no parameters + +If you provide a value for `input` but the script does not define a `param()` statement, the +resource exits with code `2` and emits the following error message: + +```plaintext +Input was provided but script does not have a parameter to accept input. +``` + +```powershell +$instance = @' +getScript: | + "Script without parameters" +input: oops +'@ + +dsc resource get --resource Microsoft.DSC.Transitional/PowerShellScript --input $instance +``` + +```Output + ERROR PID : Input was provided but script does not have a parameter to accept input. + ERROR Failed to run process 'pwsh': Command: Resource 'pwsh' [exit code 1] manifest description: PowerShell script execution failed + ERROR Command: Resource 'pwsh' [exit code 1] manifest description: PowerShell script execution failed +``` + +### Error: Script defines a parameter but no input provided + +If the script defines a `param()` statement but no `input` is specified for the instance, the +resource exits with code `2` and emits the following error message: + +```plaintext +Script has a parameter '' but no input was provided. +``` + +```powershell +$instance = @' +getScript: | + param($inputObj) + "This will not run" +'@ + +dsc resource get --resource Microsoft.DSC.Transitional/PowerShellScript --input $instance +``` + +```Output + ERROR PID : Script has a parameter 'inputObj' but no input was provided. + ERROR Failed to run process 'pwsh': Command: Resource 'pwsh' [exit code 1] manifest description: PowerShell script execution failed + ERROR Command: Resource 'pwsh' [exit code 1] manifest description: PowerShell script execution failed +``` + +### Error: Script defines more than one parameter + +If the script defines a `param()` statement with two or more parameters, the resource exits with +code `1` and emits the following error message: + +```plaintext +Script must have exactly one parameter. +``` + +```powershell +$instance = @' +input: +- first +- second +getScript: |- + param($a, $b) + + [ordered]@{ + a = $a + b = $b + } +'@ + +dsc resource get --resource Microsoft.DSC.Transitional/PowerShellScript --input $instance +``` + +```Output + ERROR PID 23764: Script must have exactly one parameter. + ERROR Failed to run process 'pwsh': Command: Resource 'pwsh' [exit code 1] manifest description: PowerShell script execution failed + ERROR Command: Resource 'pwsh' [exit code 1] manifest description: PowerShell script execution failed +``` + +### Error: Script defines a typed parameter but input is invalid + +If the script defines the `param()` statement with a parameter that has a defined type that the +input data can't convert into, the resource raises an error message about an argument +transformation failure. + +```powershell +$instance = @' +input: foo +getScript: |- + param([int]$inputData) + + $inputData +'@ + +dsc resource get --resource Microsoft.DSC.Transitional/PowerShellScript --input $instance +``` + +```Output + ERROR PID : Exception calling "EndInvoke" with "1" argument(s): "Cannot process argument transformation on parameter 'inputData'. Cannot convert value "foo" to type "System.Int32". Error: "The input string 'foo' was not in a correct format."" + ERROR Failed to run process 'pwsh': Command: Resource 'pwsh' [exit code 1] manifest description: PowerShell script execution failed + ERROR Command: Resource 'pwsh' [exit code 1] manifest description: PowerShell script execution failed +``` + +## Using input in a configuration document + +You can pass input to a `PowerShellScript` instance inside a DSC configuration document, including +values from configuration parameters. The following configuration uses the [dsc config get][05] +command to pass a port number into the script: + +```yaml +# check-port.dsc.yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +parameters: + port: + type: int + defaultValue: 8080 +resources: + - name: checkPort + type: Microsoft.DSC.Transitional/PowerShellScript + properties: + getScript: | + param($inputObj) + Write-Information "Checking port $($inputObj.port)..." + Test-NetConnection -ComputerName localhost -Port $inputObj.port | + Select-Object -ExpandProperty TcpTestSucceeded + input: + port: "[parameters('port')]" +``` + +```powershell +dsc config get --file check-port.dsc.yaml +``` + +```yaml +executionInformation: + # Elided for brevity +metadata: + # Elided for brevity +results: +- executionInformation: + duration: PT12.3218732S + metadata: + Microsoft.DSC: + duration: PT12.3218732S + name: checkPort + type: Microsoft.DSC.Transitional/PowerShellScript + result: + actualState: + output: + - false +messages: [] +hadErrors: false +``` + + +[01]: ../index.md +[02]: /powershell/module/microsoft.powershell.core/about/about_functions_advanced_parameters#parameter-declaration +[03]: /powershell/module/microsoft.powershell.utility/convertfrom-json +[04]: /powershell/module/microsoft.powershell.core/about/about_functions_advanced_parameters#type-conversion-of-parameter-values +[05]: ../../../../../../cli/config/get.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/invoke-with-messaging.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/invoke-with-messaging.md new file mode 100644 index 0000000..1e7c3bb --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/invoke-with-messaging.md @@ -0,0 +1,527 @@ +--- +description: > + Example showing how to emit trace messages from a PowerShellScript resource. +ms.date: 05/10/2026 +ms.topic: reference +title: Invoke the PowerShellScript resource with trace messaging +--- + + + +# Invoke the PowerShellScript resource with trace messaging + +These examples show how you can emit messages from the +[`Microsoft.DSC.Transitional/PowerShellScript` resource][01]. + +## Emitting errors + +By default, any errors raised during script execution cause the execution to emit the error message +and immediately halt script execution. The following example snippets show how you can provide +error details for the user when a script fails. + +> [!IMPORTANT] +> The `PowerShellScript` resource runs scripts with `$ErrorActionPreference = 'Stop'` by default. +> Non-terminating errors from cmdlets are treated as terminating errors unless the script or cmdlet +> overrides the error action. Native command failures don't automatically stop script execution; +> script authors should check `$LASTEXITCODE` explicitly unless they enable +> [`$PSNativeCommandUseErrorActionPreference`][12] in PowerShell 7. + +### Emitting an error from a failed cmdlet + +In this example, the script depends on the `tstoy` command being available on the system. When the +command isn't available, the script fails and reports the error. + +```powershell +$instance = @' +getScript: |- + $tstoyCmd = Get-Command -Name tstoy -CommandType Application | + Select-Object -ExpandProperty Path + + & $tstoyCmd version --full --format json | ConvertFrom-Json +'@ + +dsc resource get --resource Microsoft.DSC.Transitional/PowerShellScript --input $instance +``` + +```Output + ERROR PID : Exception calling "EndInvoke" with "1" argument(s): "The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: The term 'tstoy' is not recognized as a name of a cmdlet, function, script file, or executable program. +Check the spelling of the name, or if a path was included, verify that the path is correct and try again." + ERROR Failed to run process 'pwsh': Command: Resource 'pwsh' [exit code 1] manifest description: PowerShell script execution failed + ERROR Command: Resource 'pwsh' [exit code 1] manifest description: PowerShell script execution failed +``` + +The first error in the output indicates that the script execution was stopped by the error from the +`Get-Command` invocation, which showed that `tstoy` wasn't available on the system. + +### Emitting errors with `Write-Error` + +Instead of raising the default error from a failed command, you can use the [`Write-Error`][02] +cmdlet to emit a specific error message. In this example, the script depends on the `tstoy` command +being available on the system. When the command isn't available, the script fails and reports the +error. + +```powershell +$instance = @' +getScript: |- + $tstoyCmd = Get-Command -Name tstoy* -CommandType Application | + Where-Object {$_.Name -match 'tstoy(\.exe)?' } | + Select-Object -ExpandProperty Path + if ([string]::IsNullOrEmpty($tstoyCmd)) { + Write-Error "command 'tstoy' not found; unable to report version for 'tstoy'" + } + + & $tstoyCmd version --full --format json | ConvertFrom-Json +'@ + + +dsc resource get --resource Microsoft.DSC.Transitional/PowerShellScript --input $instance +``` + +```Output + ERROR PID : Exception calling "EndInvoke" with "1" argument(s): "The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: command 'tstoy' not found; unable to report version for 'tstoy'" + ERROR Failed to run process 'pwsh': Command: Resource 'pwsh' [exit code 1] manifest description: PowerShell script execution failed + ERROR Command: Resource 'pwsh' [exit code 1] manifest description: PowerShell script execution failed +``` + +The first error in the output indicates that the script execution was stopped and includes the +message emitted from the `Write-Error` command. + +### Throwing an error from a `catch` block + +In the previous error examples, the emitted error includes information about execution stopping +because of the error action preference being set to stop. You can make the error message clearer +by rethrowing the underlying exception from a the `catch` block in a [`try`/`catch` statement][03]. + +```powershell +$instance = @' +getScript: |- + try { + $tstoyCmd = Get-Command -Name tstoy -CommandType Application | + Select-Object -ExpandProperty Path + + & $tstoyCmd version --full --format json | ConvertFrom-Json + } catch { + throw $_.Exception + } +'@ + +dsc resource get --resource Microsoft.DSC.Transitional/PowerShellScript --input $instance +``` + +```Output + ERROR PID : Exception calling "EndInvoke" with "1" argument(s): "The term 'tstoy' is not recognized as a name of a cmdlet, function, script file, or executable program. +Check the spelling of the name, or if a path was included, verify that the path is correct and try again." + ERROR Failed to run process 'pwsh': Command: Resource 'pwsh' [exit code 1] manifest description: PowerShell script execution failed + ERROR Command: Resource 'pwsh' [exit code 1] manifest description: PowerShell script execution failed +``` + +## Emitting warning messages + +You can emit warning messages from a script with the [`Write-Warning`][04] cmdlet. + +This example shows how you can emit a warning from a script without halting execution. The script +looks for the `tstoy` command and returns the version information for that command if it exists. If +the command isn't available, the script raises a warning and returns no output data. + +```powershell +$instance = @' +getScript: |- + $tstoyCmd = Get-Command -Name tstoy* -CommandType Application | + Where-Object {$_.Name -match 'tstoy(\.exe)?' } | + Select-Object -ExpandProperty Path + + if ([string]::IsNullOrEmpty($tstoyCmd)) { + Write-Warning "command 'tstoy' not found; unable to report version for 'tstoy'" + } else { + & $tstoyCmd version --full --format json | ConvertFrom-Json + } +'@ + + +dsc resource get --resource Microsoft.DSC.Transitional/PowerShellScript --input $instance +``` + +```Output + WARN PID : command 'tstoy' not found; unable to report version for 'tstoy' +actualState: + output: [] +``` + +## Emitting info messages + +You can emit `info` level messages for DSC with the [`Write-Verbose`][05] and [`Write-Host`][06] +cmdlets. When a cmdlet used in your script emits verbose or information messages, you can use the +[`-Verbose` common parameter][07] or specify the [`-InformationAction` common parameter][08] as +`Continue` to have those messages emitted for DSC. + +### Emitting verbose messages from cmdlets + +The following snippet creates a temporary file. It uses commands that emit verbose messages, like +`New-Item`. The example shows how you can specify the `-Verbose` parameter on cmdlets to surface +their verbose messaging in DSC as `info` level trace messages. + +```powershell +$instance = [ordered]@{ + input = 'create' + getScript = { + param( + [ValidateSet('create', 'delete')] + [string] $fileOperation + ) + + $tempFolder = "Temp:/dsc/examples/PowerShellScript/messaging" + $tempFile = Join-Path $tempFolder 'info.txt' + + if (Test-Path $tempFile) { + $fileInfo = Get-Item -Path $tempFile + + [ordered]@{ + path = $fileInfo.FullName + exists = $true + creationTimeUtc = $fileInfo.CreationTimeUtc + lastWriteTimeUtc = $fileInfo.LastWriteTimeUtc + attributes = $fileInfo.Attributes.ToString() + } + } else { + [ordered]@{ + path = $fileInfo.FullName + exists = $false + } + } + }.ToString() + setScript = { + param( + [ValidateSet('create', 'delete')] + [string] $fileOperation + ) + + $tempFolder = "Temp:\dsc\examples\PowerShellScript\messaging" + $tempFile = Join-Path $tempFolder 'info.txt' + + switch ($fileOperation) { + 'create' { + if (-not (Test-Path $tempFolder)) { + $null = New-Item -Path $tempFolder -ItemType Directory -Force -Verbose + } + if (-not (Test-Path $tempFile)) { + $null = New-Item -Path $tempFile -ItemType File -Verbose + } + + $fileInfo = Get-Item -Path $tempFile + + [ordered]@{ + path = $fileInfo.FullName + exists = $true + creationTimeUtc = $fileInfo.CreationTimeUtc + lastWriteTimeUtc = $fileInfo.LastWriteTimeUtc + attributes = $fileInfo.Attributes + } + } + 'delete' { + if (Test-Path $tempFile) { + Remove-Item -Path $tempFile -Force -Verbose + } + + [ordered]@{ + path = $fileInfo.FullName + exists = $false + } + } + } + }.ToString() +} + +dsc --trace-level info resource set --resource Microsoft.DSC.Transitional/PowerShellScript --input ( + $instance | ConvertTo-Json -Compress +) +``` + +```Output + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + INFO PID : Performing the operation "Create Directory" on target "Destination: C:\Users\\AppData\Local\Temp\dsc\examples\PowerShellScript". + INFO PID : Performing the operation "Create Directory" on target "Destination: C:\Users\\AppData\Local\Temp\dsc\examples\PowerShellScript\messaging". + INFO PID : Performing the operation "Create File" on target "Destination: C:\Users\\AppData\Local\Temp\dsc\examples\PowerShellScript\messaging\info.txt". + INFO diff: key 'creationTimeUtc' missing + INFO diff: key 'lastWriteTimeUtc' missing + INFO diff: key 'attributes' missing + INFO diff: actual array missing expected item + INFO diff: arrays differ for 'output' +beforeState: + output: + - path: null + exists: false +afterState: + output: + - path: C:\Users\\AppData\Local\Temp\dsc\examples\PowerShellScript\messaging\info.txt + exists: true + creationTimeUtc: 2026-05-21T17:58:31.2115007Z + lastWriteTimeUtc: 2026-05-21T17:58:31.2115007Z + attributes: 32 +changedProperties: +- output +``` + +The info messages emitted by DSC include the verbose messages from creating the temporary directory +and file. + +Invoke the resource again but with the `input` set to `delete` to remove the temporary file: + +```powershell +$instance.input = 'delete' + +dsc --trace-level info resource set --resource Microsoft.DSC.Transitional/PowerShellScript --input ( + $instance | ConvertTo-Json -Compress +) +``` + +### Emitting verbose messages with `Write-Verbose` + +You can surface custom `info` level messages from scripts with the [`Write-Verbose`][05] cmdlet. + +The following snippet shows how messages from `Write-Verbose` surface as DSC trace messages. + +```powershell +$instance = @' +getScript: |- + Write-Verbose "Setting things up" + Write-Verbose "Retrieving data" +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) + +dsc --trace-level info resource get @arguments +``` + +```Output + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Invoking get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + INFO PID : Setting things up + INFO PID : Retrieving data +actualState: + output: [] +``` + +### Emitting verbose messages with `Write-Host` + +You can surface custom `info` level messages from scripts with the [`Write-Host`][06] cmdlet. + +The following snippet shows how messages from `Write-Host` surface as DSC trace messages. + +```powershell +$instance = @' +getScript: |- + Write-Host "Setting things up" + Write-Host "Retrieving data" +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) + +dsc --trace-level info resource get @arguments +``` + +```Output + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Invoking get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + INFO PID : Setting things up + INFO PID : Retrieving data +actualState: + output: [] +``` + +## Emitting debug messages + +You can emit `debug` level messages for DSC with the [`Write-Debug`][09] cmdlet. When a cmdlet used +in your script emits debug messages, you can use the [`-Debug` common parameter][07] to have those +messages emitted for DSC. + +### Emitting debug messages from cmdlets + +The following snippet shows how debug messages from commands are captured by the resource. It +defines a function that emits debug messages and then invokes that function. + +```powershell +$instance = @' +getScript: |- + function Get-Data { + [CmdletBinding()] + param() + + Write-Debug "Starting process..." + Write-Debug "Doing things..." + Write-Debug "Done." + } + + Get-Data +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) + +dsc --trace-level debug resource get @arguments +``` + +```Output + INFO dsc_lib::dscresources::command_resource: 69: Invoking get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + DEBUG dsc_lib::dscresources::command_resource: 1218: PID : Starting process... + DEBUG dsc_lib::dscresources::command_resource: 1218: PID : Doing things... + DEBUG dsc_lib::dscresources::command_resource: 1218: PID : Done. + DEBUG dsc_lib::dscresources::command_resource: 850: Process 'pwsh' id exited with code 0 + DEBUG dsc_lib::dscresources::command_resource: 72: Verifying output of get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' +actualState: + output: [] +``` + +The output shows `debug` level messages emitted by the invoked function in the script. + +### Emitting debug messages with `Write-Debug` + +You can surface custom `debug` level messages from scripts with the [`Write-Debug`][05] cmdlet. + +The following snippet shows how messages from `Write-Debug` surface as DSC trace messages. + +```powershell +$instance = @' +getScript: |- + Write-Debug "Setting things up" + Write-Debug "Retrieving data" +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) + +dsc --trace-level debug resource get @arguments +``` + +```Output + INFO dsc_lib::dscresources::command_resource: 69: Invoking get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + DEBUG dsc_lib::dscresources::command_resource: 1218: PID : Setting things up + DEBUG dsc_lib::dscresources::command_resource: 1218: PID : Retrieving data + DEBUG dsc_lib::dscresources::command_resource: 850: Process 'pwsh' id exited with code 0 + DEBUG dsc_lib::dscresources::command_resource: 72: Verifying output of get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' +actualState: + output: [] +``` + +## Emitting trace messages + +You can emit `trace` level messages for DSC with the [`Write-Information`][10] cmdlet. When a +cmdlet used in your script emits debug messages, you can specify the +[`-InformationAction` common parameter][11] as `Continue` to have those messages emitted for DSC. + +### Emitting trace messages from cmdlets + +The following snippet shows how information messages from commands are captured by the resource as +trace messages. It defines a function that emits information messages and then invokes that +function with `-InformationAction` as `Continue`. + +```powershell +$instance = @' +getScript: |- + function Get-Data { + [CmdletBinding()] + param() + + Write-Information "Starting process..." + Write-Information "Doing things..." + Write-Information "Done." + } + + Get-Data -InformationAction Continue +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) + +dsc --trace-level trace resource get @arguments +``` + +```Output + INFO dsc_lib::dscresources::command_resource: 69: Invoking get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + TRACE dsc_lib::dscresources::command_resource: 898: Invoking command 'pwsh' with args Some(["-NoLogo", "-NonInteractive", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", "$input | ./psscript.ps1", "get"]) + TRACE dsc_lib::dscresources::command_resource: 900: Current working directory: C:\code\dsc\dsc-pr-review\bin\debug + TRACE dsc_lib::dscresources::command_resource: 806: Writing to command STDIN: {"getScript":"function Get-Data {\n [CmdletBinding()]\n param()\n\n Write-Information \"Starting process...\"\n Write-Information \"Doing things...\"\n Write-Information \"Done.\"\n}\n\nGet-Data -InformationAction Continue"} + TRACE dsc_lib::dscresources::command_resource: 1220: PID : Starting process... + TRACE dsc_lib::dscresources::command_resource: 1220: PID : Doing things... + TRACE dsc_lib::dscresources::command_resource: 1220: PID : Done. + DEBUG dsc_lib::dscresources::command_resource: 850: Process 'pwsh' id exited with code 0 + DEBUG dsc_lib::dscresources::command_resource: 72: Verifying output of get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + TRACE dsc_lib::dscresources::command_resource: 1083: Verify JSON for 'Microsoft.DSC.Transitional/PowerShellScript': {"output":[]} + +actualState: + output: [] +``` + +The output shows `trace` level messages emitted by the invoked function in the script. + +### Emitting trace messages with `Write-Information` + +You can surface custom `trace` level messages from scripts with the [`Write-Information`][10] +cmdlet. + +The following snippet shows how messages from `Write-Information` surface as DSC trace messages. + +```powershell +$instance = @' +getScript: |- + Write-Information "Setting things up" + Write-Information "Retrieving data" +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) + +dsc --trace-level trace resource get @arguments +``` + +```Output + INFO dsc_lib::dscresources::command_resource: 69: Invoking get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + TRACE dsc_lib::dscresources::command_resource: 898: Invoking command 'pwsh' with args Some(["-NoLogo", "-NonInteractive", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", "$input | ./psscript.ps1", "get"]) + TRACE dsc_lib::dscresources::command_resource: 900: Current working directory: C:\code\dsc\dsc-pr-review\bin\debug + TRACE dsc_lib::dscresources::command_resource: 806: Writing to command STDIN: {"getScript":"Write-Information \"Setting things up\"\nWrite-Information \"Retrieving data\""} + TRACE dsc_lib::dscresources::command_resource: 1220: PID : Setting things up + TRACE dsc_lib::dscresources::command_resource: 1220: PID : Retrieving data + DEBUG dsc_lib::dscresources::command_resource: 850: Process 'pwsh' id exited with code 0 + DEBUG dsc_lib::dscresources::command_resource: 72: Verifying output of get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + TRACE dsc_lib::dscresources::command_resource: 1083: Verify JSON for 'Microsoft.DSC.Transitional/PowerShellScript': {"output":[]} + +actualState: + output: [] +``` + + +[01]: ../index.md +[02]: /powershell/module/microsoft.powershell.utility/write-error +[03]: /powershell/module/microsoft.powershell.core/about/about_try_catch_finally +[04]: /powershell/module/microsoft.powershell.utility/write-warning +[05]: /powershell/module/microsoft.powershell.utility/write-verbose +[06]: /powershell/module/microsoft.powershell.utility/write-host +[07]: /powershell/module/microsoft.powershell.core/about/about_commonparameters#-verbose +[08]: /powershell/module/microsoft.powershell.core/about/about_commonparameters#-informationaction +[09]: /powershell/module/microsoft.powershell.utility/write-debug +[10]: /powershell/module/microsoft.powershell.utility/write-information +[11]: /powershell/module/microsoft.powershell.core/about/about_commonparameters#-informationaction +[12]: /powershell/module/microsoft.powershell.core/about/about_preference_variables#psnativecommanduseerroractionpreference diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/invoke-with-output-data.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/invoke-with-output-data.md new file mode 100644 index 0000000..01ae671 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/invoke-with-output-data.md @@ -0,0 +1,887 @@ +--- +description: > + Example showing how to return output data from a PowerShellScript resource. +ms.date: 05/10/2026 +ms.topic: reference +title: Invoke the PowerShellScript resource with output data +--- + + + +# Invoke the PowerShellScript resource with output data + +These examples show how you can return output from the +[`Microsoft.DSC.Transitional/PowerShellScript` resource][01]. + +## Output data types + +All output that a script emits for this resource is inserted into the `output` array for the +resource instance. The resource uses the `ConvertTo-Json` cmdlet for every item emitted to the +[Success stream][02]. The converted representation is what the resource inserts into the `output` +array. + +When the resource serializes the output data as JSON it retains up to `9` levels of depth. This can +make the output for typical PowerShell objects a script may return very large and difficult to +parse in the result for an operation. + +### Outputting scalar values + +The following snippet shows how scalar values (not objects or arrays) are handled by the resource +when emitted by a script. Scalar values include strings, integers, floats, booleans, and `$null`. + +```powershell +$instance = @' +getScript: |- + $true # boolean scalar value + 1 # integer scalar value + 1.2 # float scalar value + $null # null scalar value + 'apple' # string scalar value +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) + +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - true + - 1 + - 1.2 + - null + - apple +``` + +### Outputting objects + +When a script emits objects that aren't scalar values, the conversion to JSON representation +includes up to `9` levels of depth. Objects often have properties that are _also_ objects with +sub-properties or arrays of nested objects. + +When the object output is particularly large and complex it can cause the resource operation to +fail when DSC needs to validate the output data. The following snippet shows how emitting a +`[FileInfo]` object directly can cause the resource to fail. + +The script creates a new temporary file, which emits the `[FileInfo]` object for the new file as +output. + +```powershell +$instance = @' +getScript: |- + $filePath = 'Temp:/dsc/examples/PowerShellScript/output.txt' + + New-Item -Path $filePath -Force +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) + +dsc --trace-level debug resource get @arguments +``` + +```Output + INFO dsc_lib::dscresources::command_resource: 69: Invoking get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + DEBUG dsc_lib::dscresources::command_resource: 850: Process 'pwsh' id exited with code 0 + DEBUG dsc_lib::dscresources::command_resource: 72: Verifying output of get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + ERROR dsc::resource_command: 67: JSON: expected value at line 1 column 1 +``` + +We can demonstrate the failure independently of DSC. When you invoke the following snippet, +PowerShell hangs. A `[FileInfo]` object can be extremely large as the object contains references to +its parent folder, which references that object's parent folder, and so on. + +```powershell +$fileInfo = Get-Item -Path 'Temp:/dsc/examples/PowerShellScript/output.txt' +$fileJson = ConvertTo-Json -Depth 9 -InputObject $fileInfo +# The following commands never run because the session hangs +$outputSize = [System.Text.Encoding]::UTF8.GetByteCount($fileJson) / 1MB +"The output JSON is {0} MB" -f [Math]::Round($outputSize, 2) +``` + + +You can cancel the command by pressing Ctrl+C in your console. + +If you update the depth to `5` and invoke the command again, you can see that the size of the JSON +object is _substantial_. + +```powershell +$fileInfo = Get-Item -Path 'Temp:/dsc/examples/PowerShellScript/output.txt' +$fileJson = ConvertTo-Json -Depth 5 -InputObject $fileInfo +# The following commands never run because the session hangs +$outputSize = [System.Text.Encoding]::UTF8.GetByteCount($fileJson) / 1MB +"The output JSON is {0} MB" -f [Math]::Round($outputSize, 2) +``` + +```Output +WARNING: Resulting JSON is truncated as serialization has exceeded the set depth of 5. +The output JSON is 58.37 MB +``` + +Instead of emitting complex objects directly, consider constructing your output objects +intentionally. For a comprehensive example of emitting structured output, see the +["Structure output for an idempotent instance"](#structure-output-for-an-idempotent-instance) +section of this article. + +### Outputting arrays + +By default, when a script emits an array as output, each item in the array is captured as a +separate item in the `output` property for the resource. + +The following snippet shows the default behavior. + +```powershell +$instance = @' +getScript: |- + @('a', 'b', 'c') + @(1, 2, 3) +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) + +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - a + - b + - c + - 1 + - 2 + - 3 +``` + +In the previous snippet, the script emitted two arrays: + +1. An array containing three strings +1. An array containing three integers + +The `output` for the resource included six separate items representing each of the items in the +emitted arrays in the order that the script emitted them. + +The following snippet shows how you can use the [`Write-Object` cmdlet][03] with the +[`-NoEnumerate`][04] parameter to emit arrays from the script and keep them as arrays. + +```powershell +$instance = @' +getScript: |- + Write-Output -NoEnumerate @('a', 'b', 'c') + Write-Output -NoEnumerate @(1, 2, 3) +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) + +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - - a + - b + - c + - - 1 + - 2 + - 3 +``` + +Now the output from the script shows two items in the `output` array. Each item is an array +containing three items. + +## Discarding unwanted output + +Every item emitted to the success stream is included in the `output` for the resource. To avoid +including unwanted data in the output you need to discard that data. To discard data from a +statement that would otherwise emit unwanted output, you can: + +- Assign the statement to `$null`. +- Redirect the statement to `$null`. +- Cast the statement to `[void]`. +- Pipe the statement to `Out-Null`. + +The first three options have nearly identical performance. Piping to `Out-Null` can be much slower +when looping over a large set of data. + +The following snippet shows examples for discarding unwanted output in a script. + +```powershell +$instance = @' +getScript: |- + $filePath = 'Temp:/dsc/examples/PowerShellScript/output.txt' + # Assign to `$null` + $null = New-Item -Path $filePath -Force + # Redirect to `$null` + New-Item -Path $filePath -Force > $null + # Cast to `[void]` + [void](New-Item -Path $filePath -Force) + # Pipe to `Out-Null` + New-Item -Path $filePath -Force | Out-Null + + 'this is the only output' +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) + +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - this is the only output +``` + +## Output for `getScript` + +For `getScript` you can emit any data to the PowerShell success stream that you want to surface to +the user. The emitted data is returned in the `actualState.output` field for the **Get** operation +result and the `beforeState.output` field for the **Set** operation result. + +If you're defining the resource instance to idempotently manage the state of one or more system +components, ensure that the output you emit from `getScript` uses the same structure as the output +from `setScript` to make the results readable for the user. + +Otherwise, return any data that you want to surface to the user. If you want to give the user more +information, you can [emit messages][05]. For comprehensive examples of emitting messages from your +script see [Invoke the PowerShellScript resource with trace messaging][06]. + +The following example shows how you can emit items from `getScript` to inform the user. For a +comprehensive example of structured output for an instance that idempotently manages system state, +see ["Structure output for an idempotent instance"](#structure-output-for-an-idempotent-instance) +in this article. + +```powershell +$instance = @' +getScript: |- + "Current context is interactive: {0}" -f [Environment]::UserInteractive + "Current context is privileged: {0}" -f [Environment]::IsPrivilegedProcess +'@ + +dsc resource get --resource Microsoft.DSC.Transitional/PowerShellScript --input $instance +``` + +```yaml +actualState: + output: + - 'Current context is interactive: True' + - 'Current context is privileged: False' +``` + +## Output for `testScript` + +The `testScript` definition _must_ return a single boolean value - `$true` to indicate that the +system is in the desired state or `$false` otherwise. + +Any of the following will cause the resource to raise an error when invoking the `testScript`: + +- Not emitting any output at all to the success stream. +- Emitting any non-boolean data to the success stream. +- Emitting more than one boolean value to the success stream. + +You can [emit messages][05] To indicate to the user how and why the +system isn't in the desired state. For detailed examples of emitting messages from your script +see [Invoke the PowerShellScript resource with trace messaging][06]. + +The following example shows how you can define `testScript` to check whether a file exists and +isn't empty. It emits info messages to clarify whether and how the instance is in the desired +state. + +```powershell +$instance = @' +testScript: |- + $filePath = 'Temp:/dsc/examples/PowerShellScript/output.txt' + + if (-not (Test-Path $filePath)) { + Write-Verbose "The file '$filePath' doesn't exist" + return $false + } + + if ([string]::IsNullOrEmpty((Get-Content -Raw -Path $filePath))) { + Write-Verbose "The file '$filePath' is empty" + return $false + } + + Write-Verbose "The file '$filePath' exists and contains content" + $true +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/PowerShellScript' + '--input', $instance +) + +dsc --trace-level info resource test @arguments +``` + +```console + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Invoking test on 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + INFO PID : The file 'Temp:/dsc/examples/PowerShellScript/output.txt' is empty + INFO diff: key 'testScript' missing +desiredState: + testScript: |- + $filePath = 'Temp:/dsc/examples/PowerShellScript/output.txt' + + if (-not (Test-Path $filePath)) { + Write-Verbose "The file '$filePath' doesn't exist" + return $false + } + + if ([string]::IsNullOrEmpty((Get-Content -Raw -Path $filePath))) { + Write-Verbose "The file '$filePath' is empty" + return $false + } + + Write-Verbose "The file '$filePath' exists and contains content" + $true +actualState: + _inDesiredState: false +inDesiredState: false +differingProperties: +- testScript +``` + +For a more comprehensive example that idempotently manages system state see the +["Structure output for an idempotent instance"](#structure-output-for-an-idempotent-instance) +section of this article. + +## Output for `setScript` + +For `setScript` you can emit any data to the PowerShell success stream that you want to surface to +the user. The emitted data is returned in the `afterState.output` field for the **Set** operation +result. + +If you're defining the resource instance to idempotently manage the state of one or more system +components, ensure that the output you emit from `setScript` uses the same structure as the output +from `getScript` to make the results readable for the user. + +Otherwise, return any data that you want to surface to the user. If you want to give the user more +information, you can [emit messages][05]. For comprehensive examples of +emitting messages from your script see +[Invoke the PowerShellScript resource with trace messaging][06]. + +The following example shows how you can emit items from `setScript` to inform the user about how +the script is modifying the system. + +```powershell +$instance = @' +setScript: |- + $filePath = 'Temp:/dsc/examples/PowerShellScript/output.txt' + $content = 'Hello world' + if (-not (Test-Path $filePath)) { + "File '$filePath' doesn't exist - creating it" + $null = New-Item -Path $filePath -Force + } + + $currentContent = Get-Content -Raw -Path $filePath + if ([string]::IsNullOrEmpty($currentContent)) { + "File '$filePath' is empty - adding content" + $content | Set-Content -Path $filePath -NoNewline + } elseif ($currentContent -ne $content) { + "File '$filePath' contains invalid content - overriding content" + $content | Set-Content -Path $filePath -NoNewline + } else { + "File '$filePath' contains desired content'" + } + + [ordered]@{ + initialContent = $currentContent + finalContent = $content + } +'@ + +dsc resource set --resource Microsoft.DSC.Transitional/PowerShellScript --input $instance +``` + +```yaml +beforeState: {} +afterState: + output: + - File 'Temp:/dsc/examples/PowerShellScript/output.txt' is empty - adding conent + - initialContent: null + finalContent: Hello world +changedProperties: +- output +``` + +In this example, `beforeState` is an empty object because the instance doesn't define `getScript`. +The output from `setScript` includes two items. The first is a message indicating that the file +exists but is empty. The second item is an object showing both the initial content and final +content of the file. + +For a comprehensive example of structured output for an instance that idempotently manages system +state, including defining `getScript` to populate the `beforeState` in the **Set** result, see the +[Structure output for an idempotent instance](#structure-output-for-an-idempotent-instance) section +of this article. + +## Structure output for an idempotent instance + +To return output that is readable for the user, consider returning only objects. Use property names +to orient the user when reviewing the output. Limit the depth of the object to no more than three +levels when possible. + +The following example shows how you can return information about a JSON configuration file that +isn't managed by a specific DSC resource. It follows best practices by: + +1. Implementing scripts for all three operations. +1. Returning a single structured object from `getScript`. +1. Returning a boolean for `testScript` and emitting trace messages to indicate _how_ the instance + is out of the desired state. +1. Returning the same structured object from `setScript` as `getScript`. +1. Emitting trace messages to indicate which settings the `setScript` is modifying. + +> [!NOTE] +> This example uses an ordered dictionary to represent the instance because the script properties +> are much longer and more detailed than earlier examples in this article. Defining the scripts +> this way makes it easier to review the script code than defining it all together in a YAML +> snippet. +> +> The `getScript` and `setScript` snippets define the output object as an ordered dictionary with +> the `[ordered]` type accelerator. This ensures that the emitted object always keeps the key-value +> pairs in the defined order. Defining the output object as a normal hashtable causes the ordering +> of the output object properties to be nondeterministic, which can make comparing results more +> difficult. +> +> You could also define the output object as a `[pscustomobject]` and use the `Add-Member` function +> to add more properties to the initial object. + +First, define an ordered dictionary to represent the instance. Define the `input` for the scripts +the instance will use. In this example, the input data includes both the path to the file and the +settings to manage in that file. + +```powershell +$instance = [ordered]@{ + input = [ordered]@{ + filePath = 'Temp:/dsc/examples/PowerShellScript/output.json' + settings = [ordered]@{ + updateAutomatically = $true + updateFrequency = 30 + } + } +} +``` + +Next, define `getScript` to retrieve the actual state of the configuration file. The script must +define a `param()` statement to accept the input data. + +The script returns an object that always includes the `filePath` and `exists` properties. +`filePath` is identical to `input.filePath` for the instance. `exists` indicates whether the file +actually exists on the system. + +If the file doesn't exist, that's all the information the instance can provide. The script returns +that data and stops processing. + +If the file does exist, the output object also includes the `settings` and `lastWriteTime` +properties. `settings` is the contents of the file converted from JSON. `lastWriteTime` is the +actual last write time for the file itself. + +```powershell +$instance.getScript = { + param($inputData) + + $result = [ordered]@{ + filePath = $inputData.filePath + exists = Test-Path -Path $inputData.filePath + } + + if (-not $result.exists) { + Write-Verbose "Config file doesn't exist" + return $result + } + Write-Verbose "Retrieving settings and last write time from config file" + $fileInfo = Get-Item -Path $inputData.filePath + $settings = Get-Content -Raw -Path $inputData.filePath | ConvertFrom-Json + + $result.settings = $settings + $result.lastWriteTime = $fileInfo.LastWriteTime + + $result +}.ToString() +``` + +The next snippet defines `testScript` for the instance. As with `getScript`, the script must define +a single parameter. Unlike `getScript`, this script must return exactly one boolean value. + +The test script: + +1. Checks whether the configuration file (`input.filePath`) exists. If it doesn't, the script emits + an info message and returns `$false`. +1. Checks whether the configuration file is empty. If it is, the script emits an info message and + returns `$false`. +1. Iterates over the key-value pairs for the desired settings (`input.settings`) to check whether + each of them is in the desired state. If the desired setting isn't defined or is defined with + an incorrect value the script emits an info message and marks the resource as noncompliant but + _doesn't_ stop processing. + + This ensures that the instance can fully report on the desired settings instead of only reporting + the first missing or incorrect setting. +1. Returns `$false` if any setting wasn't in the desired state and otherwise `$true`. + +```powershell +$instance.testScript = { + param($inputData) + + if (-not (Test-Path -Path $inputData.filePath)) { + Write-Verbose "Config file doesn't exist" + return $false + } + + $content = Get-Content -Raw -Path $inputData.filePath + if ([string]::IsNullOrEmpty($content)) { + Write-Verbose "Config file is empty" + return $false + } + + # Initialize variable for result. If any check fails, set to `$false` + # From this point on we want to fully validate state for info messages to + # the user instead of returning early. + $inDesiredState = $true + + # Loop over the desired state to compare to actual settings + $desiredSettings = $inputData.settings.psobject.Properties + $actualSettings = ($content | ConvertFrom-Json).psobject.Properties + foreach ($setting in $desiredSettings) { + $name = $setting.Name + $desiredValue = $setting.Value + $actualSetting = $actualSettings | Where-Object Name -EQ $name + + if ($null -eq $actualSetting) { + Write-Verbose "Missing setting '$name'" + $inDesiredState = $false + continue + } + + if ($actualSetting.Value -ne $setting.Value) { + $message = "Expected setting '{0}' to be ``{1}`` but it is ``{2}``" -f @( + $name + $desiredValue + $actualSetting.Value + ) + Write-Verbose $message + $inDesiredState = $false + } + } + + $inDesiredState +}.ToString() +``` + +To enforce the desired state, define the `setScript` for the instance. The script must define a +single parameter. To make the result for the **Set** operation readable the script emits the same +data structure as `getScript`. + +The script is defined to be idempotent, only modifying the system if needed. It follows these steps: + +1. Define the result object with `filePath` as the `input.filePath` value and `exists` as `true`. +1. Check whether the configuration file exists. If it doesn't, emit a message to indicate that the + instance is creating the file. Then create the file and write the desired state settings + (`input.settings`) into it. Populate the `settings` and `lastWriteTime` fields for the result + object and then use the `return` keyword to emit the result and stop processing the script. +1. If the configuration file does exist retrieve the settings from it. Iterate over the desired + state settings (`input.settings`). If the setting is missing or defined incorrectly, emit an + info message and mark the instance as requiring an update with the `$shouldUpdate` variable. + This ensures that the instance only modifies the file when the settings aren't in the desired + state. + + > [!NOTE] + > This is necessary for version `0.1.0` of this resource. In this release the resource doesn't + > use the `testScript` to determine whether to actually invoke the `setScript`. The resource + > _always_ invokes `setScript` when you invoke the **Set** operation for the resource or on a + > configuration document containing an instance of the resource. + + If the setting is missing, add the desired state setting to the object representing the actual + state. If the setting has the incorrect value, set that property on the same object to the + desired state. This ensures that the resource doesn't inadvertently modify or remove any + settings in the configuration file that the instance isn't managing (the setting is defined in + the file but not `input.settings`). +1. If any of the desired state settings weren't defined in the configuration file or were defined + with invalid values emit a message and update the file with the combined settings. Otherwise + emit a message indicating that the configuration file didn't require any modification. +1. Update the result object to include the final settings and the last write time for the file and + emit the result. + +`setScript` returns the same structured output data as `getScript` regardless of whether the script +creates, updates, or doesn't modify the configuration file. This helps make the output for the +**Set** operation readable and enable directly comparing the `beforeState` and `afterState` fields +in the result. + +```powershell +$instance.setScript = { + param($inputData) + + $filePath = $inputData.filePath + $settings = $inputData.settings + $result = [ordered]@{ + filePath = $filePath + exists = $true + } + + if (-not (Test-Path -Path $filePath)) { + Write-Verbose "Creating config file with specified settings" + $null = New-Item -Path $filePath -Force -Verbose + $json = $settings | ConvertTo-Json + $json | Out-File -FilePath $filePath -Encoding utf8NoBOM + + $result.settings = $settings + $result.lastWriteTime = Get-Item -Path $filePath | + Select-Object -ExpandProperty LastWriteTime + + return $result + } + + $content = Get-Content -Raw -Path $filePath + $actualSettings = $content | ConvertFrom-Json + $shouldUpdate = $false + # Iterate over defined settings, updating the actual settings as needed. + # Don't remove any non-managed settings, only enforce specified settings. + # Set shouldUpdate to $true if any changes are needed, but wait to write + # to the file until all changes are processed to avoid multiple writes. + foreach ($setting in $settings.psobject.Properties) { + $name = $setting.Name + $value = $setting.Value + Write-Verbose "Processing setting '$name' with desired value ``$value``" + $actual = $actualSettings.psobject.Properties | + Where-Object Name -EQ $name | + Select-Object -First 1 + + if ($null -eq $actual) { + Write-Verbose "Adding setting '$name' as ``$value``" + + $shouldUpdate = $true + $memberParams = @{ + InputObject = $actualSettings + MemberType = 'NoteProperty' + Name = $name + Value = $value + } + Add-Member @memberParams + } elseif ($value -eq $actual.Value) { + Write-Verbose "Setting '$name' is already set to ``$value``" + } else { + $message = "Changing setting '{0}' from ``{1}`` to ``{2}``" -f @( + $name + $actual.Value + $value + ) + Write-Verbose $message + + $shouldUpdate = $true + $actualSettings.$name = $value + } + } + + if ($shouldUpdate) { + Write-Verbose "Updating config file with new settings" + $json = $actualSettings | ConvertTo-Json + $json | Out-File -FilePath $filePath -Encoding utf8NoBOM + } else { + Write-Verbose "Config file is already in the desired state. No update needed." + } + + $result.settings = $actualSettings + $result.lastWriteTime = Get-Item -Path $filePath | + Select-Object -ExpandProperty LastWriteTime + + $result +}.ToString() +``` + +With the instance fully defined, invoke the **Get** operation to ensure that returning the actual +state works as expected: + +```powershell +dsc --trace-level info resource get --resource Microsoft.DSC.Transitional/PowerShellScript --input ( + ConvertTo-Json -InputObject $instance +) +``` + +```Output + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Invoking get 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + INFO PID : Config file doesn't exist +actualState: + output: + - filePath: Temp:/dsc/examples/PowerShellScript/output.json + exists: false +``` + +The output shows that the configuration file doesn't exist. + +Next, invoke the **Set** operation to create the file: + +```powershell +dsc --trace-level info resource set --resource Microsoft.DSC.Transitional/PowerShellScript --input ( + ConvertTo-Json -InputObject $instance +) +``` + +```Output + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + INFO PID : Config file doesn't exist + INFO PID : Creating config file with specified settings + INFO PID : Performing the operation "Create File" on target "Destination: C:\Users\\AppData\Local\Temp\dsc\examples\PowerShellScript\output.json". + INFO diff: key 'updateAutomatically' is not an object + INFO diff: key 'updateFrequency' is not an object + INFO diff: key '_exist' is not an object + INFO diff: key 'lastWriteTime' missing + INFO diff: actual array missing expected item + INFO diff: arrays differ for 'output' +beforeState: + output: + - filePath: Temp:/dsc/examples/PowerShellScript/output.json + exists: false +afterState: + output: + - filePath: Temp:/dsc/examples/PowerShellScript/output.json + exists: true + settings: + updateAutomatically: true + updateFrequency: 30 + lastWriteTime: 2026-06-02T16:45:23.9746807-05:00 +changedProperties: +- output +``` + +The emitted messages show that the configuration file doesn't exist and the resource is creating +it. The `beforeState` is populated by the `getScript` and shows that the file doesn't exist. The +`afterState` then shows that the instance created the file with the expected settings and includes +the last write time. + +Invoking the **Set** operation again shows that the defined instance is idempotent: + +```powershell +dsc --trace-level info resource set --resource Microsoft.DSC.Transitional/PowerShellScript --input ( + ConvertTo-Json -InputObject $instance +) +``` + +```Output + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + INFO PID : Retrieving settings and last write time from config file + INFO PID : Processing setting 'updateAutomatically' with desired value `True` + INFO PID : Setting 'updateAutomatically' is already set to `True` + INFO PID : Processing setting 'updateFrequency' with desired value `30` + INFO PID : Setting 'updateFrequency' is already set to `30` + INFO PID : Config file is already in the desired state. No update needed. +beforeState: + output: + - filePath: Temp:/dsc/examples/PowerShellScript/output.json + exists: true + settings: + updateAutomatically: true + updateFrequency: 30 + lastWriteTime: 2026-06-02T16:45:23.9746807-05:00 +afterState: + output: + - filePath: Temp:/dsc/examples/PowerShellScript/output.json + exists: true + settings: + updateAutomatically: true + updateFrequency: 30 + lastWriteTime: 2026-06-02T16:45:23.9746807-05:00 +changedProperties: [] +``` + +The output in `beforeState` and `afterState` is identical and `changedProperties` is an empty +array. The emitted messages clarify that the instance checked each setting in the configuration +file and found them compliant to the desired state. + +Finally, update `input.settings` by: + +- Removing `updateAutomatically` +- Updating `updateFrequency` to `45` +- Adding `logLevel` as `info` + +Then invoke the resource again to see how the instance updates the configuration file. + +```powershell +$instance.input.settings.Remove('updateAutomatically') +$instance.input.settings.updateFrequency = 45 +$instance.input.settings.logLevel = 'info' + +dsc --trace-level info resource set --resource Microsoft.DSC.Transitional/PowerShellScript --input ( + ConvertTo-Json -InputObject $instance +) +``` + +```Output + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/PowerShellScript' using 'pwsh' + INFO PID : Retrieving settings and last write time from config file + INFO PID : Processing setting 'updateFrequency' with desired value `45` + INFO PID : Changing setting 'updateFrequency' from `30` to `45` + INFO PID : Processing setting 'logLevel' with desired value `info` + INFO PID : Adding setting 'logLevel' as `info` + INFO PID : Updating config file with new settings + INFO diff: key 'logLevel' missing + INFO diff: actual array missing expected item + INFO diff: arrays differ for 'output' +beforeState: + output: + - filePath: Temp:/dsc/examples/PowerShellScript/output.json + exists: true + settings: + updateAutomatically: true + updateFrequency: 30 + lastWriteTime: 2026-06-02T16:45:23.9746807-05:00 +afterState: + output: + - filePath: Temp:/dsc/examples/PowerShellScript/output.json + exists: true + settings: + updateAutomatically: true + updateFrequency: 45 + logLevel: info + lastWriteTime: 2026-06-02T16:53:39.2138244-05:00 +changedProperties: +- output +``` + +The emitted messages indicate that the instance only checked the `updateFrequency` and `logLevel` +settings - it didn't enforce `updateAutomatically`. The messages show that the instance updated +`updateFrequency` from `30` to `45` and added the missing `logLevel` setting. + +The result object again shows how `beforeState` differs from `afterState`, confirming that the +instance did modify system state. + + +[01]: ../index.md +[02]: /powershell/module/microsoft.powershell.core/about/about_output_streams#success-stream +[03]: /powershell/module/microsoft.powershell.utility/write-output +[04]: /powershell/module/microsoft.powershell.utility/write-output#-noenumerate +[05]: ../index.md#emitting-messages +[06]: ./invoke-with-messaging.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/psscript.config.dsc.yaml b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/psscript.config.dsc.yaml new file mode 100644 index 0000000..b3d6126 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/examples/psscript.config.dsc.yaml @@ -0,0 +1,105 @@ +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.vscode.json + +parameters: + motd: + type: string + defaultValue: "Hello, friend!" + minLength: 1 + maxLength: 100 + +resources: +- type: Microsoft.DSC.Transitional/PowerShellScript + name: Report processor info + properties: + getScript: |- + $count = [System.Environment]::ProcessorCount + $arch = [System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture + + [ordered]@{ + processorCount = $count + processorArchitecture = $arch.ToString() + } + setScript: |- + $count = [System.Environment]::ProcessorCount + $arch = [System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture + + [ordered]@{ + processorCount = $count + processorArchitecture = $arch.ToString() + } +- type: Microsoft.DSC.Transitional/PowerShellScript + name: Message of the Day + properties: + input: "[parameters('motd')]" + getScript: | + param($motd) + + $filePath = 'Temp:/example.motd' + + Write-Verbose "Checking for MOTD file at '$filePath'" + $result = [ordered]@{ + filePath = $filePath + exists = Test-Path -Path $filePath + } + + if ($result.exists) { + Write-Verbose "MOTD file found at '$filePath', retrieving content and last updated time" + $result.motd = (Get-Content -Path $filePath -Raw).TrimEnd("`r", "`n") + $result.lastUpdated = (Get-Item -Path $filePath).LastWriteTime + } else { + Write-Verbose "MOTD file not found at '$filePath'" + } + + $result + setScript: |- + param($motd) + + $filePath = 'Temp:/example.motd' + $result = [ordered]@{ + filePath = $filePath + exists = $true + motd = $motd + } + + if (-not (Test-Path -Path $filePath)) { + Write-Verbose "MOTD file not found at '$filePath', creating new file" + New-Item -Path $filePath -ItemType File -Force | Out-Null + Write-Verbose "MOTD file created at '$filePath', setting content" + $motd | Set-Content -Path $filePath -Force + } else { + Write-Verbose "MOTD file found at '$filePath', checking content" + $currentMotd = (Get-Content -Path $filePath -Raw).TrimEnd("`r", "`n") + if ($currentMotd -ne $motd) { + Write-Verbose "MOTD content differs from desired value, updating file" + $motd | Set-Content -Path $filePath -Force + } else { + Write-Verbose "MOTD content matches desired value, no update needed" + } + } + + $result.lastUpdated = (Get-Item -Path $filePath).LastWriteTime + + $result + testScript: |- + param($motd) + + $filePath = 'Temp:/example.motd' + + Write-Verbose "Checking for MOTD file at '$filePath'" + if (-not (Test-Path -Path $filePath)) { + Write-Verbose "MOTD file not found at '$filePath'" + return $false + } + + Write-Verbose "MOTD file found at '$filePath', retrieving content" + $currentMotd = Get-Content -Path $filePath -Raw + if ([string]::IsNullOrEmpty($currentMotd)) { + Write-Verbose "MOTD file at '$filePath' is empty" + return $false + } elseif ($currentMotd -ne $motd) { + Write-Verbose "Expected MOTD content '$motd' does not match actual content '$currentMotd'" + return $false + } + + Write-Verbose "MOTD content is the expected value '$motd'" + $true \ No newline at end of file diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/index.md new file mode 100644 index 0000000..39b4180 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/PowerShellScript/index.md @@ -0,0 +1,543 @@ +--- +description: Microsoft.DSC.Transitional/PowerShellScript resource reference documentation +ms.date: 07/07/2025 +ms.topic: reference +title: Microsoft.DSC.Transitional/PowerShellScript +--- + + + +# Microsoft.DSC.Transitional/PowerShellScript + +## Synopsis + +Enable running PowerShell 7 scripts inline. + +> [!IMPORTANT] +> The `Microsoft.DSC.Transitional/PowerShellScript` resource is intended as a temporary +> transitional resource while defining DSC resources for your needs. + +## Metadata + +```yaml +Version : 0.1.0 +Kind : resource +Tags : [Transitional, Windows, Linux, MacOS] +Author : Microsoft +``` + +## Instance definition syntax + +```yaml +resources: + - name: + type: Microsoft.DSC.Transitional/PowerShellScript + properties: + # Optional properties + getScript: string + setScript: string + testScript: string + input: anyOf # string, boolean, integer, object, array, null + output: array + _inDesiredState: boolean # or null +``` + +## Description + +The `Microsoft.DSC.Transitional/PowerShellScript` resource enables you to run PowerShell 7 scripts +inline as part of your DSC configuration. This resource is useful for executing PowerShell logic +that hasn't been fully transitioned to a dedicated DSC resource. + +The resource allows you to: + +- Define separate PowerShell scripts for **Get**, **Set**, and **Test** operations. +- Pass input data to the scripts. +- Receive output data from the scripts. +- Control the desired state behavior through the `_inDesiredState` property. + +The properties you define determine how the resource behaves. + +- If you don't define `getScript`, the `actualState` field in **Get** operation results and + `beforeState` field in **Set** operation results is always an empty object (`{}`). +- If you don't define `testScript`, the `inDesiredState` field for **Test** operation results is + always `true`. +- If you don't define `setScript`, the `afterState` field in **Set** operation results is always + an empty object (`{}`). +- If you define `input`, every script property you define _must_ start with a `param()` statement + that defines a single parameter. The value for `input` is _always_ passed to the scripts when the + resource invokes them. + + When the instance _doesn't_ define `input` the script properties must **not** include a `param()` + statement. + +> [!NOTE] +> This resource always invokes the script properties in PowerShell (`pwsh`). To define a resource +> instance with script properties that execute in Windows PowerShell (`powershell.exe`), see +> [`Microsoft.DSC.Transitional/WindowsPowerShellScript`][01]. + +### Defining script properties + +For an instance to be functional you must define one or more script properties: + +- Define `getScript` to retrieve actual system state with the **Get** operation or to show how the + instance modified the system during a **Set** operation. +- Define `testScript` to indicate whether the system is in the desired state with the **Test** + operation. + + > [!IMPORTANT] + > Version `0.1.0` of the resource does _not_ invoke the `testScript` to determine whether to + > invoke the `setScript`. The resource always invokes `setScript` for the **Set** operation. + > + > Ensure that you define the `setScript` to be idempotent or include a check before making any + > changes to the system to avoid unnecessary processing and unintended behaviors. + +- Define `setScript` to modify the system with the **Set** operation. You can use this resource to + define an instance that performs a specific task, such as warming a cache or clearing logs, or to + enforce a specific desired state for any number of system components. + + In either case, consider [emitting messages](#emitting-messages) to the user that helps them + understand what the instance is doing during an operation. + + If you are using the resource instance to enforce a specific desired state you should: + + 1. Emit one or more output objects representing the final state of the system components the + instance is modifying. + 1. Define `getScript` to emit the same data structures as output objects representing the actual + state of the system components the instance is managing. + + This ensures that the user can more easily compare the `beforeState` and `afterState` fields of + the **Set** operation result to see how the instance modified the system. + +The following subsections provide more information on input, error handling, output, and emitting +messages from within the script properties. + +#### Handling input + +To pass input to a script, you must: + +1. Define the script property with a `param()` statement that specifies a single parameter. + Omitting the `param()` statement, defining an empty `param()` statement, or defining more than + one parameter all cause the resource to fail. +1. Define the [`input`](#input) property for the resource instance with a non-null value. When you + omit the `input` property or define it with a null value, like `input: null`, the resource + raises an error causing the operation to fail. + +The data bound to the script parameter is the result of using the `ConvertFrom-Json` cmdlet on the +value for the `input` property of the resource instance. + +You can define the script parameter with a type, like `[string[]]` when the script expects the input +as an array of strings. PowerShell's normal parameter binding and type conversion behavior applies +to the script parameter. If the input data can't be converted to the defined type then the script +fails and raises an error indicating that the input data was invalid. + +You can also apply [validation attributes][02] to the parameter to further validate that the input +data is correct for your script. + +For detailed examples of using input data with this resource, see +[Invoke the PowerShellScript resource with input data][03]. + +#### Handling errors + +This resource invokes the PowerShell scripts with the [`$ErrorActionPreference` variable][04] set +to `Stop`. By default, _any_ error raised by the script, regardless of whether it's terminating, +stops script execution. + +You can control whether script execution continues on an error message in two ways: + +1. Specify the [`-ErrorAction` common parameter][05] for any command you expect to fail. Specify + the value for the parameter as `Continue` to emit the error message or `Ignore` to skip the + error message. In either case, execution will continue after the error. +1. Use a [`try`/`catch` statement][06] to add error handling for errors. When a statement in the + `try` block raises an error, the code in the `catch` block will execute before the code in the + `finally` block (if defined). Unless code in the `catch` or `finally` blocks raises an error, + the script will continue to execute. + +Providing error handling enables you to emit better information for users when something goes wrong +with the script behavior. + +However, even when you provide handling for errors, like using a `try`/`catch` statement or passing +`-ErrorAction Ignore` to a command you expect to fail, the resource considers the operation to have +failed. The resource doesn't populate the `output` property for failed scripts. + +There is no way with the current version of the resource for a script to raise any errors and _not_ +fail. You can only provide better diagnostics for the user in the event of a failure. + +For detailed examples of emitting errors from scripts, see ["Emitting errors"][07] in +[Invoke the PowerShellScript resource with trace messaging][08]. + +#### Returning output + +Any objects emitted by the script for an operation are converted to JSON with the `ConvertTo-Json` +cmdlet and appended to the `output` property array returned by the resource. The ordering of the +items in `output` is the same that they were emitted by the script. + +You can emit any number of items. You don't need to use any specific PowerShell cmdlet to emit +output for this resource. Any output from a PowerShell statement that isn't redirected or captured +as a variable is automatically included in the output. + +You can prevent statements from emitting output by assigning them to `$null`. For example, if your +script uses the `New-Item` cmdlet to create a file, the output for that command is emitted from +your script by default. To avoid emitting that data, you could use the following snippet: + +```powershell +$null = New-Item -Path $filePath +``` + +To provide more readable results to users, consider only emitting a single structured object from +both `getScript` and `setScript`. Emitting an object with descriptive property names makes it +easier to compare the `beforeState` and `afterState` fields for a **Set** operation result. Using +the same data structure also enables DSC to correctly determine the `changedProperties` field for +the **Set** operation result. If the output from `getScript` and `setScript` are identical then +`changedProperties` is an empty array. + +For `testScript`, be sure to _only_ and _always_ emit a single boolean value (`$true` or `$false`). +If `testScript` emits any non-boolean value, more than one boolean value, or no values at all then +the resource considers the operation to have failed and raises an error. + +For comprehensive examples showing how to emit and control output from scripts, see +[Invoke the PowerShellScript resource with output data][09]. + +#### Emitting messages + +The following table maps DSC's tracing levels to PowerShell output streams and `Write-*` cmdlets: + +| DSC trace level | PowerShell stream | PowerShell cmdlets | +|:---------------:|:-----------------:|:-----------------------------:| +| - | Success | `Write-Output` | +| `error` | Error | `Write-Error` | +| `warn` | Warning | `Write-Warning` | +| `info` | Verbose | `Write-Verbose`, `Write-Host` | +| `debug` | Debug | `Write-Debug` | +| `trace` | Information | `Write-Information` | + +> [!IMPORTANT] +> Remember that _any_ error emitted from the script causes the resource and DSC to consider the +> script execution to have failed, even when the script continued after an error. + +For comprehensive examples of emitting messages from scripts, see +[Invoke the PowerShellScript resource with trace messaging][08]. + +## Requirements + +- Using this adapter requires a supported version of PowerShell (`pwsh`) to be installed on the + system. + +## Capabilities + +The resource has the following capabilities: + +- `get` - You can use the resource to retrieve the actual state of an instance. +- `set` - You can use the resource to enforce the desired state for an instance. +- `test` - You can use the resource to test whether an instance is in the desired state. + +For more information about resource capabilities, see [DSC resource capabilities][00]. + +## Examples + +1. [Configure a system with the PowerShellScript resource][10] - Shows how to use this resource + in a configuration document. +1. [Invoke the PowerShellScript resource with input data][03] - Shows how to pass data to this + resource. +1. [Invoke the PowerShellScript resource with output data][09] - Shows how to return data from this + resource. +1. [Invoke the PowerShellScript resource with trace messaging][08] - Shows how to emit DSC trace + messages from this resource. + +## Properties + +The following list describes the properties for the resource. + +- **Instance properties:** The following properties are optional. + They define the desired state for an instance of the resource. + + - [getScript](#getscript) - The PowerShell script to run during the **Get** operation. + - [setScript](#setscript) - The PowerShell script to run during the **Set** operation. + - [testScript](#testscript) - The PowerShell script to run during the **Test** operation. + - [input](#input) - Input data to pass to the PowerShell scripts. + - [output](#output) - Output data returned from the PowerShell scripts. + - [_inDesiredState](#_indesiredstate) - Indicates whether the resource instance is in the desired + state. + +### getScript + +
Expand for getScript property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines the PowerShell script to execute during the **Get** operation. This property is never +returned by the resource. The resource invokes the script this property defines for the **Get** +operation and to populate the `beforeState` for a **Set** operation. + +This script should return the current state of the instance. The script can access input data and +should return relevant state information. _Every_ item the script emits to the PowerShell success +stream is inserted into the [`output`](#output) property. + +When possible, prefer emitting a single structured object to the success stream. This makes reading +the `actualState` for a **Get** operation result and the `beforeState` for a **Set** operation +result easier for users. + +### setScript + +
Expand for setScript property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines the PowerShell script to execute during the **Set** operation. This script should configure +the system to match the desired state. The script can access input data and should perform the +necessary changes to bring the system into compliance. + +If the instance defines the [`getScript`](#getscript) property to return data then this property +_should_ return data in the same order and structure. The result object for the **Set** operation +includes `beforeState` (populated by the output for `getScript`) and `afterState` (populated by the +output for `setScript`). Keeping the output order and structure the same for both scripts enables +easier comparison of the changes in resource state. + +### testScript + +
Expand for testScript property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines the PowerShell script to execute during the **Test** operation. This script should +determine whether the system is in the desired state and return appropriate state information. The +script can access input data and should return a single boolean value of `$true` or `$false`. + +The script should _not_ emit any other data for output. Emitting more data than a single boolean +value or emitting a non-boolean value causes the resource to raise an error. + +Instead, [emit messages](#emitting-messages) to indicate how and why the instance is out of the +desired state. + +> [!IMPORTANT] +> In version `0.1.0` for the resource, this script is _only_ invoked for the **Test** operation +> when you use the `dsc config test` or `dsc resource test` commands. When you invoke the **Set** +> operation the resource _always_ invokes the [`setScript`](#setscript) even when `testScript` +> would report that the resource is in the desired state. + +### input + +
Expand for input property metadata + +```yaml +Type : anyOf (string, boolean, integer, object, array, null) +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines input data to pass to the PowerShell scripts. This can be any of the following JSON data +types: + +- `string` +- `boolean` +- `integer` +- `object` +- `array` + +The input data is available to every script property and can be used to parameterize script +behavior. + +When passing input data to a script, always define the `params` keyword with a single named +parameter, like `params($inputData)`. The resource binds the value from the `input` property to +that parameter. + +The value for this property affects how it is passed to the PowerShell scripts for the resource: + +| JSON value type | Bound PowerShell parameter value | +|:---------------:|:--------------------------------:| +| `string` | `[String]` | +| `object` | `[PSCustomObject]` | +| `array` | `[Object[]]` | +| `integer` | `[Int64]` | +| `number` | Invalid † | +| `boolean` | `[Boolean]` | +| `null` | Invalid † | + +> [!NOTE] +> Passing a number with a fractional part, such as `1.23`, or `null` is invalid for the top-level +> value of the `input` field. However, you can pass numbers and `null` values nested as object +> properties or array items. +> +> For example, `input: 1.23` is invalid while `input: {"num": 1.23}` and `input: [1.23]` are valid. +> Similarly, `input: null` is invalid while `input: {nested: null}` and `input: [null]` are both +> valid. + +If you define your scriptblock parameters without providing a type for the input data, like +`params($inputData)`, the type for that parameter is exactly as described in the prior table. You +can also define a type for the parameter, which causes PowerShell to cast the input data to the +given type. For example, `params([string[]]$inputData)` will cast the value for `input` to an array +of strings. + +For comprehensive examples of how to use input data with this resource, see +[Invoking the PowerShellScript resource with input data][03]. + +### output + +
Expand for output property metadata + +```yaml +Type : array +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines output data returned from the PowerShell scripts. This property contains the results of +script execution and can include any data that the scripts choose to return. + +Every object emitted to the PowerShell success output stream is inserted into the `output` for the +operation in the order that the scriptblock emits those objects. The emitted items are +automatically converted to JSON values by the resource. Don't use the `ConvertTo-Json` cmdlet to +transform the items yourself. + +When emitting objects with nested properties the resource will emit the object up 9 levels deep. +Objects with more deep nesting fail to serialize correctly into JSON. + +Where possible, limit the output data to the value you need. You can use the `Select-Object` cmdlet +to select only the required properties or create a custom object to represent the output data. + +> [!IMPORTANT] +> This resource doesn't populate the `output` property for failed scripts. The resource considers +> a script to have failed when it emits _any_ errors, even when those errors are explicitly handled. +> For more information, see the [Handling errors](#handling-errors) section of this documentation. + +Using the `Write-*` cmdlets to emit messages to PowerShell's other output streams doesn't populate +the `output` property. Instead, those messages are surfaced through DSC's tracing. For more +information, see the [Emitting messages](#emitting-messages) section of this documentation. + +For comprehensive examples of how to return output data with this resource, see +[Invoking the PowerShellScript resource with output data][09]. + +### _inDesiredState + +
Expand for _inDesiredState property metadata + +```yaml +Type : boolean +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +DefaultValue : null +``` + +
+ +Indicates whether the resource is in the desired state. This property is only returned when a +caller invokes the **Test** operation for the resource. The value of this property depends on +whether the resource defines the [`testScript](#testscript) property: + +1. When the resource instance defines `testScript`, DSC invokes that script and uses the boolean + result it returns as the value of this property. +1. When the resource instance doesn't define `testScript`, the value is `true`. + +## Instance validating schema + +The following snippet contains the JSON Schema that validates an instance of the resource. + +```json +{ + "type": "object", + "properties": { + "getScript": { + "type": ["string", "null"] + }, + "setScript": { + "type": ["string", "null"] + }, + "testScript": { + "type": ["string", "null"] + }, + "input": { + "type": ["string", "boolean", "integer", "object", "array", "null"] + }, + "output": { + "type": ["array", "null"] + }, + "_inDesiredState": { + "type": ["boolean", "null"], + "default": null + } + }, + "additionalProperties": false +} +``` + +## Exit codes + +The resource returns the following exit codes from operations: + +- [0](#exit-code-0) - Success +- [1](#exit-code-1) - PowerShell script execution failed +- [2](#exit-code-2) - PowerShell exception occurred +- [3](#exit-code-3) - Script had errors + +### Exit code 0 + +Indicates the resource operation completed without errors. + +### Exit code 1 + +Indicates the PowerShell script execution failed. When the resource returns this exit code, it also +emits an error message with details about the execution failure. + +### Exit code 2 + +Indicates a PowerShell exception occurred during script execution. When the resource returns this +exit code, it writes the error to the console. + +### Exit code 3 + +Indicates the script had errors, typically due to missing or invalid input data. This exit code is +commonly returned when required input parameters are not provided to the PowerShell scripts or when +the input data is in an unexpected format. + +## See also + +- [Microsoft.DSC.Transitional/RunCommandOnSet][12] +- [Microsoft.DSC.Transitional/WindowsPowerShellScript][13] + + +[00]: ../../../../../../concepts/resources/capabilities.md +[01]: ../WindowsPowerShellScript/index.md +[02]: /powershell/module/microsoft.powershell.core/about/about_functions_advanced_parameters#parameter-and-variable-validation-attributes +[03]: ./examples/invoke-with-input-data.md +[04]: /powershell/module/microsoft.powershell.core/about/about_preference_variables#erroractionpreference +[05]: /powershell/module/microsoft.powershell.core/about/about_commonparameters#-erroraction +[06]: /powershell/module/microsoft.powershell.core/about/about_try_catch_finally +[07]: ./examples/invoke-with-messaging.md#emitting-errors +[08]: ./examples/invoke-with-messaging.md +[09]: ./examples/invoke-with-output-data.md +[10]: ./examples/configure-with-script.md +[12]: ../RunCommandOnSet/index.md +[13]: ../WindowsPowerShellScript/index.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/RunCommandOnSet/examples/run-a-simple-command.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/RunCommandOnSet/examples/run-a-simple-command.md new file mode 100644 index 0000000..ecaa5e6 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/RunCommandOnSet/examples/run-a-simple-command.md @@ -0,0 +1,54 @@ +--- +description: > + Example showing how you can invoke the Microsoft.DSC.Transitional/RunCommandOnSet resource with DSC to run a simple command. + +ms.date: 06/30/2025 +ms.topic: reference +title: Run a simple command +--- + +# Run a simple command + +This example shows how you can use the `Microsoft.DSC.Transitional/RunCommandOnSet` resource to +execute a simple command during the **Set** operation. + +## Run the command + +The following snippet shows how you can invoke the resource to execute a custom command with +[dsc resource set][00]. + +```powershell +$instance = @{ + executable = "C:\Windows\system32\cmd.exe" + arguments = @( + '/C', + 'echo Hello world' + ) +} | ConvertTo-Json +dsc resource set --resource Microsoft.DSC.Transitional/RunCommandOnSet --input $instance +``` + +When the resource runs the command, DSC returns a result similar to: + +```yaml +beforeState: + executable: cmd + arguments: + - /C + - echo + - Hello world +afterState: + executable: cmd + arguments: + - /C + - echo + - Hello world +changedProperties: [] +``` + +> [!NOTE] +> The output from the command executed by the `runCommandOnSet` resource isn't displayed in the +> console. If you want to capture the output, you should redirect it to a file. + + +[00]: ../../../../../../cli/resource/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/RunCommandOnSet/examples/run-powershell-command.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/RunCommandOnSet/examples/run-powershell-command.md new file mode 100644 index 0000000..9dd90c5 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/RunCommandOnSet/examples/run-powershell-command.md @@ -0,0 +1,78 @@ +--- +description: > + Example showing how you can invoke the Microsoft.DSC.Transitional/RunCommandOnSet resource with DSC to + run a PowerShell command. +ms.date: 06/30/2025 +ms.topic: reference +title: Run a PowerShell command +--- + +# Run a PowerShell command + +This example shows how you can use the `Microsoft.DSC.Transitional/RunCommandOnSet` resource to +execute a PowerShell command during the **Set** operation. + +## Define the PowerShell command to run + +The following snippet shows how you can define a PowerShell command to run during the DSC **Set** +operation: + +```powershell +$command = "Write-Output Hello | Out-File $env:TEMP\hello.txt" +$instance = @{ + executable = "powershell.exe" + arguments = @( + "-Command", + $command + ) +} | ConvertTo-Json + +dsc resource set --resource Microsoft.DSC.Transitional/RunCommandOnSet --input $instance +``` + +To verify the results, run the following command: + +```powershell +Get-Content -Path $env:TEMP\hello.txt +``` + +This should return: + +```text +Hello +``` + +## Run the PowerShell command in a configuration document + +You can also include this resource in a DSC configuration document: + +```powershell +$command = "if ((Get-Command -Name winget -CommandType Application -ErrorAction Ignore)) {winget install --id Microsoft.PowerShell.Preview}" +$document = @" +`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: + - name: RunPowerShellCommand + type: Microsoft.DSC.Transitional/RunCommandOnSet + properties: + executable: "powershell.exe" + arguments: + - "-Command" + - $command + exitCode: 0 +"@ +``` + +Apply the configuration document with the [dsc config set][00] command: + +```powershell +dsc config set --input $document +``` + +To verify the result, you can run the `winget.exe` command: + +```powershell +winget list --id Microsoft.PowerShell.Preview +``` + + +[00]: ../../../../../../cli/config/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/RunCommandOnSet/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/RunCommandOnSet/index.md new file mode 100644 index 0000000..104bc74 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/RunCommandOnSet/index.md @@ -0,0 +1,183 @@ +--- +description: Microsoft.DSC.Transitional/RunCommandOnSet resource reference documentation +ms.date: 06/30/2025 +ms.topic: reference +title: Microsoft.DSC.Transitional/RunCommandOnSet +--- + +# Microsoft.DSC.Transitional/RunCommandOnSet + +## Synopsis + +Execute a command during DSC **Set** operation. + +> [!IMPORTANT] +> The `runcommandonset` command and `Microsoft.DSC.Transitional/RunCommandOnSet` resource +> is intended as a temporary transitional resource while migrating DSCv3 resources for +> your needs. + +## Metadata + +```yaml +Version : 0.1.0 +Kind : resource +Tags : [Transitional, Windows, Linux, MacOS] +Author : Microsoft +``` + +## Instance definition syntax + +```yaml +resources: + - name: + type: Microsoft.DSC.Transitional/RunCommandOnSet + properties: + # Required properties + executable: string + # Optional properties + arguments: array + exitCode: integer +``` + +## Description + +The `Microsoft.DSC.Transitional/RunCommandOnSet` resource enables you to run a specified executable +command during the DSC **Set** operation. This is useful for commands that need to run as part of +your configuration, but haven't fully transitioned to a DSC resource. + +The resource allows you to: + +- Specify an executable to run +- Pass arguments to the executable +- Define a custom exit code to indicate success + +> [!IMPORTANT] +> The **Get** operation for this resource does not return any output from the executed command. +> Additionally, when using the **Test** operation, the resource always reports as being +> in the desired state. DSC _always_ invokes the command during **Set**. + +## Capabilities + +The resource has the following capabilities: + +- `get` - You can use the resource to retrieve the actual state of an instance. +- `set` - You can use the resource to enforce the desired state for an instance. + +This resource uses the synthetic test functionality of DSC to determine whether an instance is in +the desired state. For more information about resource capabilities, see +[DSC resource capabilities][00]. + +## Examples + +1. [Run a simple command][01] - Shows how to run a simple command. +1. [Run a PowerShell command][02] - Shows how you can run a PowerShell command. + +## Properties + +The following list describes the properties for the resource. + +- **Required properties:** The following properties are always + required when defining an instance of the resource. An instance that doesn't define each of these + properties is invalid. + + - [executable](#executable) - The executable to run on set. + +- **Instance properties:** The following properties are optional. + They define the desired state for an instance of the resource. + + - [arguments](#arguments) - The argument(s), if any, to pass to the executable that runs on get or + set. + - [exitCode](#exitcode) - The expected exit code to indicate success, if non-zero. Default is zero + for success. + +### executable + +
Expand for executable property metadata + +```yaml +Type : string +IsRequired : true +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines the executable program or command to run during the DSC **Set** operation. +This can be any valid executable file or command accessible from the system PATH. + +### arguments + +
Expand for arguments property metadata + +```yaml +Type : array +ItemsType : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines the arguments to pass to the executable. Each element in the array represents a +separate argument that will be passed to the executable. The arguments are passed +in the same order that you specify them. + +### exitCode + +
Expand for exitCode property metadata + +```yaml +Type : integer +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +DefaultValue : 0 +``` + +
+ +Defines the expected exit code to indicate success if not zero. By default, an exit code of `0` +indicates successful execution. If your executable returns a different exit code to indicate +success, specify that value here. + +## Instance validating schema + +The following snippet contains the JSON Schema that validates an instance of the resource. + +```json +{ + "type": "object", + "required": [ + "executable" + ], + "properties": { + "arguments": { + "title": "The argument(s), if any, to pass to the executable that runs on set", + "type": "array" + }, + "executable": { + "title": "The executable to run on set", + "type": "string" + }, + "exitCode": { + "title": "The expected exit code to indicate success, if non-zero. Default is zero for success.", + "type": "integer" + } + }, + "additionalProperties": false +} +``` + +## See also + +- [Microsoft.DSC.PowerShell](../../PowerShell/index.md) +- [Microsoft.Windows.WindowsPowerShell](../../../../Microsoft/Windows/WindowsPowerShell/index.md) + +[00]: ../../../../../../concepts/resources/capabilities.md +[01]: ./examples/run-a-simple-command.md +[02]: ./examples/run-powershell-command.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/configure-with-script.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/configure-with-script.md new file mode 100644 index 0000000..f6f4880 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/configure-with-script.md @@ -0,0 +1,310 @@ +--- +description: > + Example showing how to use the WindowsPowerShellScript resource in a DSC + configuration document. +ms.date: 05/10/2026 +ms.topic: reference +title: Configure a system with the WindowsPowerShellScript resource +--- + + + +# Configure a system with the WindowsPowerShellScript resource + +This example shows how you can use the [`Microsoft.DSC.Transitional/WindowsPowerShellScript`][01] +resource in a configuration both to invoke non-idempotent scripts and to idempotently manage a +message of the day file that doesn't have a specific DSC resource. + +## Definition + +The configuration document for this example defines two instances of the resource: + +1. The first instance, `Report processor info`, returns the number of processor cores and the + processor architecture from both `getScript` and `setScript`. This instance is informational + only - it doesn't modify the system. +1. The second instance, `Message of the Day`, idempotently manages a message of the day file. It + uses `input` to define the contents of the file and pulls the value for the input from the + `parameters` definition. It defines all three script properties: `getScript` to return the + actual state, `testScript` to determine if the instance is in the desired state, and `setScript` + to enforce the desired state. + + The `getScript` and `setScript` definitions return the same structured output representing the + state of the MOTD file to make monitoring how the instance modifies the system easier. All three + script definitions use the `Write-Verbose` cmdlet to emit informational messages about what the + instance is doing. In particular the messages from `testScript` describe whether and how the + file isn't in the desired state to address the limited information the script can surface in its + output. + +:::code language="yaml" source="winpsscript.config.dsc.yaml"::: + +Copy the configuration document and save it as `winpsscript.config.dsc.yaml`. + +## Get the current state + +To retrieve the current state of the system, use the [dsc config get][02] command on the +configuration document. + +```powershell +dsc --trace-level info config get --file ./winpsscript.config.dsc.yaml +``` + +```Messages + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Invoking get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + INFO Invoking get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + INFO PID : Checking for MOTD file at 'Temp:/example.motd' + INFO PID : MOTD file not found at 'Temp:/example.motd' +``` + +```yaml +executionInformation: + # Elided for brevity +metadata: + Microsoft.DSC: + # Elided for brevity +results: +- executionInformation: + duration: PT1.2985379S + metadata: + Microsoft.DSC: + duration: PT1.2985379S + name: Report processor info + type: Microsoft.DSC.Transitional/WindowsPowerShellScript + result: + actualState: + output: + - processorCount: 8 + processorArchitecture: X64 +- executionInformation: + duration: PT0.9556133S + metadata: + Microsoft.DSC: + duration: PT0.9556133S + name: Message of the Day + type: Microsoft.DSC.Transitional/WindowsPowerShellScript + result: + actualState: + output: + - filePath: Temp:/example.motd + exists: false +messages: [] +hadErrors: false +``` + +The command emitted messages to stderr and the result to stdout. The messages include informational +messages from `getScript` for the message of the day instance indicating that the script looked for +but did not find the MOTD file. + +The result includes structured output from both instances: + +- The processor report instance shows that the system has `8` cores and is an `X64` architecture. +- The message of the day instance shows that the expected MOTD file doesn't exist at + `Temp:/example.motd`. + +## Enforce the desired state + +To update the system to the desired state, use the [dsc config set][03] command on the +configuration document. + +```powershell +dsc --trace-level info config set --file ./winpsscript.config.dsc.yaml +``` + +```Messages + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + INFO PID : Checking for MOTD file at 'Temp:/example.motd' + INFO PID : MOTD file not found at 'Temp:/example.motd' + INFO PID : MOTD file not found at 'Temp:/example.motd', creating new file + INFO PID : MOTD file created at 'Temp:/example.motd', setting content + INFO diff: key 'motd' missing + INFO diff: key 'lastUpdated' missing + INFO diff: actual array missing expected item + INFO diff: arrays differ for 'output +``` + +```yaml +executionInformation: + # Elided for brevity +metadata: + Microsoft.DSC: + # Elided for brevity +results: +- executionInformation: + duration: PT2.1871641S + metadata: + Microsoft.DSC: + duration: PT2.1871641S + name: Report processor info + type: Microsoft.DSC.Transitional/WindowsPowerShellScript + result: + beforeState: + output: + - processorCount: 8 + processorArchitecture: X64 + afterState: + output: + - processorCount: 8 + processorArchitecture: X64 + changedProperties: [] +- executionInformation: + duration: PT1.708226S + metadata: + Microsoft.DSC: + duration: PT1.708226S + name: Message of the Day + type: Microsoft.DSC.Transitional/WindowsPowerShellScript + result: + beforeState: + output: + - exists: false + filePath: Temp:/example.motd + afterState: + output: + - exists: true + motd: Hello, friend! + filePath: Temp:/example.motd + lastUpdated: 2026-06-02T18:05:16.8811712-05:00 + changedProperties: + - output +messages: [] +hadErrors: false +``` + +As before, the message of the day instance surfaces informational messages. The messages show that +the MOTD file wasn't found and then the `setScript` reports that it is creating the file and +setting the content. + +It's easier to review the result data for each instance separately: + +- ```yaml + name: Report processor info + type: Microsoft.DSC.Transitional/WindowsPowerShellScript + result: + beforeState: + output: + - processorCount: 8 + processorArchitecture: X64 + afterState: + output: + - processorCount: 8 + processorArchitecture: X64 + changedProperties: [] + ``` + + The processor info report shows the same state for the system before and after the **Set** + operation. If the instance didn't define `setScript` then `afterState` would be an empty object + (`{}`) and the `changedProperties` field would report that `output` was modified. Providing + identical output for the `setScript` ensures that the result doesn't imply any system changes. + +- ```yaml + name: Message of the Day + type: Microsoft.DSC.Transitional/WindowsPowerShellScript + result: + beforeState: + output: + - exists: false + filePath: Temp:/example.motd + afterState: + output: + - exists: true + motd: Hello, friend! + filePath: Temp:/example.motd + lastUpdated: 2026-06-02T18:05:16.8811712-05:00 + changedProperties: + - output + ``` + + The result for the message of the day instance shows that `exists` changed from `false` to `true`. + The `afterState` also includes the `motd` property showing the newly-set MOTD and reports the + last updated time for the file. + +If you invoke the **Set** operation for the configuration again you should see that neither instance +modifies the system: + +```powershell +dsc --trace-level info config set --file ./winpsscript.config.dsc.yaml +``` + +```Messages + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + INFO PID : Checking for MOTD file at 'Temp:/example.motd' + INFO PID : MOTD file found at 'Temp:/example.motd', retrieving content and last updated time + INFO PID : MOTD file found at 'Temp:/example.motd', checking content + INFO PID : MOTD content matches desired value, no update needed +``` + +```yaml +executionInformation: + # Elided for brevity +metadata: + Microsoft.DSC: + # Elided for brevity +results: +- executionInformation: + duration: PT3.8028321S + metadata: + Microsoft.DSC: + duration: PT3.8028321S + name: Report processor info + type: Microsoft.DSC.Transitional/WindowsPowerShellScript + result: + beforeState: + output: + - processorCount: 8 + processorArchitecture: X64 + afterState: + output: + - processorCount: 8 + processorArchitecture: X64 + changedProperties: [] +- executionInformation: + duration: PT2.6216447S + metadata: + Microsoft.DSC: + duration: PT2.6216447S + name: Message of the Day + type: Microsoft.DSC.Transitional/WindowsPowerShellScript + result: + beforeState: + output: + - filePath: Temp:/example.motd + motd: Hello, friend! + exists: true + lastUpdated: 2026-06-03T08:46:38.0491245-05:00 + afterState: + output: + - motd: Hello, friend! + exists: true + lastUpdated: 2026-06-03T08:46:38.0491245-05:00 + filePath: Temp:/example.motd + changedProperties: [] +messages: [] +hadErrors: false +``` + +## Cleanup + +To return your system to its original state, invoke the following Windows PowerShell command to +remove the MOTD file from the `Temp:/` folder: + +```powershell +Remove-Item -Path 'Temp:/example.motd' -Verbose +``` + + +[01]: ../index.md +[02]: ../../../../../../cli/config/get.md +[03]: ../../../../../../cli/config/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/invoke-with-input-data.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/invoke-with-input-data.md new file mode 100644 index 0000000..bac64c5 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/invoke-with-input-data.md @@ -0,0 +1,469 @@ +--- +description: > + Example showing how to pass input data to a WindowsPowerShellScript resource + and access properties, array elements, and nested values inside the script. +ms.date: 05/10/2026 +ms.topic: reference +title: Invoke the WindowsPowerShellScript resource with input data +--- + + + +# Invoke the WindowsPowerShellScript resource with input data + +These examples show how you can pass input data to the +[`Microsoft.DSC.Transitional/WindowsPowerShellScript` resource][01] and how to bind that data to +your script with a [`param()` statement][02]. + +## Input data types + +The following examples show how data input is bound to the parameters for a defined scriptblock +when the parameter isn't defined with a specific type. + +The data that the resource passes to a script is first converted from the JSON input that DSC sends +with the [`ConvertFrom-Json` cmdlet][03]. + +### Passing string input data + +When you define `input` as a string value, the parameter for the script is a `[string]` object. + +```powershell +$instance = @' +input: hello world +getScript: |- + param($inputData) + + [ordered]@{ + boundDataType = "[$($inputData.GetType().FullName)]" + boundDataValue = $inputData + } +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - boundDataType: '[System.String]' + boundDataValue: hello world +``` + +### Passing integer input data + +When you define `input` as an integer value, the parameter for the script is an `[Int64]` value. + +```powershell +$instance = @' +input: 10 +getScript: |- + param($inputData) + + [ordered]@{ + boundDataType = "[$($inputData.GetType().FullName)]" + boundDataValue = $inputData + } +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - boundDataType: '[System.Int64]' + boundDataValue: 10 +``` + +### Passing boolean input data + +When you define `input` as a boolean value, the parameter for the script is a `[Boolean]` value. + +```powershell +$instance = @' +input: true +getScript: |- + param($inputData) + + [ordered]@{ + boundDataType = "[$($inputData.GetType().FullName)]" + boundDataValue = $inputData + } +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - boundDataType: '[System.Boolean]' + boundDataValue: true +``` + +### Passing array input data + +When you define `input` as a string value, the parameter for the script is a `[Object[]]` array. +The items in the array are data types as emitted by the [`ConvertFrom-Json` cmdlet][03]. + +```powershell +$instance = @' +input: +- hello world +- 10 +- 1.23 +- true +- null +- nested: object +- - nested + - array +getScript: |- + param($inputData) + + $inputData | ForEach-Object -Begin { $i = 0 } -Process { + [ordered]@{ + boundDataItemIndex = $i + boundDataItemType = if ($null -eq $_) { + '$null' + } else { + "[$($_.GetType().FullName)]" + } + boundDataItemValue = $_ + } + $i++ + } +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - boundDataItemIndex: 0 + boundDataItemType: '[System.String]' + boundDataItemValue: hello world + - boundDataItemIndex: 1 + boundDataItemType: '[System.Int64]' + boundDataItemValue: 10 + - boundDataItemIndex: 2 + boundDataItemType: '[System.Double]' + boundDataItemValue: 1.23 + - boundDataItemIndex: 3 + boundDataItemType: '[System.Boolean]' + boundDataItemValue: true + - boundDataItemIndex: 4 + boundDataItemType: $null + boundDataItemValue: null + - boundDataItemIndex: 5 + boundDataItemType: '[System.Management.Automation.PSCustomObject]' + boundDataItemValue: + nested: object + - boundDataItemIndex: 6 + boundDataItemType: '[System.Object[]]' + boundDataItemValue: + - nested + - array +``` + +### Passing object input data + +When you define `input` as an object value, the parameter for the script is a `[pscustomobject]`. +The values for each property of the object are data types as emitted by the +[`ConvertFrom-Json` cmdlet][03]. + +```powershell +$instance = @' +input: + string: hello world + integer: 10 + number: 1.23 + boolean: true + "null": null + nestedObject: + foo: bar + nestedArray: + - nested + - array +getScript: |- + param($inputData) + + $inputData.psobject.Properties | ForEach-Object -Process { + [ordered]@{ + boundDataPropertyName = $_.Name + boundDataPropertyType = "[$($_.TypeNameOfValue)]" + boundDataPropertyValue = $_.Value + } + } +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - boundDataPropertyName: string + boundDataPropertyType: '[System.String]' + boundDataPropertyValue: hello world + - boundDataPropertyName: integer + boundDataPropertyType: '[System.Int64]' + boundDataPropertyValue: 10 + - boundDataPropertyName: number + boundDataPropertyType: '[System.Double]' + boundDataPropertyValue: 1.23 + - boundDataPropertyName: boolean + boundDataPropertyType: '[System.Boolean]' + boundDataPropertyValue: true + - boundDataPropertyName: 'null' + boundDataPropertyType: '[System.Object]' + boundDataPropertyValue: null + - boundDataPropertyName: nestedObject + boundDataPropertyType: '[System.Management.Automation.PSCustomObject]' + boundDataPropertyValue: + foo: bar + - boundDataPropertyName: nestedArray + boundDataPropertyType: '[System.Object[]]' + boundDataPropertyValue: + - nested + - array +``` + +## Casting input data + +When you define the parameters for a scriptblock, you can specify a type for the input data. The +script uses PowerShell's [parameter type conversion][04] to try to convert the input +data. If the type conversion is impossible for the input data, PowerShell raises an error and the +operation fails. + +The following example shows how you can convert the input data to a given type. In this case, it +converts every item in the input data into a `[datetime]` object. + +```powershell +$instance = @' +input: + - 2026-01-02 + - 01/20/2026 +getScript: |- + param([datetime[]]$inputData) + + $inputData | ForEach-Object { + [ordered]@{ + InputDate = $_ + NextDate = $_.AddDays(1) + } + } +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - InputDate: 2026-01-02T00:00:00 + NextDate: 2026-01-03T00:00:00 + - InputDate: 2026-01-20T00:00:00 + NextDate: 2026-01-21T00:00:00 +``` + +## Input related errors + +Passing input to a script has several requirements: + +1. The script property for the resource must use the `param()` statement to define exactly one + parameter. +1. The `input` property for the resource must be defined with a non-null value. +1. If the `param()` statement defines a type for the input data, the value for the `input` property + of the instance must be convertible to that type. + +The resource raises an error and prevents the script from executing when any of these requirements +aren't met by the resource instance definition. + +### Error: input provided but script has no parameters + +If you provide a value for `input` but the script does not define a `param()` statement, the +resource exits with code `2` and emits the following error message: + +```plaintext +Input was provided but script does not have a parameter to accept input. +``` + +```powershell +$instance = @' +getScript: | + "Script without parameters" +input: oops +'@ + +dsc resource get --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input $instance +``` + +```Output + ERROR PID : Input was provided but script does not have a parameter to accept input. + ERROR Failed to run process 'powershell': Command: Resource 'powershell' [exit code 1] manifest description: PowerShell script execution failed + ERROR Command: Resource 'powershell' [exit code 1] manifest description: PowerShell script execution failed +``` + +### Error: Script defines a parameter but no input provided + +If the script defines a `param()` statement but no `input` is specified for the instance, the +resource exits with code `2` and emits the following error message: + +```plaintext +Script has a parameter '' but no input was provided. +``` + +```powershell +$instance = @' +getScript: | + param($inputObj) + "This will not run" +'@ + +dsc resource get --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input $instance +``` + +```Output + ERROR PID : Script has a parameter 'inputObj' but no input was provided. + ERROR Failed to run process 'powershell': Command: Resource 'powershell' [exit code 1] manifest description: PowerShell script execution failed + ERROR Command: Resource 'powershell' [exit code 1] manifest description: PowerShell script execution failed +``` + +### Error: Script defines more than one parameter + +If the script defines a `param()` statement with two or more parameters, the resource exits with +code `1` and emits the following error message: + +```plaintext +Script must have exactly one parameter. +``` + +```powershell +$instance = @' +input: +- first +- second +getScript: |- + param($a, $b) + + [ordered]@{ + a = $a + b = $b + } +'@ + +dsc resource get --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input $instance +``` + +```Output + ERROR PID 23764: Script must have exactly one parameter. + ERROR Failed to run process 'powershell': Command: Resource 'powershell' [exit code 1] manifest description: PowerShell script execution failed + ERROR Command: Resource 'powershell' [exit code 1] manifest description: PowerShell script execution failed +``` + +### Error: Script defines a typed parameter but input is invalid + +If the script defines the `param()` statement with a parameter that has a defined type that the +input data can't convert into, the resource raises an error message about an argument +transformation failure. + +```powershell +$instance = @' +input: foo +getScript: |- + param([int]$inputData) + + $inputData +'@ + +dsc resource get --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input $instance +``` + +```Output + ERROR PID : Exception calling "EndInvoke" with "1" argument(s): "Cannot process argument transformation on parameter 'inputData'. Cannot convert value "foo" to type "System.Int32". Error: "The input string 'foo' was not in a correct format."" + ERROR Failed to run process 'powershell': Command: Resource 'powershell' [exit code 1] manifest description: PowerShell script execution failed + ERROR Command: Resource 'powershell' [exit code 1] manifest description: PowerShell script execution failed +``` + +## Using input in a configuration document + +You can pass input to a `WindowsPowerShellScript` instance inside a DSC configuration document, +including values from configuration parameters. The following configuration uses the +[dsc config get][05] command to pass a port number into the script: + +```yaml +# check-port.dsc.yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +parameters: + port: + type: int + defaultValue: 8080 +resources: + - name: checkPort + type: Microsoft.DSC.Transitional/WindowsPowerShellScript + properties: + getScript: | + param($inputObj) + Write-Information "Checking port $($inputObj.port)..." + Test-NetConnection -ComputerName localhost -Port $inputObj.port | + Select-Object -ExpandProperty TcpTestSucceeded + input: + port: "[parameters('port')]" +``` + +```powershell +dsc config get --file check-port.dsc.yaml +``` + +```yaml +executionInformation: + # Elided for brevity +metadata: + # Elided for brevity +results: +- executionInformation: + duration: PT12.3218732S + metadata: + Microsoft.DSC: + duration: PT12.3218732S + name: checkPort + type: Microsoft.DSC.Transitional/WindowsPowerShellScript + result: + actualState: + output: + - false +messages: [] +hadErrors: false +``` + + +[01]: ../index.md +[02]: /powershell/module/microsoft.powershell.core/about/about_functions_advanced_parameters#parameter-declaration +[03]: /powershell/module/microsoft.powershell.utility/convertfrom-json +[04]: /powershell/module/microsoft.powershell.core/about/about_functions_advanced_parameters#type-conversion-of-parameter-values +[05]: ../../../../../../cli/config/get.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/invoke-with-messaging.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/invoke-with-messaging.md new file mode 100644 index 0000000..27644e4 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/invoke-with-messaging.md @@ -0,0 +1,520 @@ +--- +description: > + Example showing how to emit trace messages from a WindowsPowerShellScript + resource. +ms.date: 05/10/2026 +ms.topic: reference +title: Invoke the WindowsPowerShellScript resource with trace messaging +--- + + + +# Invoke the WindowsPowerShellScript resource with trace messaging + +These examples show how you can emit messages from the +[`Microsoft.DSC.Transitional/WindowsPowerShellScript` resource][01]. + +## Emitting errors + +By default, any errors raised during script execution cause the execution to emit the error message +and immediately halt script execution. The following example snippets show how you can provide +error details for the user when a script fails. + +### Emitting an error from a failed cmdlet + +In this example, the script depends on the `tstoy` command being available on the system. When the +command isn't available, the script fails and reports the error. + +```powershell +$instance = @' +getScript: |- + $tstoyCmd = Get-Command -Name tstoy -CommandType Application | + Select-Object -ExpandProperty Path + + & $tstoyCmd version --full --format json | ConvertFrom-Json +'@ + +dsc resource get --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input $instance +``` + +```Output + ERROR PID : Exception calling "EndInvoke" with "1" argument(s): "The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: The term 'tstoy' is not recognized as a name of a cmdlet, function, script file, or executable program. +Check the spelling of the name, or if a path was included, verify that the path is correct and try again." + ERROR Failed to run process 'powershell': Command: Resource 'powershell' [exit code 1] manifest description: PowerShell script execution failed + ERROR Command: Resource 'powershell' [exit code 1] manifest description: PowerShell script execution failed +``` + +The first error in the output indicates that the script execution was stopped by the error from the +`Get-Command` invocation, which showed that `tstoy` wasn't available on the system. + +### Emitting errors with `Write-Error` + +Instead of raising the default error from a failed command, you can use the [`Write-Error`][02] +cmdlet to emit a specific error message. In this example, the script depends on the `tstoy` command +being available on the system. When the command isn't available, the script fails and reports the +error. + +```powershell +$instance = @' +getScript: |- + $tstoyCmd = Get-Command -Name tstoy* -CommandType Application | + Where-Object {$_.Name -match 'tstoy(\.exe)?' } | + Select-Object -ExpandProperty Path + if ([string]::IsNullOrEmpty($tstoyCmd)) { + Write-Error "command 'tstoy' not found; unable to report version for 'tstoy'" + } + + & $tstoyCmd version --full --format json | ConvertFrom-Json +'@ + + +dsc resource get --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input $instance +``` + +```Output + ERROR PID : Exception calling "EndInvoke" with "1" argument(s): "The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: command 'tstoy' not found; unable to report version for 'tstoy'" + ERROR Failed to run process 'powershell': Command: Resource 'powershell' [exit code 1] manifest description: PowerShell script execution failed + ERROR Command: Resource 'powershell' [exit code 1] manifest description: PowerShell script execution failed +``` + +The first error in the output indicates that the script execution was stopped and includes the +message emitted from the `Write-Error` command. + +### Throwing an error from a `catch` block + +In the previous error examples, the emitted error includes information about execution stopping +because of the error action preference being set to stop. You can make the error message clearer +by rethrowing the underlying exception from a the `catch` block in a [`try`/`catch` statement][03]. + +```powershell +$instance = @' +getScript: |- + try { + $tstoyCmd = Get-Command -Name tstoy -CommandType Application | + Select-Object -ExpandProperty Path + + & $tstoyCmd version --full --format json | ConvertFrom-Json + } catch { + throw $_.Exception + } +'@ + +dsc resource get --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input $instance +``` + +```Output + ERROR PID : Exception calling "EndInvoke" with "1" argument(s): "The term 'tstoy' is not recognized as a name of a cmdlet, function, script file, or executable program. +Check the spelling of the name, or if a path was included, verify that the path is correct and try again." + ERROR Failed to run process 'powershell': Command: Resource 'powershell' [exit code 1] manifest description: PowerShell script execution failed + ERROR Command: Resource 'powershell' [exit code 1] manifest description: PowerShell script execution failed +``` + +## Emitting warning messages + +You can emit warning messages from a script with the [`Write-Warning`][04] cmdlet. + +This example shows how you can emit a warning from a script without halting execution. The script +looks for the `tstoy` command and returns the version information for that command if it exists. If +the command isn't available, the script raises a warning and returns no output data. + +```powershell +$instance = @' +getScript: |- + $tstoyCmd = Get-Command -Name tstoy* -CommandType Application | + Where-Object {$_.Name -match 'tstoy(\.exe)?' } | + Select-Object -ExpandProperty Path + + if ([string]::IsNullOrEmpty($tstoyCmd)) { + Write-Warning "command 'tstoy' not found; unable to report version for 'tstoy'" + } else { + & $tstoyCmd version --full --format json | ConvertFrom-Json + } +'@ + + +dsc resource get --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input $instance +``` + +```Output + WARN PID : command 'tstoy' not found; unable to report version for 'tstoy' +actualState: + output: [] +``` + +## Emitting info messages + +You can emit `info` level messages for DSC with the [`Write-Verbose`][05] and [`Write-Host`][06] +cmdlets. When a cmdlet used in your script emits verbose or information messages, you can use the +[`-Verbose` common parameter][07] or specify the [`-InformationAction` common parameter][08] as +`Continue` to have those messages emitted for DSC. + +### Emitting verbose messages from cmdlets + +The following snippet creates a temporary file. It uses commands that emit verbose messages, like +`New-Item`. The example shows how you can specify the `-Verbose` parameter on cmdlets to surface +their verbose messaging in DSC as `info` level trace messages. + +```powershell +$instance = [ordered]@{ + input = 'create' + getScript = { + param( + [ValidateSet('create', 'delete')] + [string] $fileOperation + ) + + $tempFolder = "Temp:/dsc/examples/WindowsPowerShellScript/messaging" + $tempFile = Join-Path $tempFolder 'info.txt' + + if (Test-Path $tempFile) { + $fileInfo = Get-Item -Path $tempFile + + [ordered]@{ + path = $fileInfo.FullName + exists = $true + creationTimeUtc = $fileInfo.CreationTimeUtc + lastWriteTimeUtc = $fileInfo.LastWriteTimeUtc + attributes = $fileInfo.Attributes.ToString() + } + } else { + [ordered]@{ + path = $fileInfo.FullName + exists = $false + } + } + }.ToString() + setScript = { + param( + [ValidateSet('create', 'delete')] + [string] $fileOperation + ) + + $tempFolder = "Temp:\dsc\examples\WindowsPowerShellScript\messaging" + $tempFile = Join-Path $tempFolder 'info.txt' + + switch ($fileOperation) { + 'create' { + if (-not (Test-Path $tempFolder)) { + $null = New-Item -Path $tempFolder -ItemType Directory -Force -Verbose + } + if (-not (Test-Path $tempFile)) { + $null = New-Item -Path $tempFile -ItemType File -Verbose + } + + $fileInfo = Get-Item -Path $tempFile + + [ordered]@{ + path = $fileInfo.FullName + exists = $true + creationTimeUtc = $fileInfo.CreationTimeUtc + lastWriteTimeUtc = $fileInfo.LastWriteTimeUtc + attributes = $fileInfo.Attributes + } + } + 'delete' { + if (Test-Path $tempFile) { + Remove-Item -Path $tempFile -Force -Verbose + } + + [ordered]@{ + path = $fileInfo.FullName + exists = $false + } + } + } + }.ToString() +} + +dsc --trace-level info resource set --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input ( + $instance | ConvertTo-Json -Compress +) +``` + +```Output + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + INFO PID : Performing the operation "Create Directory" on target "Destination: C:\Users\\AppData\Local\Temp\dsc\examples\WindowsPowerShellScript". + INFO PID : Performing the operation "Create Directory" on target "Destination: C:\Users\\AppData\Local\Temp\dsc\examples\WindowsPowerShellScript\messaging". + INFO PID : Performing the operation "Create File" on target "Destination: C:\Users\\AppData\Local\Temp\dsc\examples\WindowsPowerShellScript\messaging\info.txt". + INFO diff: key 'creationTimeUtc' missing + INFO diff: key 'lastWriteTimeUtc' missing + INFO diff: key 'attributes' missing + INFO diff: actual array missing expected item + INFO diff: arrays differ for 'output' +beforeState: + output: + - path: null + exists: false +afterState: + output: + - path: C:\Users\\AppData\Local\Temp\dsc\examples\WindowsPowerShellScript\messaging\info.txt + exists: true + creationTimeUtc: 2026-05-21T17:58:31.2115007Z + lastWriteTimeUtc: 2026-05-21T17:58:31.2115007Z + attributes: 32 +changedProperties: +- output +``` + +The info messages emitted by DSC include the verbose messages from creating the temporary directory +and file. + +Invoke the resource again but with the `input` set to `delete` to remove the temporary file: + +```powershell +$instance.input = 'delete' + +dsc --trace-level info resource set --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input ( + $instance | ConvertTo-Json -Compress +) +``` + +### Emitting verbose messages with `Write-Verbose` + +You can surface custom `info` level messages from scripts with the [`Write-Verbose`][05] cmdlet. + +The following snippet shows how messages from `Write-Verbose` surface as DSC trace messages. + +```powershell +$instance = @' +getScript: |- + Write-Verbose "Setting things up" + Write-Verbose "Retrieving data" +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) + +dsc --trace-level info resource get @arguments +``` + +```Output + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Invoking get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + INFO PID : Setting things up + INFO PID : Retrieving data +actualState: + output: [] +``` + +### Emitting verbose messages with `Write-Host` + +You can surface custom `info` level messages from scripts with the [`Write-Host`][06] cmdlet. + +The following snippet shows how messages from `Write-Host` surface as DSC trace messages. + +```powershell +$instance = @' +getScript: |- + Write-Host "Setting things up" + Write-Host "Retrieving data" +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) + +dsc --trace-level info resource get @arguments +``` + +```Output + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Invoking get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + INFO PID : Setting things up + INFO PID : Retrieving data +actualState: + output: [] +``` + +## Emitting debug messages + +You can emit `debug` level messages for DSC with the [`Write-Debug`][09] cmdlet. When a cmdlet used +in your script emits debug messages, you can use the [`-Debug` common parameter][07] to have those +messages emitted for DSC. + +### Emitting debug messages from cmdlets + +The following snippet shows how debug messages from commands are captured by the resource. It +defines a function that emits debug messages and then invokes that function. + +```powershell +$instance = @' +getScript: |- + function Get-Data { + [CmdletBinding()] + param() + + Write-Debug "Starting process..." + Write-Debug "Doing things..." + Write-Debug "Done." + } + + Get-Data +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) + +dsc --trace-level debug resource get @arguments +``` + +```Output + INFO dsc_lib::dscresources::command_resource: 69: Invoking get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + DEBUG dsc_lib::dscresources::command_resource: 1218: PID : Starting process... + DEBUG dsc_lib::dscresources::command_resource: 1218: PID : Doing things... + DEBUG dsc_lib::dscresources::command_resource: 1218: PID : Done. + DEBUG dsc_lib::dscresources::command_resource: 850: Process 'powershell' id exited with code 0 + DEBUG dsc_lib::dscresources::command_resource: 72: Verifying output of get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' +actualState: + output: [] +``` + +The output shows `debug` level messages emitted by the invoked function in the script. + +### Emitting debug messages with `Write-Debug` + +You can surface custom `debug` level messages from scripts with the [`Write-Debug`][05] cmdlet. + +The following snippet shows how messages from `Write-Debug` surface as DSC trace messages. + +```powershell +$instance = @' +getScript: |- + Write-Debug "Setting things up" + Write-Debug "Retrieving data" +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) + +dsc --trace-level debug resource get @arguments +``` + +```Output + INFO dsc_lib::dscresources::command_resource: 69: Invoking get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + DEBUG dsc_lib::dscresources::command_resource: 1218: PID : Setting things up + DEBUG dsc_lib::dscresources::command_resource: 1218: PID : Retrieving data + DEBUG dsc_lib::dscresources::command_resource: 850: Process 'powershell' id exited with code 0 + DEBUG dsc_lib::dscresources::command_resource: 72: Verifying output of get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' +actualState: + output: [] +``` + +## Emitting trace messages + +You can emit `trace` level messages for DSC with the [`Write-Information`][10] cmdlet. When a +cmdlet used in your script emits debug messages, you can specify the +[`-InformationAction` common parameter][11] as `Continue` to have those messages emitted for DSC. + +### Emitting trace messages from cmdlets + +The following snippet shows how information messages from commands are captured by the resource as +trace messages. It defines a function that emits information messages and then invokes that +function with `-InformationAction` as `Continue`. + +```powershell +$instance = @' +getScript: |- + function Get-Data { + [CmdletBinding()] + param() + + Write-Information "Starting process..." + Write-Information "Doing things..." + Write-Information "Done." + } + + Get-Data -InformationAction Continue +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) + +dsc --trace-level trace resource get @arguments +``` + +```Output + INFO dsc_lib::dscresources::command_resource: 69: Invoking get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + TRACE dsc_lib::dscresources::command_resource: 898: Invoking command 'powershell' with args Some(["-NoLogo", "-NonInteractive", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", "$input | ./psscript.ps1", "get"]) + TRACE dsc_lib::dscresources::command_resource: 900: Current working directory: C:\code\dsc\dsc-pr-review\bin\debug + TRACE dsc_lib::dscresources::command_resource: 806: Writing to command STDIN: {"getScript":"function Get-Data {\n [CmdletBinding()]\n param()\n\n Write-Information \"Starting process...\"\n Write-Information \"Doing things...\"\n Write-Information \"Done.\"\n}\n\nGet-Data -InformationAction Continue"} + TRACE dsc_lib::dscresources::command_resource: 1220: PID : Starting process... + TRACE dsc_lib::dscresources::command_resource: 1220: PID : Doing things... + TRACE dsc_lib::dscresources::command_resource: 1220: PID : Done. + DEBUG dsc_lib::dscresources::command_resource: 850: Process 'powershell' id exited with code 0 + DEBUG dsc_lib::dscresources::command_resource: 72: Verifying output of get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + TRACE dsc_lib::dscresources::command_resource: 1083: Verify JSON for 'Microsoft.DSC.Transitional/WindowsPowerShellScript': {"output":[]} + +actualState: + output: [] +``` + +The output shows `trace` level messages emitted by the invoked function in the script. + +### Emitting trace messages with `Write-Information` + +You can surface custom `trace` level messages from scripts with the [`Write-Information`][10] +cmdlet. + +The following snippet shows how messages from `Write-Information` surface as DSC trace messages. + +```powershell +$instance = @' +getScript: |- + Write-Information "Setting things up" + Write-Information "Retrieving data" +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) + +dsc --trace-level trace resource get @arguments +``` + +```Output + INFO dsc_lib::dscresources::command_resource: 69: Invoking get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + TRACE dsc_lib::dscresources::command_resource: 898: Invoking command 'powershell' with args Some(["-NoLogo", "-NonInteractive", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", "$input | ./psscript.ps1", "get"]) + TRACE dsc_lib::dscresources::command_resource: 900: Current working directory: C:\code\dsc\dsc-pr-review\bin\debug + TRACE dsc_lib::dscresources::command_resource: 806: Writing to command STDIN: {"getScript":"Write-Information \"Setting things up\"\nWrite-Information \"Retrieving data\""} + TRACE dsc_lib::dscresources::command_resource: 1220: PID : Setting things up + TRACE dsc_lib::dscresources::command_resource: 1220: PID : Retrieving data + DEBUG dsc_lib::dscresources::command_resource: 850: Process 'powershell' id exited with code 0 + DEBUG dsc_lib::dscresources::command_resource: 72: Verifying output of get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + TRACE dsc_lib::dscresources::command_resource: 1083: Verify JSON for 'Microsoft.DSC.Transitional/WindowsPowerShellScript': {"output":[]} + +actualState: + output: [] +``` + + +[01]: ../index.md +[02]: /powershell/module/microsoft.powershell.utility/write-error +[03]: /powershell/module/microsoft.powershell.core/about/about_try_catch_finally +[04]: /powershell/module/microsoft.powershell.utility/write-warning +[05]: /powershell/module/microsoft.powershell.utility/write-verbose +[06]: /powershell/module/microsoft.powershell.utility/write-host +[07]: /powershell/module/microsoft.powershell.core/about/about_commonparameters#-verbose +[08]: /powershell/module/microsoft.powershell.core/about/about_commonparameters#-informationaction +[09]: /powershell/module/microsoft.powershell.utility/write-debug +[10]: /powershell/module/microsoft.powershell.utility/write-information +[11]: /powershell/module/microsoft.powershell.core/about/about_commonparameters#-informationaction diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/invoke-with-output-data.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/invoke-with-output-data.md new file mode 100644 index 0000000..bf96797 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/invoke-with-output-data.md @@ -0,0 +1,888 @@ +--- +description: > + Example showing how to return output data from a WindowsPowerShellScript + resource. +ms.date: 05/10/2026 +ms.topic: reference +title: Invoke the WindowsPowerShellScript resource with output data +--- + + + +# Invoke the WindowsPowerShellScript resource with output data + +These examples show how you can return output from the +[`Microsoft.DSC.Transitional/WindowsPowerShellScript` resource][01]. + +## Output data types + +All output that a script emits for this resource is inserted into the `output` array for the +resource instance. The resource uses the `ConvertTo-Json` cmdlet for every item emitted to the +[Success stream][02]. The converted representation is what the resource inserts into the `output` +array. + +When the resource serializes the output data as JSON it retains up to `9` levels of depth. This can +make the output for typical PowerShell objects a script may return very large and difficult to +parse in the result for an operation. + +### Outputting scalar values + +The following snippet shows how scalar values (not objects or arrays) are handled by the resource +when emitted by a script. Scalar values include strings, integers, floats, booleans, and `$null`. + +```powershell +$instance = @' +getScript: |- + $true # boolean scalar value + 1 # integer scalar value + 1.2 # float scalar value + $null # null scalar value + 'apple' # string scalar value +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) + +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - true + - 1 + - 1.2 + - null + - apple +``` + +### Outputting objects + +When a script emits objects that aren't scalar values, the conversion to JSON representation +includes up to `9` levels of depth. Objects often have properties that are _also_ objects with +sub-properties or arrays of nested objects. + +When the object output is particularly large and complex it can cause the resource operation to +fail when DSC needs to validate the output data. The following snippet shows how emitting a +`[FileInfo]` object directly can cause the resource to fail. + +The script creates a new temporary file, which emits the `[FileInfo]` object for the new file as +output. + +```powershell +$instance = @' +getScript: |- + $filePath = 'Temp:/dsc/examples/WindowsPowerShellScript/output.txt' + + New-Item -Path $filePath -Force +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) + +dsc --trace-level debug resource get @arguments +``` + +```Output + INFO dsc_lib::dscresources::command_resource: 69: Invoking get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + DEBUG dsc_lib::dscresources::command_resource: 850: Process 'powershell' id exited with code 0 + DEBUG dsc_lib::dscresources::command_resource: 72: Verifying output of get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + ERROR dsc::resource_command: 67: JSON: expected value at line 1 column 1 +``` + +We can demonstrate the failure independently of DSC. When you invoke the following snippet, +PowerShell hangs. A `[FileInfo]` object can be extremely large as the object contains references to +its parent folder, which references that object's parent folder, and so on. + +```powershell +$fileInfo = Get-Item -Path 'Temp:/dsc/examples/WindowsPowerShellScript/output.txt' +$fileJson = ConvertTo-Json -Depth 9 -InputObject $fileInfo +# The following commands never run because the session hangs +$outputSize = [System.Text.Encoding]::UTF8.GetByteCount($fileJson) / 1MB +"The output JSON is {0} MB" -f [Math]::Round($outputSize, 2) +``` + + +You can cancel the command by pressing Ctrl+C in your console. + +If you update the depth to `5` and invoke the command again, you can see that the size of the JSON +object is _substantial_. + +```powershell +$fileInfo = Get-Item -Path 'Temp:/dsc/examples/WindowsPowerShellScript/output.txt' +$fileJson = ConvertTo-Json -Depth 5 -InputObject $fileInfo +# The following commands never run because the session hangs +$outputSize = [System.Text.Encoding]::UTF8.GetByteCount($fileJson) / 1MB +"The output JSON is {0} MB" -f [Math]::Round($outputSize, 2) +``` + +```Output +WARNING: Resulting JSON is truncated as serialization has exceeded the set depth of 5. +The output JSON is 58.37 MB +``` + +Instead of emitting complex objects directly, consider constructing your output objects +intentionally. For a comprehensive example of emitting structured output, see the +["Structure output for an idempotent instance"](#structure-output-for-an-idempotent-instance) +section of this article. + +### Outputting arrays + +By default, when a script emits an array as output, each item in the array is captured as a +separate item in the `output` property for the resource. + +The following snippet shows the default behavior. + +```powershell +$instance = @' +getScript: |- + @('a', 'b', 'c') + @(1, 2, 3) +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) + +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - a + - b + - c + - 1 + - 2 + - 3 +``` + +In the previous snippet, the script emitted two arrays: + +1. An array containing three strings +1. An array containing three integers + +The `output` for the resource included six separate items representing each of the items in the +emitted arrays in the order that the script emitted them. + +The following snippet shows how you can use the [`Write-Object` cmdlet][03] with the +[`-NoEnumerate`][04] parameter to emit arrays from the script and keep them as arrays. + +```powershell +$instance = @' +getScript: |- + Write-Output -NoEnumerate @('a', 'b', 'c') + Write-Output -NoEnumerate @(1, 2, 3) +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) + +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - - a + - b + - c + - - 1 + - 2 + - 3 +``` + +Now the output from the script shows two items in the `output` array. Each item is an array +containing three items. + +## Discarding unwanted output + +Every item emitted to the success stream is included in the `output` for the resource. To avoid +including unwanted data in the output you need to discard that data. To discard data from a +statement that would otherwise emit unwanted output, you can: + +- Assign the statement to `$null`. +- Redirect the statement to `$null`. +- Cast the statement to `[void]`. +- Pipe the statement to `Out-Null`. + +The first three options have nearly identical performance. Piping to `Out-Null` can be much slower +when looping over a large set of data. + +The following snippet shows examples for discarding unwanted output in a script. + +```powershell +$instance = @' +getScript: |- + $filePath = 'Temp:/dsc/examples/WindowsPowerShellScript/output.txt' + # Assign to `$null` + $null = New-Item -Path $filePath -Force + # Redirect to `$null` + New-Item -Path $filePath -Force > $null + # Cast to `[void]` + [void](New-Item -Path $filePath -Force) + # Pipe to `Out-Null` + New-Item -Path $filePath -Force | Out-Null + + 'this is the only output' +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) + +dsc resource get @arguments +``` + +```yaml +actualState: + output: + - this is the only output +``` + +## Output for `getScript` + +For `getScript` you can emit any data to the PowerShell success stream that you want to surface to +the user. The emitted data is returned in the `actualState.output` field for the **Get** operation +result and the `beforeState.output` field for the **Set** operation result. + +If you're defining the resource instance to idempotently manage the state of one or more system +components, ensure that the output you emit from `getScript` uses the same structure as the output +from `setScript` to make the results readable for the user. + +Otherwise, return any data that you want to surface to the user. If you want to give the user more +information, you can [emit messages][05]. For comprehensive examples of emitting messages from your +script see [Invoke the WindowsPowerShellScript resource with trace messaging][06]. + +The following example shows how you can emit items from `getScript` to inform the user. For a +comprehensive example of structured output for an instance that idempotently manages system state, +see ["Structure output for an idempotent instance"](#structure-output-for-an-idempotent-instance) +in this article. + +```powershell +$instance = @' +getScript: |- + "Current context is interactive: {0}" -f [Environment]::UserInteractive + "Current context is privileged: {0}" -f [Environment]::IsPrivilegedProcess +'@ + +dsc resource get --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input $instance +``` + +```yaml +actualState: + output: + - 'Current context is interactive: True' + - 'Current context is privileged: False' +``` + +## Output for `testScript` + +The `testScript` definition _must_ return a single boolean value - `$true` to indicate that the +system is in the desired state or `$false` otherwise. + +Any of the following will cause the resource to raise an error when invoking the `testScript`: + +- Not emitting any output at all to the success stream. +- Emitting any non-boolean data to the success stream. +- Emitting more than one boolean value to the success stream. + +You can [emit messages][05] To indicate to the user how and why the +system isn't in the desired state. For detailed examples of emitting messages from your script +see [Invoke the WindowsPowerShellScript resource with trace messaging][06]. + +The following example shows how you can define `testScript` to check whether a file exists and +isn't empty. It emits info messages to clarify whether and how the instance is in the desired +state. + +```powershell +$instance = @' +testScript: |- + $filePath = 'Temp:/dsc/examples/WindowsPowerShellScript/output.txt' + + if (-not (Test-Path $filePath)) { + Write-Verbose "The file '$filePath' doesn't exist" + return $false + } + + if ([string]::IsNullOrEmpty((Get-Content -Raw -Path $filePath))) { + Write-Verbose "The file '$filePath' is empty" + return $false + } + + Write-Verbose "The file '$filePath' exists and contains content" + $true +'@ + +$arguments = @( + '--resource', 'Microsoft.DSC.Transitional/WindowsPowerShellScript' + '--input', $instance +) + +dsc --trace-level info resource test @arguments +``` + +```console + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Invoking test on 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + INFO PID : The file 'Temp:/dsc/examples/WindowsPowerShellScript/output.txt' is empty + INFO diff: key 'testScript' missing +desiredState: + testScript: |- + $filePath = 'Temp:/dsc/examples/WindowsPowerShellScript/output.txt' + + if (-not (Test-Path $filePath)) { + Write-Verbose "The file '$filePath' doesn't exist" + return $false + } + + if ([string]::IsNullOrEmpty((Get-Content -Raw -Path $filePath))) { + Write-Verbose "The file '$filePath' is empty" + return $false + } + + Write-Verbose "The file '$filePath' exists and contains content" + $true +actualState: + _inDesiredState: false +inDesiredState: false +differingProperties: +- testScript +``` + +For a more comprehensive example that idempotently manages system state see the +["Structure output for an idempotent instance"](#structure-output-for-an-idempotent-instance) +section of this article. + +## Output for `setScript` + +For `setScript` you can emit any data to the PowerShell success stream that you want to surface to +the user. The emitted data is returned in the `afterState.output` field for the **Set** operation +result. + +If you're defining the resource instance to idempotently manage the state of one or more system +components, ensure that the output you emit from `setScript` uses the same structure as the output +from `getScript` to make the results readable for the user. + +Otherwise, return any data that you want to surface to the user. If you want to give the user more +information, you can [emit messages][05]. For comprehensive examples of +emitting messages from your script see +[Invoke the WindowsPowerShellScript resource with trace messaging][06]. + +The following example shows how you can emit items from `setScript` to inform the user about how +the script is modifying the system. + +```powershell +$instance = @' +setScript: |- + $filePath = 'Temp:/dsc/examples/WindowsPowerShellScript/output.txt' + $content = 'Hello world' + if (-not (Test-Path $filePath)) { + "File '$filePath' doesn't exist - creating it" + $null = New-Item -Path $filePath -Force + } + + $currentContent = Get-Content -Raw -Path $filePath + if ([string]::IsNullOrEmpty($currentContent)) { + "File '$filePath' is empty - adding content" + $content | Set-Content -Path $filePath -NoNewline + } elseif ($currentContent -ne $content) { + "File '$filePath' contains invalid content - overriding content" + $content | Set-Content -Path $filePath -NoNewline + } else { + "File '$filePath' contains desired content'" + } + + [ordered]@{ + initialContent = $currentContent + finalContent = $content + } +'@ + +dsc resource set --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input $instance +``` + +```yaml +beforeState: {} +afterState: + output: + - File 'Temp:/dsc/examples/WindowsPowerShellScript/output.txt' is empty - adding conent + - initialContent: null + finalContent: Hello world +changedProperties: +- output +``` + +In this example, `beforeState` is an empty object because the instance doesn't define `getScript`. +The output from `setScript` includes two items. The first is a message indicating that the file +exists but is empty. The second item is an object showing both the initial content and final +content of the file. + +For a comprehensive example of structured output for an instance that idempotently manages system +state, including defining `getScript` to populate the `beforeState` in the **Set** result, see the +[Structure output for an idempotent instance](#structure-output-for-an-idempotent-instance) section +of this article. + +## Structure output for an idempotent instance + +To return output that is readable for the user, consider returning only objects. Use property names +to orient the user when reviewing the output. Limit the depth of the object to no more than three +levels when possible. + +The following example shows how you can return information about a JSON configuration file that +isn't managed by a specific DSC resource. It follows best practices by: + +1. Implementing scripts for all three operations. +1. Returning a single structured object from `getScript`. +1. Returning a boolean for `testScript` and emitting trace messages to indicate _how_ the instance + is out of the desired state. +1. Returning the same structured object from `setScript` as `getScript`. +1. Emitting trace messages to indicate which settings the `setScript` is modifying. + +> [!NOTE] +> This example uses an ordered dictionary to represent the instance because the script properties +> are much longer and more detailed than earlier examples in this article. Defining the scripts +> this way makes it easier to review the script code than defining it all together in a YAML +> snippet. +> +> The `getScript` and `setScript` snippets define the output object as an ordered dictionary with +> the `[ordered]` type accelerator. This ensures that the emitted object always keeps the key-value +> pairs in the defined order. Defining the output object as a normal hashtable causes the ordering +> of the output object properties to be nondeterministic, which can make comparing results more +> difficult. +> +> You could also define the output object as a `[pscustomobject]` and use the `Add-Member` function +> to add more properties to the initial object. + +First, define an ordered dictionary to represent the instance. Define the `input` for the scripts +the instance will use. In this example, the input data includes both the path to the file and the +settings to manage in that file. + +```powershell +$instance = [ordered]@{ + input = [ordered]@{ + filePath = 'Temp:/dsc/examples/WindowsPowerShellScript/output.json' + settings = [ordered]@{ + updateAutomatically = $true + updateFrequency = 30 + } + } +} +``` + +Next, define `getScript` to retrieve the actual state of the configuration file. The script must +define a `param()` statement to accept the input data. + +The script returns an object that always includes the `filePath` and `exists` properties. +`filePath` is identical to `input.filePath` for the instance. `exists` indicates whether the file +actually exists on the system. + +If the file doesn't exist, that's all the information the instance can provide. The script returns +that data and stops processing. + +If the file does exist, the output object also includes the `settings` and `lastWriteTime` +properties. `settings` is the contents of the file converted from JSON. `lastWriteTime` is the +actual last write time for the file itself. + +```powershell +$instance.getScript = { + param($inputData) + + $result = [ordered]@{ + filePath = $inputData.filePath + exists = Test-Path -Path $inputData.filePath + } + + if (-not $result.exists) { + Write-Verbose "Config file doesn't exist" + return $result + } + Write-Verbose "Retrieving settings and last write time from config file" + $fileInfo = Get-Item -Path $inputData.filePath + $settings = Get-Content -Raw -Path $inputData.filePath | ConvertFrom-Json + + $result.settings = $settings + $result.lastWriteTime = $fileInfo.LastWriteTime + + $result +}.ToString() +``` + +The next snippet defines `testScript` for the instance. As with `getScript`, the script must define +a single parameter. Unlike `getScript`, this script must return exactly one boolean value. + +The test script: + +1. Checks whether the configuration file (`input.filePath`) exists. If it doesn't, the script emits + an info message and returns `$false`. +1. Checks whether the configuration file is empty. If it is, the script emits an info message and + returns `$false`. +1. Iterates over the key-value pairs for the desired settings (`input.settings`) to check whether + each of them is in the desired state. If the desired setting isn't defined or is defined with + an incorrect value the script emits an info message and marks the resource as noncompliant but + _doesn't_ stop processing. + + This ensures that the instance can fully report on the desired settings instead of only reporting + the first missing or incorrect setting. +1. Returns `$false` if any setting wasn't in the desired state and otherwise `$true`. + +```powershell +$instance.testScript = { + param($inputData) + + if (-not (Test-Path -Path $inputData.filePath)) { + Write-Verbose "Config file doesn't exist" + return $false + } + + $content = Get-Content -Raw -Path $inputData.filePath + if ([string]::IsNullOrEmpty($content)) { + Write-Verbose "Config file is empty" + return $false + } + + # Initialize variable for result. If any check fails, set to `$false` + # From this point on we want to fully validate state for info messages to + # the user instead of returning early. + $inDesiredState = $true + + # Loop over the desired state to compare to actual settings + $desiredSettings = $inputData.settings.psobject.Properties + $actualSettings = ($content | ConvertFrom-Json).psobject.Properties + foreach ($setting in $desiredSettings) { + $name = $setting.Name + $desiredValue = $setting.Value + $actualSetting = $actualSettings | Where-Object Name -EQ $name + + if ($null -eq $actualSetting) { + Write-Verbose "Missing setting '$name'" + $inDesiredState = $false + continue + } + + if ($actualSetting.Value -ne $setting.Value) { + $message = "Expected setting '{0}' to be ``{1}`` but it is ``{2}``" -f @( + $name + $desiredValue + $actualSetting.Value + ) + Write-Verbose $message + $inDesiredState = $false + } + } + + $inDesiredState +}.ToString() +``` + +To enforce the desired state, define the `setScript` for the instance. The script must define a +single parameter. To make the result for the **Set** operation readable the script emits the same +data structure as `getScript`. + +The script is defined to be idempotent, only modifying the system if needed. It follows these steps: + +1. Define the result object with `filePath` as the `input.filePath` value and `exists` as `true`. +1. Check whether the configuration file exists. If it doesn't, emit a message to indicate that the + instance is creating the file. Then create the file and write the desired state settings + (`input.settings`) into it. Populate the `settings` and `lastWriteTime` fields for the result + object and then use the `return` keyword to emit the result and stop processing the script. +1. If the configuration file does exist retrieve the settings from it. Iterate over the desired + state settings (`input.settings`). If the setting is missing or defined incorrectly, emit an + info message and mark the instance as requiring an update with the `$shouldUpdate` variable. + This ensures that the instance only modifies the file when the settings aren't in the desired + state. + + > [!NOTE] + > This is necessary for version `0.1.0` of this resource. In this release the resource doesn't + > use the `testScript` to determine whether to actually invoke the `setScript`. The resource + > _always_ invokes `setScript` when you invoke the **Set** operation for the resource or on a + > configuration document containing an instance of the resource. + + If the setting is missing, add the desired state setting to the object representing the actual + state. If the setting has the incorrect value, set that property on the same object to the + desired state. This ensures that the resource doesn't inadvertently modify or remove any + settings in the configuration file that the instance isn't managing (the setting is defined in + the file but not `input.settings`). +1. If any of the desired state settings weren't defined in the configuration file or were defined + with invalid values emit a message and update the file with the combined settings. Otherwise + emit a message indicating that the configuration file didn't require any modification. +1. Update the result object to include the final settings and the last write time for the file and + emit the result. + +`setScript` returns the same structured output data as `getScript` regardless of whether the script +creates, updates, or doesn't modify the configuration file. This helps make the output for the +**Set** operation readable and enable directly comparing the `beforeState` and `afterState` fields +in the result. + +```powershell +$instance.setScript = { + param($inputData) + + $filePath = $inputData.filePath + $settings = $inputData.settings + $result = [ordered]@{ + filePath = $filePath + exists = $true + } + + if (-not (Test-Path -Path $filePath)) { + Write-Verbose "Creating config file with specified settings" + $null = New-Item -Path $filePath -Force -Verbose + $json = $settings | ConvertTo-Json + $json | Out-File -FilePath $filePath -Encoding utf8NoBOM + + $result.settings = $settings + $result.lastWriteTime = Get-Item -Path $filePath | + Select-Object -ExpandProperty LastWriteTime + + return $result + } + + $content = Get-Content -Raw -Path $filePath + $actualSettings = $content | ConvertFrom-Json + $shouldUpdate = $false + # Iterate over defined settings, updating the actual settings as needed. + # Don't remove any non-managed settings, only enforce specified settings. + # Set shouldUpdate to $true if any changes are needed, but wait to write + # to the file until all changes are processed to avoid multiple writes. + foreach ($setting in $settings.psobject.Properties) { + $name = $setting.Name + $value = $setting.Value + Write-Verbose "Processing setting '$name' with desired value ``$value``" + $actual = $actualSettings.psobject.Properties | + Where-Object Name -EQ $name | + Select-Object -First 1 + + if ($null -eq $actual) { + Write-Verbose "Adding setting '$name' as ``$value``" + + $shouldUpdate = $true + $memberParams = @{ + InputObject = $actualSettings + MemberType = 'NoteProperty' + Name = $name + Value = $value + } + Add-Member @memberParams + } elseif ($value -eq $actual.Value) { + Write-Verbose "Setting '$name' is already set to ``$value``" + } else { + $message = "Changing setting '{0}' from ``{1}`` to ``{2}``" -f @( + $name + $actual.Value + $value + ) + Write-Verbose $message + + $shouldUpdate = $true + $actualSettings.$name = $value + } + } + + if ($shouldUpdate) { + Write-Verbose "Updating config file with new settings" + $json = $actualSettings | ConvertTo-Json + $json | Out-File -FilePath $filePath -Encoding utf8NoBOM + } else { + Write-Verbose "Config file is already in the desired state. No update needed." + } + + $result.settings = $actualSettings + $result.lastWriteTime = Get-Item -Path $filePath | + Select-Object -ExpandProperty LastWriteTime + + $result +}.ToString() +``` + +With the instance fully defined, invoke the **Get** operation to ensure that returning the actual +state works as expected: + +```powershell +dsc --trace-level info resource get --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input ( + ConvertTo-Json -InputObject $instance +) +``` + +```Output + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Invoking get 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + INFO PID : Config file doesn't exist +actualState: + output: + - filePath: Temp:/dsc/examples/WindowsPowerShellScript/output.json + exists: false +``` + +The output shows that the configuration file doesn't exist. + +Next, invoke the **Set** operation to create the file: + +```powershell +dsc --trace-level info resource set --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input ( + ConvertTo-Json -InputObject $instance +) +``` + +```Output + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + INFO PID : Config file doesn't exist + INFO PID : Creating config file with specified settings + INFO PID : Performing the operation "Create File" on target "Destination: C:\Users\\AppData\Local\Temp\dsc\examples\WindowsPowerShellScript\output.json". + INFO diff: key 'updateAutomatically' is not an object + INFO diff: key 'updateFrequency' is not an object + INFO diff: key '_exist' is not an object + INFO diff: key 'lastWriteTime' missing + INFO diff: actual array missing expected item + INFO diff: arrays differ for 'output' +beforeState: + output: + - filePath: Temp:/dsc/examples/WindowsPowerShellScript/output.json + exists: false +afterState: + output: + - filePath: Temp:/dsc/examples/WindowsPowerShellScript/output.json + exists: true + settings: + updateAutomatically: true + updateFrequency: 30 + lastWriteTime: 2026-06-02T16:45:23.9746807-05:00 +changedProperties: +- output +``` + +The emitted messages show that the configuration file doesn't exist and the resource is creating +it. The `beforeState` is populated by the `getScript` and shows that the file doesn't exist. The +`afterState` then shows that the instance created the file with the expected settings and includes +the last write time. + +Invoking the **Set** operation again shows that the defined instance is idempotent: + +```powershell +dsc --trace-level info resource set --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input ( + ConvertTo-Json -InputObject $instance +) +``` + +```Output + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + INFO PID : Retrieving settings and last write time from config file + INFO PID : Processing setting 'updateAutomatically' with desired value `True` + INFO PID : Setting 'updateAutomatically' is already set to `True` + INFO PID : Processing setting 'updateFrequency' with desired value `30` + INFO PID : Setting 'updateFrequency' is already set to `30` + INFO PID : Config file is already in the desired state. No update needed. +beforeState: + output: + - filePath: Temp:/dsc/examples/WindowsPowerShellScript/output.json + exists: true + settings: + updateAutomatically: true + updateFrequency: 30 + lastWriteTime: 2026-06-02T16:45:23.9746807-05:00 +afterState: + output: + - filePath: Temp:/dsc/examples/WindowsPowerShellScript/output.json + exists: true + settings: + updateAutomatically: true + updateFrequency: 30 + lastWriteTime: 2026-06-02T16:45:23.9746807-05:00 +changedProperties: [] +``` + +The output in `beforeState` and `afterState` is identical and `changedProperties` is an empty +array. The emitted messages clarify that the instance checked each setting in the configuration +file and found them compliant to the desired state. + +Finally, update `input.settings` by: + +- Removing `updateAutomatically` +- Updating `updateFrequency` to `45` +- Adding `logLevel` as `info` + +Then invoke the resource again to see how the instance updates the configuration file. + +```powershell +$instance.input.settings.Remove('updateAutomatically') +$instance.input.settings.updateFrequency = 45 +$instance.input.settings.logLevel = 'info' + +dsc --trace-level info resource set --resource Microsoft.DSC.Transitional/WindowsPowerShellScript --input ( + ConvertTo-Json -InputObject $instance +) +``` + +```Output + INFO Trace-level is Info + INFO Discovering 'Extension' using filter: * + INFO Discovering 'Resource' using filter: * + INFO No results returned for discovery extension 'Microsoft.PowerShell/Discover' + INFO Getting current state for set by invoking get on 'Microsoft.DSC.Transitional/WindowsPowerShellScript' using 'powershell' + INFO PID : Retrieving settings and last write time from config file + INFO PID : Processing setting 'updateFrequency' with desired value `45` + INFO PID : Changing setting 'updateFrequency' from `30` to `45` + INFO PID : Processing setting 'logLevel' with desired value `info` + INFO PID : Adding setting 'logLevel' as `info` + INFO PID : Updating config file with new settings + INFO diff: key 'logLevel' missing + INFO diff: actual array missing expected item + INFO diff: arrays differ for 'output' +beforeState: + output: + - filePath: Temp:/dsc/examples/WindowsPowerShellScript/output.json + exists: true + settings: + updateAutomatically: true + updateFrequency: 30 + lastWriteTime: 2026-06-02T16:45:23.9746807-05:00 +afterState: + output: + - filePath: Temp:/dsc/examples/WindowsPowerShellScript/output.json + exists: true + settings: + updateAutomatically: true + updateFrequency: 45 + logLevel: info + lastWriteTime: 2026-06-02T16:53:39.2138244-05:00 +changedProperties: +- output +``` + +The emitted messages indicate that the instance only checked the `updateFrequency` and `logLevel` +settings - it didn't enforce `updateAutomatically`. The messages show that the instance updated +`updateFrequency` from `30` to `45` and added the missing `logLevel` setting. + +The result object again shows how `beforeState` differs from `afterState`, confirming that the +instance did modify system state. + + +[01]: ../index.md +[02]: /powershell/module/microsoft.powershell.core/about/about_output_streams#success-stream +[03]: /powershell/module/microsoft.powershell.utility/write-output +[04]: /powershell/module/microsoft.powershell.utility/write-output#-noenumerate +[05]: ../index.md#emitting-messages +[06]: ./invoke-with-messaging.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/winpsscript.config.dsc.yaml b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/winpsscript.config.dsc.yaml new file mode 100644 index 0000000..a246c0d --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/winpsscript.config.dsc.yaml @@ -0,0 +1,105 @@ +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.vscode.json + +parameters: + motd: + type: string + defaultValue: "Hello, friend!" + minLength: 1 + maxLength: 100 + +resources: +- type: Microsoft.DSC.Transitional/WindowsPowerShellScript + name: Report processor info + properties: + getScript: |- + $count = [System.Environment]::ProcessorCount + $arch = [System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture + + [ordered]@{ + processorCount = $count + processorArchitecture = $arch.ToString() + } + setScript: |- + $count = [System.Environment]::ProcessorCount + $arch = [System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture + + [ordered]@{ + processorCount = $count + processorArchitecture = $arch.ToString() + } +- type: Microsoft.DSC.Transitional/WindowsPowerShellScript + name: Message of the Day + properties: + input: "[parameters('motd')]" + getScript: | + param($motd) + + $filePath = 'Temp:/example.motd' + + Write-Verbose "Checking for MOTD file at '$filePath'" + $result = [ordered]@{ + filePath = $filePath + exists = Test-Path -Path $filePath + } + + if ($result.exists) { + Write-Verbose "MOTD file found at '$filePath', retrieving content and last updated time" + $result.motd = (Get-Content -Path $filePath -Raw).TrimEnd("`r", "`n") + $result.lastUpdated = (Get-Item -Path $filePath).LastWriteTime + } else { + Write-Verbose "MOTD file not found at '$filePath'" + } + + $result + setScript: |- + param($motd) + + $filePath = 'Temp:/example.motd' + $result = [ordered]@{ + filePath = $filePath + exists = $true + motd = $motd + } + + if (-not (Test-Path -Path $filePath)) { + Write-Verbose "MOTD file not found at '$filePath', creating new file" + New-Item -Path $filePath -ItemType File -Force | Out-Null + Write-Verbose "MOTD file created at '$filePath', setting content" + $motd | Set-Content -Path $filePath -Force + } else { + Write-Verbose "MOTD file found at '$filePath', checking content" + $currentMotd = (Get-Content -Path $filePath -Raw).TrimEnd("`r", "`n") + if ($currentMotd -ne $motd) { + Write-Verbose "MOTD content differs from desired value, updating file" + $motd | Set-Content -Path $filePath -Force + } else { + Write-Verbose "MOTD content matches desired value, no update needed" + } + } + + $result.lastUpdated = (Get-Item -Path $filePath).LastWriteTime + + $result + testScript: |- + param($motd) + + $filePath = 'Temp:/example.motd' + + Write-Verbose "Checking for MOTD file at '$filePath'" + if (-not (Test-Path -Path $filePath)) { + Write-Verbose "MOTD file not found at '$filePath'" + return $false + } + + Write-Verbose "MOTD file found at '$filePath', retrieving content" + $currentMotd = Get-Content -Path $filePath -Raw + if ([string]::IsNullOrEmpty($currentMotd)) { + Write-Verbose "MOTD file at '$filePath' is empty" + return $false + } elseif ($currentMotd -ne $motd) { + Write-Verbose "Expected MOTD content '$motd' does not match actual content '$currentMotd'" + return $false + } + + Write-Verbose "MOTD content is the expected value '$motd'" + $true \ No newline at end of file diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/index.md new file mode 100644 index 0000000..3ba553a --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/DSC/Transitional/WindowsPowerShellScript/index.md @@ -0,0 +1,542 @@ +--- +description: Microsoft.DSC.Transitional/WindowsPowerShellScript resource reference documentation +ms.date: 07/07/2025 +ms.topic: reference +title: Microsoft.DSC.Transitional/WindowsPowerShellScript +--- + + + +# Microsoft.DSC.Transitional/WindowsPowerShellScript + +## Synopsis + +Enable running Windows PowerShell 5.1 scripts inline. + +> [!IMPORTANT] +> The `Microsoft.DSC.Transitional/WindowsPowerShellScript` resource is intended as a temporary +> transitional resource while defining DSC resources for your needs. + +## Metadata + +```yaml +Version : 0.1.0 +Kind : resource +Tags : [Transitional, Windows] +Author : Microsoft +``` + +## Instance definition syntax + +```yaml +resources: + - name: + type: Microsoft.DSC.Transitional/WindowsPowerShellScript + properties: + # Optional properties + getScript: string + setScript: string + testScript: string + input: anyOf # string, boolean, integer, object, array, null + output: array + _inDesiredState: boolean # or null +``` + +## Description + +The `Microsoft.DSC.Transitional/WindowsPowerShellScript` resource enables you to run Windows +PowerShell 5.1 scripts inline as part of your DSC configuration. This resource is useful for +executing PowerShell logic that hasn't been fully transitioned to a dedicated DSC resource. + +The resource allows you to: + +- Define separate PowerShell scripts for **Get**, **Set**, and **Test** operations. +- Pass input data to the scripts. +- Receive output data from the scripts. +- Control the desired state behavior through the `_inDesiredState` property. + +The properties you define determine how the resource behaves. + +- If you don't define `getScript`, the `actualState` field in **Get** operation results and + `beforeState` field in **Set** operation results is always an empty object (`{}`). +- If you don't define `testScript`, the `inDesiredState` field for **Test** operation results is + always `true`. +- If you don't define `setScript`, the `afterState` field in **Set** operation results is always + an empty object (`{}`). +- If you define `input`, every script property you define _must_ start with a `param()` statement + that defines a single parameter. The value for `input` is _always_ passed to the scripts when the + resource invokes them. + + When the instance _doesn't_ define `input` the script properties must **not** include a `param()` + statement. + +> [!NOTE] +> This resource always invokes the script properties in PowerShell (`pwsh`). To define a resource +> instance with script properties that execute in Windows PowerShell (`powershell.exe`), see +> [`Microsoft.DSC.Transitional/PowerShellScript`][01]. + +### Defining script properties + +For an instance to be functional you must define one or more script properties: + +- Define `getScript` to retrieve actual system state with the **Get** operation or to show how the + instance modified the system during a **Set** operation. +- Define `testScript` to indicate whether the system is in the desired state with the **Test** + operation. + + > [!IMPORTANT] + > Version `0.1.0` of the resource does _not_ invoke the `testScript` to determine whether to + > invoke the `setScript`. The resource always invokes `setScript` for the **Set** operation. + > + > Ensure that you define the `setScript` to be idempotent or include a check before making any + > changes to the system to avoid unnecessary processing and unintended behaviors. + +- Define `setScript` to modify the system with the **Set** operation. You can use this resource to + define an instance that performs a specific task, such as warming a cache or clearing logs, or to + enforce a specific desired state for any number of system components. + + In either case, consider [emitting messages](#emitting-messages) to the user that helps them + understand what the instance is doing during an operation. + + If you are using the resource instance to enforce a specific desired state you should: + + 1. Emit one or more output objects representing the final state of the system components the + instance is modifying. + 1. Define `getScript` to emit the same data structures as output objects representing the actual + state of the system components the instance is managing. + + This ensures that the user can more easily compare the `beforeState` and `afterState` fields of + the **Set** operation result to see how the instance modified the system. + +The following subsections provide more information on input, error handling, output, and emitting +messages from within the script properties. + +#### Handling input + +To pass input to a script, you must: + +1. Define the script property with a `param()` statement that specifies a single parameter. + Omitting the `param()` statement, defining an empty `param()` statement, or defining more than + one parameter all cause the resource to fail. +1. Define the [`input`](#input) property for the resource instance with a non-null value. When you + omit the `input` property or define it with a null value, like `input: null`, the resource + raises an error causing the operation to fail. + +The data bound to the script parameter is the result of using the `ConvertFrom-Json` cmdlet on the +value for the `input` property of the resource instance. + +You can define the script parameter with a type, like `[string[]]` when the script expects the input +as an array of strings. PowerShell's normal parameter binding and type conversion behavior applies +to the script parameter. If the input data can't be converted to the defined type then the script +fails and raises an error indicating that the input data was invalid. + +You can also apply [validation attributes][02] to the parameter to further validate that the input +data is correct for your script. + +For detailed examples of using input data with this resource, see +[Invoke the WindowsPowerShellScript resource with input data][03]. + +#### Handling errors + +This resource invokes the PowerShell scripts with the [`$ErrorActionPreference` variable][04] set +to `Stop`. By default, _any_ error raised by the script, regardless of whether it's terminating, +stops script execution. + +You can control whether script execution continues on an error message in two ways: + +1. Specify the [`-ErrorAction` common parameter][05] for any command you expect to fail. Specify + the value for the parameter as `Continue` to emit the error message or `Ignore` to skip the + error message. In either case, execution will continue after the error. +1. Use a [`try`/`catch` statement][06] to add error handling for errors. When a statement in the + `try` block raises an error, the code in the `catch` block will execute before the code in the + `finally` block (if defined). Unless code in the `catch` or `finally` blocks raises an error, + the script will continue to execute. + +Providing error handling enables you to emit better information for users when something goes wrong +with the script behavior. + +However, even when you provide handling for errors, like using a `try`/`catch` statement or passing +`-ErrorAction Ignore` to a command you expect to fail, the resource considers the operation to have +failed. The resource doesn't populate the `output` property for failed scripts. + +There is no way with the current version of the resource for a script to raise any errors and _not_ +fail. You can only provide better diagnostics for the user in the event of a failure. + +For detailed examples of emitting errors from scripts, see ["Emitting errors"][07] in +[Invoke the WindowsPowerShellScript resource with trace messaging][08]. + +#### Returning output + +Any objects emitted by the script for an operation are converted to JSON with the `ConvertTo-Json` +cmdlet and appended to the `output` property array returned by the resource. The ordering of the +items in `output` is the same that they were emitted by the script. + +You can emit any number of items. You don't need to use any specific PowerShell cmdlet to emit +output for this resource. Any output from a PowerShell statement that isn't redirected or captured +as a variable is automatically included in the output. + +You can prevent statements from emitting output by assigning them to `$null`. For example, if your +script uses the `New-Item` cmdlet to create a file, the output for that command is emitted from +your script by default. To avoid emitting that data, you could use the following snippet: + +```powershell +$null = New-Item -Path $filePath +``` + +To provide more readable results to users, consider only emitting a single structured object from +both `getScript` and `setScript`. Emitting an object with descriptive property names makes it +easier to compare the `beforeState` and `afterState` fields for a **Set** operation result. Using +the same data structure also enables DSC to correctly determine the `changedProperties` field for +the **Set** operation result. If the output from `getScript` and `setScript` are identical then +`changedProperties` is an empty array. + +For `testScript`, be sure to _only_ and _always_ emit a single boolean value (`$true` or `$false`). +If `testScript` emits any non-boolean value, more than one boolean value, or no values at all then +the resource considers the operation to have failed and raises an error. + +For comprehensive examples showing how to emit and control output from scripts, see +[Invoke the WindowsPowerShellScript resource with output data][09]. + +#### Emitting messages + +The following table maps DSC's tracing levels to PowerShell output streams and `Write-*` cmdlets: + +| DSC trace level | PowerShell stream | PowerShell cmdlets | +|:---------------:|:-----------------:|:-----------------------------:| +| - | Success | `Write-Output` | +| `error` | Error | `Write-Error` | +| `warn` | Warning | `Write-Warning` | +| `info` | Verbose | `Write-Verbose`, `Write-Host` | +| `debug` | Debug | `Write-Debug` | +| `trace` | Information | `Write-Information` | + +> [!IMPORTANT] +> Remember that _any_ error emitted from the script causes the resource and DSC to consider the +> script execution to have failed, even when the script continued after an error. + +For comprehensive examples of emitting messages from scripts, see +[Invoke the WindowsPowerShellScript resource with trace messaging][08]. + +## Requirements + +- The resource is only usable on a Windows system. + +## Capabilities + +The resource has the following capabilities: + +- `get` - You can use the resource to retrieve the actual state of an instance. +- `set` - You can use the resource to enforce the desired state for an instance. +- `test` - You can use the resource to test whether an instance is in the desired state. + +For more information about resource capabilities, see [DSC resource capabilities][00]. + +## Examples + +1. [Configure a system with the WindowsPowerShellScript resource][10] - Shows how to use this + resource in a configuration document. +1. [Invoke the WindowsPowerShellScript resource with input data][03] - Shows how to pass data to + this resource. +1. [Invoke the WindowsPowerShellScript resource with output data][09] - Shows how to return data + from this resource. +1. [Invoke the WindowsPowerShellScript resource with trace messaging][08] - Shows how to emit DSC + trace messages from this resource. + +## Properties + +The following list describes the properties for the resource. + +- **Instance properties:** The following properties are optional. + They define the desired state for an instance of the resource. + + - [getScript](#getscript) - The Windows PowerShell script to run during the **Get** operation. + - [setScript](#setscript) - The Windows PowerShell script to run during the **Set** operation. + - [testScript](#testscript) - The Windows PowerShell script to run during the **Test** operation. + - [input](#input) - Input data to pass to the Windows PowerShell scripts. + - [output](#output) - Output data returned from the Windows PowerShell scripts. + - [_inDesiredState](#_indesiredstate) - Indicates whether the resource instance is in the desired + state. + +### getScript + +
Expand for getScript property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines the Windows PowerShell script to execute during the **Get** operation. This property is +never returned by the resource. The resource invokes the script this property defines for the +**Get** operation and to populate the `beforeState` for a **Set** operation. + +This script should return the current state of the instance. The script can access input data and +should return relevant state information. _Every_ item the script emits to the PowerShell success +stream is inserted into the [`output`](#output) property. + +When possible, prefer emitting a single structured object to the success stream. This makes reading +the `actualState` for a **Get** operation result and the `beforeState` for a **Set** operation +result easier for users. + +### setScript + +
Expand for setScript property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines the Windows PowerShell script to execute during the **Set** operation. This script should +configure the system to match the desired state. The script can access input data and should +perform the necessary changes to bring the system into compliance. + +If the instance defines the [`getScript`](#getscript) property to return data then this property +_should_ return data in the same order and structure. The result object for the **Set** operation +includes `beforeState` (populated by the output for `getScript`) and `afterState` (populated by the +output for `setScript`). Keeping the output order and structure the same for both scripts enables +easier comparison of the changes in resource state. + +### testScript + +
Expand for testScript property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines the Windows PowerShell script to execute during the **Test** operation. This script should +determine whether the system is in the desired state and return appropriate state information. The +script can access input data and should return a single boolean value of `$true` or `$false`. + +The script should _not_ emit any other data for output. Emitting more data than a single boolean +value or emitting a non-boolean value causes the resource to raise an error. + +Instead, [emit messages](#emitting-messages) to indicate how and why the instance is out of the +desired state. + +> [!IMPORTANT] +> In version `0.1.0` for the resource, this script is _only_ invoked for the **Test** operation +> when you use the `dsc config test` or `dsc resource test` commands. When you invoke the **Set** +> operation the resource _always_ invokes the [`setScript`](#setscript) even when `testScript` +> would report that the resource is in the desired state. + +### input + +
Expand for input property metadata + +```yaml +Type : anyOf (string, boolean, integer, object, array, null) +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines input data to pass to the PowerShell scripts. This can be any of the following JSON data +types: + +- `string` +- `boolean` +- `integer` +- `object` +- `array` + +The input data is available to every script property and can be used to parameterize script +behavior. + +When passing input data to a script, always define the `params` keyword with a single named +parameter, like `params($inputData)`. The resource binds the value from the `input` property to +that parameter. + +The value for this property affects how it is passed to the PowerShell scripts for the resource: + +| JSON value type | Bound PowerShell parameter value | +|:---------------:|:--------------------------------:| +| `string` | `[String]` | +| `object` | `[PSCustomObject]` | +| `array` | `[Object[]]` | +| `integer` | `[Int64]` | +| `number` | Invalid † | +| `boolean` | `[Boolean]` | +| `null` | Invalid † | + +> [!NOTE] +> Passing a number with a fractional part, such as `1.23`, or `null` is invalid for the top-level +> value of the `input` field. However, you can pass numbers and `null` values nested as object +> properties or array items. +> +> For example, `input: 1.23` is invalid while `input: {"num": 1.23}` and `input: [1.23]` are valid. +> Similarly, `input: null` is invalid while `input: {nested: null}` and `input: [null]` are both +> valid. + +If you define your scriptblock parameters without providing a type for the input data, like +`params($inputData)`, the type for that parameter is exactly as described in the prior table. You +can also define a type for the parameter, which causes PowerShell to cast the input data to the +given type. For example, `params([string[]]$inputData)` will cast the value for `input` to an array +of strings. + +For comprehensive examples of how to use input data with this resource, see +[Invoke the WindowsPowerShellScript resource with input data][03]. + +### output + +
Expand for output property metadata + +```yaml +Type : array +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Defines output data returned from the Windows PowerShell scripts. This property contains the +results of script execution and can include any data that the scripts choose to return. + +Every object emitted to the PowerShell success output stream is inserted into the `output` for the +operation in the order that the scriptblock emits those objects. The emitted items are +automatically converted to JSON values by the resource. Don't use the `ConvertTo-Json` cmdlet to +transform the items yourself. + +When emitting objects with nested properties the resource will emit the object up 9 levels deep. +Objects with more deep nesting fail to serialize correctly into JSON. + +Where possible, limit the output data to the value you need. You can use the `Select-Object` cmdlet +to select only the required properties or create a custom object to represent the output data. + +> [!IMPORTANT] +> This resource doesn't populate the `output` property for failed scripts. The resource considers +> a script to have failed when it emits _any_ errors, even when those errors are explicitly handled. +> For more information, see the [Handling errors](#handling-errors) section of this documentation. + +Using the `Write-*` cmdlets to emit messages to PowerShell's other output streams doesn't populate +the `output` property. Instead, those messages are surfaced through DSC's tracing. For more +information, see the [Emitting messages](#emitting-messages) section of this documentation. + +For comprehensive examples of how to return output data with this resource, see +[Invoke the WindowsPowerShellScript resource with output data][09]. + +### _inDesiredState + +
Expand for _inDesiredState property metadata + +```yaml +Type : boolean +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +DefaultValue : null +``` + +
+ +Indicates whether the resource is in the desired state. This property is only returned when a +caller invokes the **Test** operation for the resource. The value of this property depends on +whether the resource defines the [`testScript](#testscript) property: + +1. When the resource instance defines `testScript`, DSC invokes that script and uses the boolean + result it returns as the value of this property. +1. When the resource instance doesn't define `testScript`, the value is `true`. + +## Instance validating schema + +The following snippet contains the JSON Schema that validates an instance of the resource. + +```json +{ + "type": "object", + "properties": { + "getScript": { + "type": ["string", "null"] + }, + "setScript": { + "type": ["string", "null"] + }, + "testScript": { + "type": ["string", "null"] + }, + "input": { + "type": ["string", "boolean", "integer", "object", "array", "null"] + }, + "output": { + "type": ["array", "null"] + }, + "_inDesiredState": { + "type": ["boolean", "null"], + "default": null + } + }, + "additionalProperties": false +} +``` + +## Exit codes + +The resource returns the following exit codes from operations: + +- [0](#exit-code-0) - Success +- [1](#exit-code-1) - PowerShell script execution failed +- [2](#exit-code-2) - PowerShell exception occurred +- [3](#exit-code-3) - Script had errors + +### Exit code 0 + +Indicates the resource operation completed without errors. + +### Exit code 1 + +Indicates the Windows PowerShell script execution failed. When the resource returns this exit code, +it also emits an error message with details about the execution failure. + +### Exit code 2 + +Indicates a Windows PowerShell exception occurred during script execution. When the resource +returns this exit code, it writes the error to the console. + +### Exit code 3 + +Indicates the script had errors, typically due to missing or invalid input data. This exit code is +commonly returned when required input parameters are not provided to the PowerShell scripts or when +the input data is in an unexpected format. + +## See also + +- [Microsoft.DSC.Transitional/RunCommandOnSet][12] +- [Microsoft.DSC.Transitional/PowerShellScript][13] + + +[00]: ../../../../../../concepts/resources/capabilities.md +[01]: ../PowerShellScript/index.md +[02]: /powershell/module/microsoft.powershell.core/about/about_functions_advanced_parameters#parameter-and-variable-validation-attributes +[03]: ./examples/invoke-with-input-data.md +[04]: /powershell/module/microsoft.powershell.core/about/about_preference_variables#erroractionpreference +[05]: /powershell/module/microsoft.powershell.core/about/about_commonparameters#-erroraction +[06]: /powershell/module/microsoft.powershell.core/about/about_try_catch_finally +[07]: ./examples/invoke-with-messaging.md#emitting-errors +[08]: ./examples/invoke-with-messaging.md +[09]: ./examples/invoke-with-output-data.md +[10]: ./examples/configure-with-script.md +[12]: ../RunCommandOnSet/index.md +[13]: ../PowerShellScript/index.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/examples/validate-in-a-configuration.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/examples/validate-in-a-configuration.md index e696911..0fefb62 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/examples/validate-in-a-configuration.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/examples/validate-in-a-configuration.md @@ -275,7 +275,9 @@ hadErrors: false ## Verify the desired state -DSC can use the resource to validate the operating system information in a configuration with the [dsc config test][03] command. When you use the `dsc config test` command, DSC invokes the **Test** operation against every resource in the configuration document. +DSC can use the resource to validate the operating system information in a configuration with the +[dsc config test][03] command. When you use the `dsc config test` command, DSC invokes the **Test** +operation against every resource in the configuration document. The `Microsoft/OSInfo` resource doesn't implement the [test operation][04]. It relies on the synthetic testing feature of DSC instead. The synthetic test uses a case-sensitive equivalency @@ -303,8 +305,9 @@ dsc config set --file .\osinfo.config.dsc.yaml --- The output depends on whether the operating system is 32-bit or 64-bit. In all cases, the -`changedProperties` field for the result is an empty list. The `Microsoft.DSC/Assertion` group resource -never changes system state and the `Microsoft/OSInfo` resource doesn't implement the **Set**** operation. +`changedProperties` field for the result is an empty list. The `Microsoft.DSC/Assertion` group +resource never changes system state and the `Microsoft/OSInfo` resource doesn't implement the +**Set**** operation. # [32-bit Linux](#tab/32bit/linux) diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/examples/validate-minimum-version.config.dsc.yaml b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/examples/validate-minimum-version.config.dsc.yaml new file mode 100644 index 0000000..e774cba --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/examples/validate-minimum-version.config.dsc.yaml @@ -0,0 +1,18 @@ +# yaml-language-server: $schema=https://aka.ms/dsc/schemas/v3/bundled/config/document.vscode.json +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: + - name: Operating System Assertion + type: Microsoft.DSC/Assertion + properties: + $schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json + resources: + - name: Minimum operating system version + type: Microsoft/OSInfo + properties: + version: '>= 10.0' + - name: Show operating system + type: Microsoft.DSC.Debug/Echo + properties: + output: 'The operating system meets the minimum version requirement.' + dependsOn: + - "[resourceId('Microsoft.DSC/Assertion', 'Operating System Assertion')]" diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/examples/validate-minimum-version.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/examples/validate-minimum-version.md new file mode 100644 index 0000000..4cbdc58 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/examples/validate-minimum-version.md @@ -0,0 +1,80 @@ +--- +description: Validate a minimum operating system version with Microsoft/OSInfo +ms.date: 07/11/2026 +ms.topic: reference +title: Validate a minimum operating system version +--- + +# Validate a minimum operating system version + +This example uses the `Microsoft/OSInfo` resource with the `Microsoft.DSC/Assertion` group +resource to verify that the operating system version meets a minimum requirement before DSC runs +another resource. + +> [!IMPORTANT] +> The `osinfo` command and `Microsoft/OSInfo` resource are a proof-of-concept example for use with +> DSC. Don't use it in production. + +## Definition + +The **Operating System Assertion** group contains a `Microsoft/OSInfo` resource instance with the +version constraint `>= 10.0`. The `Microsoft.DSC/Assertion` resource always invokes **Test** for +nested instances. If the operating system is earlier than version `10.0`, the configuration fails +and DSC doesn't invoke **Show operating system**. + +:::code language="yaml" source="validate-minimum-version.config.dsc.yaml"::: + +## Running the configuration + +Run the configuration with the [dsc config set][01] command: + +```bash +dsc config set --file ./validate-minimum-version.config.dsc.yaml +``` + +On an operating system whose version is at least `10.0`, DSC returns successful results for both +the assertion group and the dependent echo resource: + +```yaml +results: +- name: Operating System Assertion + type: Microsoft.DSC/Assertion + result: + beforeState: + - name: Minimum operating system version + type: Microsoft/OSInfo + result: + actualState: + family: Windows + version: 10.0.26200 + _inDesiredState: true + afterState: + - name: Minimum operating system version + type: Microsoft/OSInfo + result: + desiredState: + version: '>= 10.0' + actualState: + family: Windows + version: 10.0.26200 + edition: Windows 11 + bitness: 64 + architecture: x86_64 + _inDesiredState: true + inDesiredState: true + differingProperties: [] + changedProperties: [] +- name: Show operating system + type: Microsoft.DSC.Debug/Echo + result: + beforeState: + output: The operating system meets the minimum version requirement. + afterState: + output: The operating system meets the minimum version requirement. + changedProperties: null +messages: [] +hadErrors: false +``` + + +[01]: ../../../../cli/config/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/examples/validate-with-dsc-resource.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/examples/validate-with-dsc-resource.md index b229a31..194efe9 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/examples/validate-with-dsc-resource.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/examples/validate-with-dsc-resource.md @@ -2,7 +2,7 @@ description: > Validate operating system information with the Microsoft/OSInfo DSC Resource and the dsc resource commands. -ms.date: 03/25/2025 +ms.date: 07/12/2026 ms.topic: reference title: Validate operating system information with dsc resource --- @@ -32,11 +32,10 @@ dsc resource get -r Microsoft/OSInfo ```yaml actualState: - $id: https://developer.microsoft.com/json-schemas/dsc/os_info/20230303/Microsoft.Dsc.OS_Info.schema.json family: Linux version: '20.04' codename: focal - bitness: '64' + bitness: 64 architecture: x86_64 ``` @@ -49,10 +48,9 @@ dsc resource get -r Microsoft/OSInfo ```yaml actualState: - $id: https://developer.microsoft.com/json-schemas/dsc/os_info/20230303/Microsoft.Dsc.OS_Info.schema.json - family: MacOS + family: macOS version: 13.5.0 - bitness: '64' + bitness: 64 architecture: arm64 ``` @@ -64,11 +62,11 @@ dsc resource get --resource Microsoft/OSInfo ```yaml actualState: - $id: https://developer.microsoft.com/json-schemas/dsc/os_info/20230303/Microsoft.Dsc.OS_Info.schema.json family: Windows version: 10.0.22621 edition: Windows 11 Enterprise - bitness: '64' + bitness: 64 + architecture: x86_64 ``` --- @@ -79,10 +77,13 @@ DSC can use the resource to validate the operating system information. When you [dsc resource test][02] command, input JSON representing the desired state of the instance is required. The JSON must define at least one instance property to validate. -The resource doesn't implement the [test operation][03]. It relies on the synthetic testing feature -of DSC instead. The synthetic test uses a case-sensitive equivalency comparison between the actual -state of the instance properties and the desired state. If any property value isn't an exact match, -DSC considers the instance to be out of the desired state. +The resource implements the [test operation][03]. The command passes the desired state to the +resource over stdin and the resource returns the actual operating system information with an +`_inDesiredState` value. DSC returns that value as `inDesiredState` in the test result. + +All properties except `version` use case-sensitive equality comparison. For `version`, you can use +an exact version or a constraint with `>`, `<`, `=`, `>=`, or `<=`. For more information, see the +[version property][04] reference. # [Linux](#tab/linux) @@ -90,49 +91,46 @@ This test checks whether the `family` property for the instance is `Linux`. It p state for the instance to the command from stdin with the `--file` (`-f`) option. ```bash -invalid_instance='{"family": "Linux"}' -echo $invalid_instance | dsc resource test -r "${resource}" -f - +valid_instance='{"family": "Linux", "version": ">= 20.04"}' +echo $valid_instance | dsc resource test -r Microsoft/OSInfo -f - ``` ```yaml desiredState: - family: linux + family: Linux + version: '>= 20.04' actualState: - $id: https://developer.microsoft.com/json-schemas/dsc/os_info/20230303/Microsoft.Dsc.OS_Info.schema.json family: Linux version: '20.04' codename: focal - bitness: '64' + bitness: 64 architecture: x86_64 -inDesiredState: false -differingProperties: -- family + _inDesiredState: true +inDesiredState: true +differingProperties: [] ``` -The result shows that the resource is out of the desired state because the actual state of the -`family` property wasn't case-sensitively equal to the desired state. - -The next test validates that the operating system is a 64-bit Linux operating system. It passes -the desired state for the instance to the command with the `--input` (`-i`) option. +The result shows that the resource evaluated both the family and version constraint successfully. +The next test demonstrates a case-sensitive mismatch. ```bash -valid_instance='{ "family": "Linux", "bitness": "64" }' -echo $valid_instance | dsc resource test -r Microsoft/OSInfo -i $valid_instance +invalid_instance='{ "family": "linux" }' +dsc resource test -r Microsoft/OSInfo -i $invalid_instance ``` ```yaml desiredState: - family: Linux - bitness: '64' + family: linux actualState: - $id: https://developer.microsoft.com/json-schemas/dsc/os_info/20230303/Microsoft.Dsc.OS_Info.schema.json family: Linux version: '20.04' codename: focal - bitness: '64' + bitness: 64 architecture: x86_64 -inDesiredState: true -differingProperties: [] + _inDesiredState: false +inDesiredState: false +differingProperties: +- family ``` # [macOS](#tab/macos) @@ -141,100 +139,94 @@ This test checks whether the `family` property for the instance is `macOS`. It p state for the instance to the command from stdin with the `--file` (`-f`) option. ```zsh -invalid_instance='{"family": "macOS"}' -echo $invalid_instance | dsc resource test -r Microsoft/OSInfo -f - +valid_instance='{"family": "macOS", "version": ">= 13.0"}' +echo $valid_instance | dsc resource test -r Microsoft/OSInfo -f - ``` ```yaml desiredState: family: macOS + version: '>= 13.0' actualState: - $id: https://developer.microsoft.com/json-schemas/dsc/os_info/20230303/Microsoft.Dsc.OS_Info.schema.json - family: MacOS + family: macOS version: 13.5.0 - bitness: '64' + bitness: 64 architecture: arm64 -inDesiredState: false -differingProperties: -- family + _inDesiredState: true +inDesiredState: true +differingProperties: [] ``` -The result shows that the resource is out of the desired state because the actual state of the -`family` property wasn't case-sensitively equal to the desired state. - -The next test validates that the operating system is a 64-bit macOS operating system. It passes the -desired state for the instance to the command with the `--input` (`-i`) option. +The result shows that the resource evaluates the version constraint in addition to the family. +The next test demonstrates a case-sensitive mismatch. ```zsh -valid_instance='{ "family": "MacOS", "bitness": "64" }' -dsc resource test -r Microsoft/OSInfo -i $valid_instance +invalid_instance='{ "family": "MacOS" }' +dsc resource test -r Microsoft/OSInfo -i $invalid_instance ``` ```yaml desiredState: family: MacOS - bitness: '64' actualState: - $id: https://developer.microsoft.com/json-schemas/dsc/os_info/20230303/Microsoft.Dsc.OS_Info.schema.json - family: MacOS + family: macOS version: 13.5.0 - bitness: '64' + bitness: 64 architecture: arm64 -inDesiredState: true -differingProperties: [] + _inDesiredState: false +inDesiredState: false +differingProperties: +- family ``` # [Windows](#tab/windows) -This test checks whether the `family` property for the instance is `windows`. It passes the desired -state for the instance to the command from stdin with the `--file` (`-f`) option. +This test checks whether the `family` property for the instance is `Windows` and whether the +operating system version is at least `10.0`. It passes the desired state for the instance to the +command from stdin with the `--file` (`-f`) option. ```powershell -$invalidInstance = @{ family = 'windows' } | ConvertTo-JSON -$invalidInstance | dsc resource test --resource Microsoft/OSInfo --file - +$validInstance = @{ family = 'Windows'; version = '>= 10.0' } | ConvertTo-JSON +$validInstance | dsc resource test --resource Microsoft/OSInfo --file - ``` ```yaml desiredState: - family: windows + family: Windows + version: '>= 10.0' actualState: - $id: https://developer.microsoft.com/json-schemas/dsc/os_info/20230303/Microsoft.Dsc.OS_Info.schema.json family: Windows version: 10.0.22621 edition: Windows 11 Enterprise - bitness: "64" -inDesiredState: false -differingProperties: -- family + bitness: 64 + architecture: x86_64 + _inDesiredState: true +inDesiredState: true +differingProperties: [] ``` -The result shows that the resource is out of the desired state because the actual state of the -`family` property wasn't case-sensitively equal to the desired state. - -The next test validates that the operating system is a 64-bit Windows operating system. It passes -the desired state for the instance to the command with the `--input` (`-i`) option. +The result shows that the resource evaluated both the family and version constraint successfully. +The next test demonstrates a case-sensitive mismatch. ```powershell -$validInstance = @{ - family = 'Windows' - bitness = '64' -} | ConvertTo-JSON +$invalidInstance = @{ family = 'windows' } | ConvertTo-JSON -dsc resource test --resource Microsoft/OSInfo --input $validInstance +dsc resource test --resource Microsoft/OSInfo --input $invalidInstance ``` ```yaml desiredState: - family: Windows - bitness: '64' + family: windows actualState: - $id: https://developer.microsoft.com/json-schemas/dsc/os_info/20230303/Microsoft.Dsc.OS_Info.schema.json family: Windows version: 10.0.22621 edition: Windows 11 Enterprise - bitness: "64" -inDesiredState: true -differingProperties: [] + bitness: 64 + architecture: x86_64 + _inDesiredState: false +inDesiredState: false +differingProperties: +- family ``` --- @@ -243,3 +235,4 @@ differingProperties: [] [01]: ../../../../cli/resource/get.md [02]: ../../../../cli/resource/test.md [03]: ../../../../../concepts/resources/overview.md#test-operations +[04]: ../index.md#version diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/index.md index 9e72cd4..8658c30 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/index.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/OSInfo/index.md @@ -1,6 +1,6 @@ --- description: Microsoft/OSInfo DSC resource reference documentation -ms.date: 03/25/2025 +ms.date: 07/11/2026 ms.topic: reference title: Microsoft/OSInfo --- @@ -46,10 +46,9 @@ The `Microsoft/OSInfo` resource enables you to assert whether a machine meets cr the operating system. The resource is only capable of assertions. It doesn't implement the set operation and can't configure the operating system. -The resource doesn't implement the [test operation][01]. It relies on the synthetic testing feature -of DSC instead. The synthetic test uses a case-sensitive equivalency comparison between the actual -state of the instance properties and the desired state. If any property value isn't an exact match, -DSC considers the instance to be out of the desired state. +The resource implements the [test operation][01]. The test operation compares every specified +instance property to the actual operating system information. The `version` property supports +version comparison constraints; all other properties use case-sensitive equality comparison. The instance properties returned by this resource depend on the operating system `family` as listed in the following table: @@ -57,8 +56,8 @@ listed in the following table: | `family` | Returned instance properties | | :-------: | :--------------------------------------------------------- | | `Linux` | `architecture`, `bitness`, `codename`, `family`, `version` | -| `MacOS` | `architecture`, `bitness`, `family`, `version` | -| `Windows` | `bitness`, `edition`, `family`, `version` | +| `macOS` | `architecture`, `bitness`, `family`, `version` | +| `Windows` | `architecture`, `bitness`, `edition`, `family`, `version` | > [!NOTE] > This resource is installed with DSC itself on all platforms. @@ -75,11 +74,9 @@ None. This resource has the following capabilities: - `get` - You can use the resource to retrieve the actual state of an instance. +- `test` - You can use the resource to test whether an instance is in the desired state. - `export` - You can use the resource to retrieve the actual state of every instance. -This resource uses the synthetic test functionality of DSC to determine whether an instance is -in the desired state. - This resource doesn't have the `set` capability. You can't use it to modify the state of a system. For more information about resource capabilities, see @@ -89,6 +86,7 @@ For more information about resource capabilities, see 1. [Validate operating system information with dsc resource][03] 1. [Validate operating system information in a configuration][04] +1. [Validate a minimum operating system version in a configuration][07] ## Properties @@ -100,7 +98,7 @@ The following list describes the properties for the resource. - **Instance properties:** The following properties are optional. They define the desired state for an instance of the resource. - - [architecture](#architecture) - Defines the processor architecture on Linux and macOS systems. + - [architecture](#architecture) - Defines the processor architecture. - [bitness](#bitness) - Defines whether the operating system is 32-bit or 64-bit. - [codename](#codename) - Defines the codename for Linux systems. - [edition](#edition) - Defines the edition for Windows systems. @@ -126,26 +124,24 @@ IsWriteOnly : false -Defines the processor architecture as reported by `uname -m` on the operating system. The resource -doesn't return this property for Windows machines. +Defines the processor architecture reported by the operating system. ### bitness
Expand for bitness property metadata ```yaml -Type : string +Type : integer IsRequired : false IsKey : false IsReadOnly : false IsWriteOnly : false -ValidValues : ['32', '64', unknown] +ValidValues : [32, 64] ```
-Defines whether the operating system is a 32-bit or 64-bit operating system. When the resource -can't determine this information, it returns a value of `unknown`. +Defines whether the operating system is a 32-bit or 64-bit operating system. ### codename @@ -210,7 +206,16 @@ IsWriteOnly : false -Defines the version of the operating system as a string. +Defines the version of the operating system as a string. During the **Test** operation, this +property accepts an exact version string or a version comparison constraint. + +The supported comparison operators are `>`, `<`, `=`, `>=`, and `<=`. Whitespace between the +operator and version is optional. When you omit an operator, the resource performs an exact string +comparison. For example, `10.0`, `=10.0`, and `= 10.0` require an exact match, while `>= 10.0` +requires the operating system version to be at least `10.0`. + +The version value after an operator must begin with a digit. Unsupported operators, such as `~=`, +are treated as literal exact-match values and won't match a normal operating system version. ### $id @@ -256,3 +261,4 @@ operation failure. [04]: examples/validate-in-a-configuration.md [05]: ../../../../concepts/resources/properties.md#read-only-resource-properties [06]: ../../../tools/osinfo.md +[07]: examples/validate-minimum-version.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FeatureOnDemandList/examples/export-features-on-demand.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FeatureOnDemandList/examples/export-features-on-demand.md new file mode 100644 index 0000000..397238a --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FeatureOnDemandList/examples/export-features-on-demand.md @@ -0,0 +1,151 @@ +--- +description: > + Examples showing how to export and filter Windows Features on Demand (capabilities) using the + Microsoft.Windows/FeatureOnDemandList resource. +ms.date: 04/21/2026 +ms.topic: reference +title: Export Features on Demand +--- + +# Export Features on Demand + +This example shows how you can use the `Microsoft.Windows/FeatureOnDemandList` resource to +enumerate Windows Features on Demand (capabilities) on a system, optionally filtering the results +by identity, state, display name, or description. + +> [!IMPORTANT] +> All operations with `Microsoft.Windows/FeatureOnDemandList` require an elevated (administrator) +> session. Run your terminal as administrator before executing these commands. + +## Export all capabilities + +To retrieve a complete list of all capabilities on the system, use the [dsc resource export][01] +command without any input. + +```powershell +dsc resource export --resource Microsoft.Windows/FeatureOnDemandList +``` + +DSC returns a configuration document that includes all capabilities and their current states: + +```yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: +- name: Microsoft.Windows/FeatureOnDemandList + type: Microsoft.Windows/FeatureOnDemandList + properties: + capabilities: + - identity: OpenSSH.Client~~~~0.0.1.0 + state: Installed + - identity: OpenSSH.Server~~~~0.0.1.0 + state: NotPresent + - identity: Language.Basic~~~en-US~0.0.1.0 + state: Installed + # ... additional capabilities +``` + +> [!NOTE] +> When exporting without filters, the resource uses a fast enumeration path that returns only +> `identity` and `state` for each capability. To retrieve additional properties such as +> `displayName`, `description`, `downloadSize`, and `installSize`, use an export filter as shown +> in the examples below. + +## Export only installed capabilities + +To list only the capabilities currently installed on the system, provide a filter with +`state: Installed`. + +```powershell +$filter = @{ + capabilities = @( + @{ state = 'Installed' } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource export --resource Microsoft.Windows/FeatureOnDemandList --input $filter +``` + +```yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: +- name: Microsoft.Windows/FeatureOnDemandList + type: Microsoft.Windows/FeatureOnDemandList + properties: + capabilities: + - identity: OpenSSH.Client~~~~0.0.1.0 + state: Installed + - identity: Language.Basic~~~en-US~0.0.1.0 + state: Installed + # ... additional installed capabilities +``` + +## Export capabilities by identity pattern + +You can filter capabilities by identity using wildcard (`*`) patterns. The match is +case-insensitive. + +```powershell +$filter = @{ + capabilities = @( + @{ identity = 'OpenSSH*' } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource export --resource Microsoft.Windows/FeatureOnDemandList --input $filter +``` + +```yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: +- name: Microsoft.Windows/FeatureOnDemandList + type: Microsoft.Windows/FeatureOnDemandList + properties: + capabilities: + - identity: OpenSSH.Client~~~~0.0.1.0 + state: Installed + - identity: OpenSSH.Server~~~~0.0.1.0 + state: NotPresent +``` + +## Export capabilities with full details + +To retrieve full details including `displayName`, `description`, `downloadSize`, and +`installSize`, include those properties as filters. A wildcard (`*`) in a filter property matches +all values for that field and triggers the full-info lookup. + +```powershell +$filter = @{ + capabilities = @( + @{ + identity = 'OpenSSH*' + displayName = '*' + } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource export --resource Microsoft.Windows/FeatureOnDemandList --input $filter +``` + +```yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: +- name: Microsoft.Windows/FeatureOnDemandList + type: Microsoft.Windows/FeatureOnDemandList + properties: + capabilities: + - identity: OpenSSH.Client~~~~0.0.1.0 + state: Installed + displayName: OpenSSH Client + description: Open SSH-based secure shell (SSH) client... + downloadSize: 0 + installSize: 4894720 + - identity: OpenSSH.Server~~~~0.0.1.0 + state: NotPresent + displayName: OpenSSH Server + description: Open SSH-based secure shell (SSH) server... + downloadSize: 1468500 + installSize: 1839104 +``` + + +[01]: ../../../../../cli/resource/export.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FeatureOnDemandList/examples/get-feature-on-demand.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FeatureOnDemandList/examples/get-feature-on-demand.md new file mode 100644 index 0000000..08ec70a --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FeatureOnDemandList/examples/get-feature-on-demand.md @@ -0,0 +1,139 @@ +--- +description: > + Examples showing how to retrieve the current state of Windows features on demand (capabilities) + using the Microsoft.Windows/FeatureOnDemandList resource. +ms.date: 04/21/2026 +ms.topic: reference +title: Get feature on demand state +--- + +# Get feature on demand state + +This example shows how you can use the `Microsoft.Windows/FeatureOnDemandList` resource to +retrieve the current state of Windows features on demand (capabilities). The examples use +`OpenSSH.Client~~~~0.0.1.0` as a representative capability identity. + +> [!IMPORTANT] +> All operations with `Microsoft.Windows/FeatureOnDemandList` require an elevated (administrator) +> session. Run your terminal as administrator before executing these commands. + +## Find capability identity strings + +Before you can get the state of a capability, you need its identity string. Use the following +command to list all capabilities and their identities: + +```powershell +dism /Online /Get-Capabilities /Format:Table +``` + +Capability identities follow the format `CapabilityName~~~~LanguageTag~Version`, for example: + +- `OpenSSH.Client~~~~0.0.1.0` +- `OpenSSH.Server~~~~0.0.1.0` +- `Language.Basic~~~en-US~0.0.1.0` + +## Get a single capability + +The following snippet shows how to retrieve the state of the OpenSSH client capability using the +[dsc resource get][01] command. + +```powershell +$instance = @{ + capabilities = @( + @{ identity = 'OpenSSH.Client~~~~0.0.1.0' } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource get --resource Microsoft.Windows/FeatureOnDemandList --input $instance +``` + +When the capability is installed, DSC returns output similar to the following: + +```yaml +actualState: + capabilities: + - identity: OpenSSH.Client~~~~0.0.1.0 + state: Installed + displayName: OpenSSH Client + description: >- + Open SSH-based secure shell (SSH) client, required for secure key management and access + to remote machines. + downloadSize: 0 + installSize: 4894720 +``` + +When the capability is not installed, the `state` field reads `NotPresent`: + +```yaml +actualState: + capabilities: + - identity: OpenSSH.Client~~~~0.0.1.0 + state: NotPresent + displayName: OpenSSH Client + description: >- + Open SSH-based secure shell (SSH) client, required for secure key management and access + to remote machines. + downloadSize: 4026000 + installSize: 4894720 +``` + +## Get multiple capabilities in a single request + +You can retrieve the state of multiple capabilities in a single call by including multiple entries +in the `capabilities` array. + +```powershell +$instance = @{ + capabilities = @( + @{ identity = 'OpenSSH.Client~~~~0.0.1.0' } + @{ identity = 'OpenSSH.Server~~~~0.0.1.0' } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource get --resource Microsoft.Windows/FeatureOnDemandList --input $instance +``` + +```yaml +actualState: + capabilities: + - identity: OpenSSH.Client~~~~0.0.1.0 + state: Installed + displayName: OpenSSH Client + description: Open SSH-based secure shell (SSH) client... + downloadSize: 0 + installSize: 4894720 + - identity: OpenSSH.Server~~~~0.0.1.0 + state: NotPresent + displayName: OpenSSH Server + description: Open SSH-based secure shell (SSH) server... + downloadSize: 1468500 + installSize: 1839104 +``` + +## Get a non-existent capability + +When you request a capability identity that is not recognized by DISM, the resource returns +`_exist: false` instead of raising an error. + +```powershell +$instance = @{ + capabilities = @( + @{ identity = 'NonExistent.Capability~~~~0.0.1.0' } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource get --resource Microsoft.Windows/FeatureOnDemandList --input $instance +``` + +```yaml +actualState: + capabilities: + - identity: NonExistent.Capability~~~~0.0.1.0 + _exist: false +``` + +The `_exist: false` response indicates the capability identity is not recognized by DISM on this +system. + + +[01]: ../../../../../cli/resource/get.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FeatureOnDemandList/examples/install-remove-feature-on-demand.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FeatureOnDemandList/examples/install-remove-feature-on-demand.md new file mode 100644 index 0000000..30631c8 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FeatureOnDemandList/examples/install-remove-feature-on-demand.md @@ -0,0 +1,166 @@ +--- +description: > + Examples showing how to install and remove Windows features on demand (capabilities) using the + Microsoft.Windows/FeatureOnDemandList resource. +ms.date: 04/21/2026 +ms.topic: reference +title: Install and remove features on demand +--- + +# Install and remove features on demand + +This example shows how you can use the `Microsoft.Windows/FeatureOnDemandList` resource to install +and remove Windows features on demand (capabilities). The examples use +`OpenSSH.Client~~~~0.0.1.0` as a representative capability identity. + +> [!IMPORTANT] +> All operations with `Microsoft.Windows/FeatureOnDemandList` require an elevated (administrator) +> session. Run your terminal as administrator before executing these commands. +> +> Installing a capability may require internet access or an appropriately configured Windows Update +> or WSUS source. Installing large capabilities may take several minutes to complete. + +## Install a capability + +To install a capability, set its `state` to `Installed` and use the [dsc resource set][01] +command. + +```powershell +$instance = @{ + capabilities = @( + @{ + identity = 'OpenSSH.Client~~~~0.0.1.0' + state = 'Installed' + } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource set --resource Microsoft.Windows/FeatureOnDemandList --input $instance +``` + +When the resource installs the capability, DSC returns the updated state: + +```yaml +beforeState: + capabilities: + - identity: OpenSSH.Client~~~~0.0.1.0 + state: NotPresent + displayName: OpenSSH Client + description: Open SSH-based secure shell (SSH) client... + downloadSize: 4026000 + installSize: 4894720 +afterState: + capabilities: + - identity: OpenSSH.Client~~~~0.0.1.0 + state: Installed + displayName: OpenSSH Client + description: Open SSH-based secure shell (SSH) client... + downloadSize: 0 + installSize: 4894720 +changedProperties: +- capabilities +``` + +If a system restart is required to complete the installation, the response includes a +`_restartRequired` property at the top level: + +```yaml +afterState: + _restartRequired: + - system: MYCOMPUTER + capabilities: + - identity: SomeCapability~~~~0.0.1.0 + state: InstallPending + ... +changedProperties: +- capabilities +``` + +## Remove a capability + +To remove a capability, set its `state` to `NotPresent` and use the [dsc resource set][01] command. + +```powershell +$instance = @{ + capabilities = @( + @{ + identity = 'OpenSSH.Client~~~~0.0.1.0' + state = 'NotPresent' + } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource set --resource Microsoft.Windows/FeatureOnDemandList --input $instance +``` + +```yaml +beforeState: + capabilities: + - identity: OpenSSH.Client~~~~0.0.1.0 + state: Installed + displayName: OpenSSH Client + description: Open SSH-based secure shell (SSH) client... + downloadSize: 0 + installSize: 4894720 +afterState: + capabilities: + - identity: OpenSSH.Client~~~~0.0.1.0 + state: NotPresent + displayName: OpenSSH Client + description: Open SSH-based secure shell (SSH) client... + downloadSize: 4026000 + installSize: 4894720 +changedProperties: +- capabilities +``` + +## Manage multiple capabilities in a single operation + +You can install or remove multiple capabilities in a single **Set** call by specifying multiple +entries in the `capabilities` array. The resource processes each entry independently. + +```powershell +$instance = @{ + capabilities = @( + @{ + identity = 'OpenSSH.Client~~~~0.0.1.0' + state = 'Installed' + } + @{ + identity = 'OpenSSH.Server~~~~0.0.1.0' + state = 'NotPresent' + } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource set --resource Microsoft.Windows/FeatureOnDemandList --input $instance +``` + +## Use in a configuration document + +You can also use the resource in a DSC configuration document to declaratively manage capabilities +across a system. + +```yaml +# features-on-demand.config.dsc.yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: + - name: Manage OpenSSH capabilities + type: Microsoft.Windows/FeatureOnDemandList + properties: + capabilities: + - identity: OpenSSH.Client~~~~0.0.1.0 + state: Installed + - identity: OpenSSH.Server~~~~0.0.1.0 + state: NotPresent +``` + +Apply the configuration with the [dsc config set][02] command: + +```powershell +dsc config set --file ./features-on-demand.config.dsc.yaml +``` + + +[01]: ../../../../../cli/resource/set.md +[02]: ../../../../../cli/config/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FeatureOnDemandList/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FeatureOnDemandList/index.md new file mode 100644 index 0000000..1e5e0bb --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FeatureOnDemandList/index.md @@ -0,0 +1,380 @@ +--- +description: Microsoft.Windows/FeatureOnDemandList resource reference documentation +ms.date: 04/21/2026 +ms.topic: reference +title: Microsoft.Windows/FeatureOnDemandList +--- + +# Microsoft.Windows/FeatureOnDemandList + +## Synopsis + +Manage Windows features on demand (capabilities) using the DISM API. + +## Metadata + +```yaml +Version : 0.1.0 +Kind : resource +Tags : [Windows, dism, capability, featureondemand, fod] +Author : Microsoft +``` + +## Instance definition syntax + +```yaml +resources: + - name: + type: Microsoft.Windows/FeatureOnDemandList + properties: + # Required properties + capabilities: + - identity: string + # Instance properties + state: Installed | NotPresent +``` + +## Description + +The `Microsoft.Windows/FeatureOnDemandList` resource enables you to idempotently manage Windows +features on demand (also known as capabilities) using the DISM API. Features on demand are optional +Windows components that are not part of the base OS image and may need to be downloaded from +Windows Update or a local source before use. Examples include language packs, accessibility tools, +the OpenSSH client and server, and developer tools like the RSAT (Remote Server Administration +Tools) suite. + +The resource can: + +- Retrieve the current state of one or more capabilities by identity. +- Install capabilities (`Installed`), downloading them from Windows Update if necessary. +- Remove capabilities from the system (`NotPresent`). +- Export a list of all capabilities on the system, optionally filtered by identity, state, display + name, or description. + +> [!NOTE] +> This resource is installed with DSC itself on Windows systems. +> +> You can update this resource by updating DSC. When you update DSC, the updated version of this +> resource is automatically available. + +## Requirements + +- The resource is only usable on a Windows system. +- All operations require an elevated (administrator) process context. +- Installing capabilities may require internet access or a configured Windows Update / WSUS source. + +## Capabilities + +The resource has the following capabilities: + +- `get` - You can use the resource to retrieve the actual state of one or more capability + instances. +- `set` - You can use the resource to enforce the desired state for one or more capability + instances. +- `export` - You can use the resource to enumerate all capabilities on the system, with optional + filtering. + +This resource uses the synthetic test functionality of DSC to determine whether an instance is in +the desired state. For more information about resource capabilities, see +[DSC resource capabilities][01]. + +## Examples + +1. [Get feature on demand state][02] - Shows how to retrieve the current state of a Windows + capability. +1. [Install and remove features on demand][03] - Shows how to install and remove Windows + capabilities using the `dsc resource set` command. +1. [Export features on demand][04] - Shows how to enumerate all capabilities on the system, with + and without filters. + +## Properties + +The following list describes the properties for the resource. + +- **Required properties:** The following properties are always + required when defining an instance of the resource. + + - [capabilities](#capabilities) - An array of capability entries. + +- **Read-only properties:** The resource returns the following + properties, but they aren't configurable. For more information about read-only properties, see + the "Read-only resource properties" section in [DSC resource properties][05]. + + - [_restartRequired](#_restartrequired) - Indicates that a system restart is required to complete + the state change. + +### capabilities + +
Expand for capabilities property metadata + +```yaml +Type : array +IsRequired : true +IsKey : false +IsReadOnly : false +``` + +
+ +An array of capability entries. Each entry is an object describing a Windows capability (Feature on +Demand). For the **Get** operation, each entry must specify [`identity`](#identity). For the **Set** +operation, each entry must specify both [`identity`](#identity) and [`state`](#state). For the +**Export** operation, the array is optional and each entry can filter results using +[`identity`](#identity), [`state`](#state), [`displayName`](#displayname), or +[`description`](#description) with wildcard support. + +Each entry in `capabilities` has the following properties: + +- [identity](#identity) - The identity string of the capability. +- [_exist](#_exist) - Indicates whether the capability is recognized by DISM. +- [state](#state) - The current or desired state of the capability. +- [displayName](#displayname) - The display name of the capability. +- [description](#description) - The description of the capability. +- [downloadSize](#downloadsize) - The download size of the capability in bytes. +- [installSize](#installsize) - The install size of the capability in bytes. + +#### identity + +
Expand for capabilities[*].identity property metadata + +```yaml +Type : string +IsRequired : true (get, set) / false (export) +IsKey : false +IsReadOnly : false +``` + +
+ +The identity string that uniquely identifies the Windows capability. For **Get** and **Set** +operations, this property is required for each entry. For **Export** operations, it's optional and +supports wildcard (`*`) patterns for case-insensitive filtering. + +Capability identities typically follow the format `CapabilityName~~~~LanguageTag~Version`, for +example `OpenSSH.Client~~~~0.0.1.0` or `Language.Basic~~~en-US~0.0.1.0`. + +Use the `dism /Online /Get-Capabilities` command to list available capability identities on your +system. + +#### _exist + +
Expand for capabilities[*]._exist property metadata + +```yaml +Type : boolean +IsRequired : false +IsKey : false +IsReadOnly : true +``` + +
+ +Indicates whether the capability exists on the system. The resource sets this property to `false` +in the **Get** response when the requested `identity` is not recognized by DISM. When `_exist` is +`false`, the `state`, `displayName`, `description`, `downloadSize`, and `installSize` properties +are not returned. + +#### state + +
Expand for capabilities[*].state property metadata + +```yaml +Type : string +IsRequired : true (set) / false (get, export) +IsKey : false +IsReadOnly : false (set input) / true (get/export output) +ValidValues : [NotPresent, UninstallPending, Staged, Removed, Installed, + InstallPending, Superseded, PartiallyInstalled] +SetValues : [Installed, NotPresent] +``` + +
+ +The state of the capability. **Get** and **Export** operations return one of the eight DISM +capability state values. **Set** operations accept only the following two values as desired state: + +| Value | Description | +|:-------------|:-------------------------------------------------------------------------------| +| `Installed` | The capability is installed. The resource installs it if not already present. | +| `NotPresent` | The capability is removed from the system. | + +The following table describes all possible state values returned by **Get** and **Export**: + +| Value | Description | +|:---------------------|:--------------------------------------------------------------------------| +| `NotPresent` | The capability is not installed and not staged. | +| `UninstallPending` | A removal operation is pending, requiring a restart to complete. | +| `Staged` | The capability payload is on disk but the capability is not installed. | +| `Removed` | The capability has been removed. | +| `Installed` | The capability is fully installed and operational. | +| `InstallPending` | An install operation is pending, requiring a restart to complete. | +| `Superseded` | The capability has been replaced by another component. | +| `PartiallyInstalled` | The capability is only partially installed. | + +#### displayName + +
Expand for capabilities[*].displayName property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : true +``` + +
+ +The human-readable display name of the capability. This property is returned by **Get** and +**Export** operations. For **Export** operations, you can specify this property as a filter value +with wildcard (`*`) support for case-insensitive matching. + +#### description + +
Expand for capabilities[*].description property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : true +``` + +
+ +A brief description of the capability. This property is returned by **Get** and **Export** +operations. For **Export** operations, you can specify this property as a filter value with +wildcard (`*`) support for case-insensitive matching. + +#### downloadSize + +
Expand for capabilities[*].downloadSize property metadata + +```yaml +Type : integer +IsRequired : false +IsKey : false +IsReadOnly : true +``` + +
+ +The size in bytes that must be downloaded to install the capability. This property is returned by +**Get** and **Export** operations. + +#### installSize + +
Expand for capabilities[*].installSize property metadata + +```yaml +Type : integer +IsRequired : false +IsKey : false +IsReadOnly : true +``` + +
+ +The size in bytes that the capability occupies on disk after installation. This property is returned +by **Get** and **Export** operations. + +### _restartRequired + +
Expand for _restartRequired property metadata + +```yaml +Type : array +IsRequired : false +IsKey : false +IsReadOnly : true +``` + +
+ +Returned at the top level of the **Set** operation response when DISM reports that a system restart +is required to complete the requested state changes. Each entry in the array is an object with a +`system` property containing the name of the computer. + +When no restart is required, this property is omitted from the response. + +## Instance validating schema + +The following snippet contains the JSON Schema that validates an instance of the resource. + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "required": ["capabilities"], + "additionalProperties": false, + "properties": { + "_restartRequired": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + } + }, + "capabilities": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "identity": { "type": "string" }, + "_exist": { "type": "boolean" }, + "state": { + "type": "string", + "enum": [ + "NotPresent", "UninstallPending", "Staged", "Removed", + "Installed", "InstallPending", "Superseded", "PartiallyInstalled" + ] + }, + "displayName": { "type": "string" }, + "description": { "type": "string" }, + "downloadSize": { "type": "integer" }, + "installSize": { "type": "integer" } + } + } + } + } +} +``` + +## Exit codes + +The resource returns the following exit codes from operations: + +- [0](#exit-code-0) - Success +- [1](#exit-code-1) - Error + +### Exit code 0 + +Indicates the resource operation completed without errors. The resource writes the result JSON to +stdout. + +### Exit code 1 + +Indicates the resource operation failed. The resource writes a descriptive error message to stderr. +Common causes include: + +- The `capabilities` array is empty. +- The `identity` property is missing from a capability entry in a **Get** or **Set** operation. +- The `state` property is missing from a capability entry in a **Set** operation. +- The desired `state` value is not one of the accepted **Set** values (`Installed`, `NotPresent`). +- The requested capability `identity` is not recognized by DISM. +- The DISM API returned an error while querying or modifying capability state. +- The process is not running with elevated privileges. + +## See also + +- [Microsoft.Windows/OptionalFeatureList resource][06] +- [Windows features on demand documentation][07] + + +[01]: ../../../../../concepts/resources/capabilities.md +[02]: ./examples/get-feature-on-demand.md +[03]: ./examples/install-remove-feature-on-demand.md +[04]: ./examples/export-features-on-demand.md +[05]: ../../../../../concepts/resources/properties.md#read-only-resource-properties +[06]: ../OptionalFeatureList/index.md +[07]: /windows-hardware/manufacture/desktop/features-on-demand-v2--capabilities diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/examples/configure-firewall-rules.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/examples/configure-firewall-rules.md new file mode 100644 index 0000000..93de162 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/examples/configure-firewall-rules.md @@ -0,0 +1,216 @@ +--- +description: > + Example showing how to use the Microsoft.Windows/FirewallRuleList resource in a DSC configuration + document to create and enforce Windows Firewall rules. +ms.date: 05/09/2026 +ms.topic: reference +title: Configure firewall rules +--- + +# Configure firewall rules + +This example shows how you can use the `Microsoft.Windows/FirewallRuleList` resource in a DSC +configuration document to create and enforce multiple Windows Firewall rules in a single operation. + +> [!IMPORTANT] +> **Set** operations for this resource require an elevated (administrator) process context. Run +> your terminal or PowerShell session as Administrator before using `dsc config set`. + +## Definition + +The configuration document for this example defines one instance of the `FirewallRuleList` +resource that manages two rules: + +- **DscDemo - Custom App (TCP-In)** — allows inbound TCP traffic on port 8080 for a custom + application, active on the Domain and Private profiles. +- **DscDemo - Block Telnet (TCP-Out)** — blocks all outbound TCP connections to port 23 (Telnet) + on all profiles. + +:::code language="yaml" source="firewall.config.dsc.yaml"::: + +Copy the configuration document and save it as `firewall.config.dsc.yaml`. + +## Test the configuration + +To see whether the rules already exist, use the [dsc config test][01] command. + +```powershell +dsc config test --file ./firewall.config.dsc.yaml +``` + +```yaml +executionInformation: + # Elided for brevity +metadata: + # Elided for brevity +results: +- executionInformation: + duration: PT0.0888807S + metadata: + Microsoft.DSC: + duration: PT0.0888807S + name: Application firewall rules + type: Microsoft.Windows/FirewallRuleList + result: + desiredState: + rules: + - name: DscDemo - Custom App (TCP-In) + description: Allow inbound TCP traffic on port 8080 for the custom app. + protocol: 6 + localPorts: '8080' + direction: Inbound + action: Allow + enabled: true + profiles: + - Domain + - Private + - name: DscDemo - Block Telnet (TCP-Out) + description: Block all outbound Telnet connections. + protocol: 6 + remotePorts: '23' + direction: Outbound + action: Block + enabled: true + profiles: + - All + actualState: + rules: + - name: DscDemo - Custom App (TCP-In) + _exist: false + description: Allow inbound TCP traffic on port 8080 for the custom app. + protocol: 6 + localPorts: '8080' + direction: Inbound + action: Allow + enabled: true + profiles: + - Domain + - Private + - name: DscDemo - Block Telnet (TCP-Out) + _exist: false + description: Block all outbound Telnet connections. + protocol: 6 + remotePorts: '23' + direction: Outbound + action: Block + enabled: true + profiles: + - All + inDesiredState: false + differingProperties: + - rules +messages: [] +hadErrors: false +``` + +Neither rule exists in the firewall store, so both entries in `actualState` show `_exist: false`. +Because the actual state differs from the desired state, `inDesiredState` is `false` and `rules` +is listed in `differingProperties`. + +## Set the configuration + +To enforce the desired state and create both rules, use the [dsc config set][02] command. + +```powershell +dsc config set --file ./firewall.config.dsc.yaml +``` + +```yaml +executionInformation: + # Elided for brevity +metadata: + # Elided for brevity +results: +- executionInformation: + duration: PT0.288497S + metadata: + Microsoft.DSC: + duration: PT0.288497S + name: Application firewall rules + type: Microsoft.Windows/FirewallRuleList + result: + beforeState: + rules: + - name: DscDemo - Custom App (TCP-In) + _exist: false + description: Allow inbound TCP traffic on port 8080 for the custom app. + protocol: 6 + localPorts: '8080' + direction: Inbound + action: Allow + enabled: true + profiles: + - Domain + - Private + - name: DscDemo - Block Telnet (TCP-Out) + _exist: false + description: Block all outbound Telnet connections. + protocol: 6 + remotePorts: '23' + direction: Outbound + action: Block + enabled: true + profiles: + - All + afterState: + rules: + - name: DscDemo - Custom App (TCP-In) + description: Allow inbound TCP traffic on port 8080 for the custom app. + protocol: 6 + localPorts: '8080' + remotePorts: '*' + localAddresses: '*' + remoteAddresses: '*' + direction: Inbound + action: Allow + enabled: true + profiles: + - Domain + - Private + interfaceTypes: + - All + edgeTraversal: false + - name: DscDemo - Block Telnet (TCP-Out) + description: Block all outbound Telnet connections. + protocol: 6 + localPorts: '*' + remotePorts: '23' + localAddresses: '*' + remoteAddresses: '*' + direction: Outbound + action: Block + enabled: true + profiles: + - All + interfaceTypes: + - All + edgeTraversal: false + changedProperties: + - rules +messages: [] +hadErrors: false +``` + +Both rules were created. The `beforeState` shows both rules with `_exist: false`, confirming they +didn't exist before the operation. The `afterState` shows the complete configuration read back +from the firewall store after creation, including `interfaceTypes: [All]` and +`edgeTraversal: false` filled in by Windows. `changedProperties` lists `rules` because the rules +array changed. + +## Cleanup + +To return your system to its original state: + +1. Save the following configuration as `firewall.cleanup.config.dsc.yaml`. + + :::code language="yaml" source="firewall.cleanup.config.dsc.yaml"::: + +1. Use the **Set** operation on the cleanup configuration document. + + ```powershell + dsc config set --file ./firewall.cleanup.config.dsc.yaml + ``` + + +[01]: ../../../../../cli/config/test.md +[02]: ../../../../../cli/config/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/examples/firewall.cleanup.config.dsc.yaml b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/examples/firewall.cleanup.config.dsc.yaml new file mode 100644 index 0000000..aa64c1e --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/examples/firewall.cleanup.config.dsc.yaml @@ -0,0 +1,11 @@ +# yaml-language-server: $schema=https://aka.ms/dsc/schemas/v3/bundled/config/document.vscode.json +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: + - name: Cleanup application firewall rules + type: Microsoft.Windows/FirewallRuleList + properties: + rules: + - name: Remove 'DscDemo - Custom App (TCP-In)' + _exist: false + - name: Remove 'DscDemo - Block Telnet (TCP-Out)' + _exist: false diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/examples/firewall.config.dsc.yaml b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/examples/firewall.config.dsc.yaml new file mode 100644 index 0000000..a42854a --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/examples/firewall.config.dsc.yaml @@ -0,0 +1,26 @@ +# yaml-language-server: $schema=https://aka.ms/dsc/schemas/v3/bundled/config/document.vscode.json +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: + - name: Application firewall rules + type: Microsoft.Windows/FirewallRuleList + properties: + rules: + - name: DscDemo - Custom App (TCP-In) + description: Allow inbound TCP traffic on port 8080 for the custom app. + protocol: 6 + localPorts: '8080' + direction: Inbound + action: Allow + enabled: true + profiles: + - Domain + - Private + - name: DscDemo - Block Telnet (TCP-Out) + description: Block all outbound Telnet connections. + protocol: 6 + remotePorts: '23' + direction: Outbound + action: Block + enabled: true + profiles: + - All diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/examples/get-firewall-rules.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/examples/get-firewall-rules.md new file mode 100644 index 0000000..6b689c8 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/examples/get-firewall-rules.md @@ -0,0 +1,204 @@ +--- +description: > + Examples showing how to use the Microsoft.Windows/FirewallRuleList resource with DSC to retrieve + and modify the state of Windows Firewall rules. +ms.date: 05/09/2026 +ms.topic: reference +title: Get firewall rule state +--- + +# Get firewall rule state + +This example shows how you can use the `Microsoft.Windows/FirewallRuleList` resource to retrieve +the current state of a Windows Firewall rule and toggle it with `dsc resource` commands. + +The example uses the built-in "Remote Desktop - User Mode (TCP-In)" rule, which is present on +every Windows installation and controls whether Remote Desktop connections are allowed. + +## Get the state of a firewall rule + +The following snippet retrieves the current state of the Remote Desktop inbound rule. + +```powershell +$instance = @{ + rules = @(@{ name = 'Remote Desktop - User Mode (TCP-In)' }) +} | ConvertTo-Json -Compress + +dsc resource get --resource Microsoft.Windows/FirewallRuleList --input $instance +``` + +When the rule exists, DSC returns its full configuration. Notice that `_exist` is absent from the +actual state — for this resource, an absent `_exist` means the rule is present. + +```yaml +actualState: + rules: + - name: Remote Desktop - User Mode (TCP-In) + description: Inbound rule for the Remote Desktop service to allow RDP traffic. [TCP 3389] + protocol: 6 + localPorts: "3389" + direction: Inbound + action: Allow + enabled: false + profiles: + - Domain + - Private + grouping: Remote Desktop + interfaceTypes: + - All + edgeTraversal: false +``` + +The rule exists but `enabled: false` means it is currently inactive and not filtering traffic. + +## Get the state of a rule that doesn't exist + +When the named rule is not registered in the Windows Firewall store, the resource returns +`_exist: false` and omits any properties that were not provided in the +input. + +```powershell +$instance = @{ + rules = @(@{ name = 'DscDemo - Custom App (TCP-In)' }) +} | ConvertTo-Json -Compress + +dsc resource get --resource Microsoft.Windows/FirewallRuleList --input $instance +``` + +```yaml +actualState: + rules: + - name: DscDemo - Custom App (TCP-In) + _exist: false +``` + +## Enable a firewall rule + +To enable the Remote Desktop rule, use the [dsc resource set][01] command with `enabled: true`. +This operation requires an elevated (administrator) terminal. + +```powershell +$desired = @{ + rules = @(@{ + name = 'Remote Desktop - User Mode (TCP-In)' + enabled = $true + }) +} | ConvertTo-Json -Compress + +dsc resource set --resource Microsoft.Windows/FirewallRuleList --input $desired +``` + +DSC first tests the current state and then calls the resource's `set` operation because the rule +is not in the desired state. The output shows the state before and after the change. + +```yaml +beforeState: + rules: + - name: Remote Desktop - User Mode (TCP-In) + description: Inbound rule for the Remote Desktop service to allow RDP traffic. [TCP 3389] + protocol: 6 + localPorts: "3389" + direction: Inbound + action: Allow + enabled: false + profiles: + - Domain + - Private + grouping: Remote Desktop + interfaceTypes: + - All + edgeTraversal: false +afterState: + rules: + - name: Remote Desktop - User Mode (TCP-In) + description: Inbound rule for the Remote Desktop service to allow RDP traffic. [TCP 3389] + protocol: 6 + localPorts: "3389" + direction: Inbound + action: Allow + enabled: true + profiles: + - Domain + - Private + grouping: Remote Desktop + interfaceTypes: + - All + edgeTraversal: false +changedProperties: +- rules +``` + +The `changedProperties` field lists `rules` because the `enabled` property of the rule changed. + +## Query multiple rules at once + +A single **Get** call can retrieve the state of multiple rules by listing them all in the `rules` +array. + +```powershell +$instance = @{ + rules = @( + @{ name = 'Remote Desktop - User Mode (TCP-In)' } + @{ name = 'Remote Desktop - User Mode (UDP-In)' } + ) +} | ConvertTo-Json -Compress + +dsc resource get --resource Microsoft.Windows/FirewallRuleList --input $instance +``` + +```yaml +actualState: + rules: + - name: Remote Desktop - User Mode (TCP-In) + description: Inbound rule for the Remote Desktop service to allow RDP traffic. [TCP 3389] + protocol: 6 + localPorts: "3389" + direction: Inbound + action: Allow + enabled: true + profiles: + - Domain + - Private + grouping: Remote Desktop + interfaceTypes: + - All + edgeTraversal: false + - name: Remote Desktop - User Mode (UDP-In) + description: Inbound rule for the Remote Desktop service to allow RDP traffic. [UDP 3389] + protocol: 17 + localPorts: "3389" + direction: Inbound + action: Allow + enabled: true + profiles: + - Domain + - Private + grouping: Remote Desktop + interfaceTypes: + - All + edgeTraversal: false +``` + +## Export all inbound allow rules + +The [dsc resource export][02] command returns all registered firewall rules. You can pass an +optional filter to narrow the results. The following snippet exports only inbound rules with +the `Allow` action. + +```powershell +$filter = @{ + rules = @(@{ + direction = 'Inbound' + action = 'Allow' + }) +} | ConvertTo-Json -Compress + +dsc resource export --resource Microsoft.Windows/FirewallRuleList --input $filter +``` + +DSC emits one JSON object for each matching rule. Properties within a single filter entry are +ANDed together; multiple filter entries are ORed. This call requires an elevated terminal. + + +[01]: ../../../../../cli/resource/set.md +[02]: ../../../../../cli/resource/export.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/index.md new file mode 100644 index 0000000..2d20d8c --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/FirewallRuleList/index.md @@ -0,0 +1,547 @@ +--- +description: Microsoft.Windows/FirewallRuleList resource reference documentation +ms.date: 05/09/2026 +ms.topic: reference +title: Microsoft.Windows/FirewallRuleList +--- + +# Microsoft.Windows/FirewallRuleList + +## Synopsis + +Manage Windows Firewall rules using the netfw.h APIs. + +## Metadata + +```yaml +Version : 0.1.0 +Kind : resource +Tags : [Windows, Firewall] +Author : Microsoft +``` + +## Instance definition syntax + +```yaml +resources: + - name: + type: Microsoft.Windows/FirewallRuleList + properties: + rules: + - name: string + # Rule properties + action: + applicationName: + description: + direction: + edgeTraversal: + enabled: + grouping: + interfaceTypes: + localAddresses: + localPorts: + profiles: + protocol: + remoteAddresses: + remotePorts: + serviceName: + _exist: +``` + +## Description + +The `Microsoft.Windows/FirewallRuleList` resource enables you to idempotently manage Windows +Firewall rules through the `netfw.h` COM APIs. A single instance of the resource manages an array +of rules, allowing you to create, update, or remove multiple rules in one operation. + +The resource can: + +- Retrieve the full configuration of one or more named firewall rules. +- Create rules that don't exist, update properties of rules that do, and remove rules by setting + `_exist: false`. +- Export all registered firewall rules, with optional AND/OR filtering by rule properties. + +> [!IMPORTANT] +> The `_exist` property on a rule item behaves differently from most DSC resources. When a rule +> exists in the Windows Firewall store, `_exist` is **omitted** from the returned state (absent +> means present). When a rule is not found, `_exist: false` appears in the response. This means +> that a missing `_exist` field in the actual state always indicates the rule exists. + +The resource is installed with DSC itself on Windows systems. + +> [!NOTE] +> You can update this resource by updating DSC. When you update DSC, the updated version of this +> resource is automatically available. + +## Requirements + +- The resource is only usable on Windows systems. +- **Set** and **Export** operations require an elevated (administrator) process context. Invoking + the resource for these operations in a non-elevated process context causes the resource to raise + an error. + +## Capabilities + +The resource has the following capabilities: + +- `get` - You can use the resource to retrieve the actual state of one or more firewall rules. +- `set` - You can use the resource to enforce the desired state of one or more firewall rules, + including creating and removing rules. +- `export` - You can use the resource to export all firewall rules registered on the system, + with optional filtering. + +This resource uses the synthetic test functionality of DSC to determine whether an instance is in +the desired state. For more information about resource capabilities, see +[DSC resource capabilities][01]. + +## Examples + +1. [Get firewall rule state][03] - Shows how to retrieve the current state of a Windows Firewall + rule and toggle it with the `dsc resource` commands. +1. [Configure firewall rules][04] - Shows how to create and manage multiple Windows Firewall rules + using a DSC configuration document. + +## Properties + +The `Microsoft.Windows/FirewallRuleList` instance has one required property at the root level. + +- **Required properties:** + + - [rules](#rules) - An array of firewall rule objects to get, set, or use as export filters. + +### rules + +
Expand for rules property metadata + +```yaml +Type : array +IsRequired : true +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +An array of firewall rule objects. For **Get** and **Set** operations, each entry in the array +must include a [name](#name) property that identifies the rule. For **Export**, each entry acts +as a filter — all properties within a single entry are ANDed together, and multiple entries are +ORed. The array must contain at least one entry for **Get** and **Set** operations. + +Each entry in the `rules` array supports the following properties. + +### name + +
Expand for name property metadata + +```yaml +Type : string +IsRequired : true for get and set +IsKey : true (within the rules array) +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +The Windows Firewall rule name as registered in the firewall store. This is the exact name shown +in the Windows Firewall console. Name matching is case-insensitive. Wildcard patterns using `*` +are supported for **Export** filter entries. + +### _exist + +
Expand for _exist property metadata + +```yaml +Type : boolean +IsRequired : false +IsKey : false +IsReadOnly : false (writable for set to remove a rule) +IsWriteOnly : false +``` + +
+ +Indicates whether a firewall rule exists. The behavior of this property differs from most DSC +resources: + +- When a rule _exists_, `_exist` is _omitted_ from the returned state. Absence means the rule + is present. +- When a rule is _not found_, `_exist: false` appears in the response. +- In a **Set** operation, set `_exist: false` on a rule entry to remove the rule if it exists. + +### description + +
Expand for description property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +A human-readable description of the firewall rule shown in the Windows Firewall console. + +### applicationName + +
Expand for applicationName property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +The fully qualified path to the application executable associated with the rule — for example, +`C:\Program Files\MyApp\myapp.exe`. When specified, the rule only applies to traffic from or +to that application. + +### serviceName + +
Expand for serviceName property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +The Windows service short name associated with the rule. When specified, the rule only applies +to traffic from or to that service. + +### protocol + +
Expand for protocol property metadata + +```yaml +Type : integer +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +InclusiveMinimumValue : 0 +InclusiveMaximumValue : 256 +``` + +
+ +The IANA IP protocol number for the rule. The following values are commonly used: + +| Value | Protocol | +|------:|:--------------------| +| `1` | ICMPv4 | +| `6` | TCP | +| `17` | UDP | +| `58` | ICMPv6 | +| `256` | Any (all protocols) | + +### localPorts + +
Expand for localPorts property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +A comma-separated list of local port numbers or ranges for the rule — for example, `80,443` or +`8000-8080`. Only valid when `protocol` is `6` (TCP) or `17` (UDP). + +### remotePorts + +
Expand for remotePorts property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +A comma-separated list of remote port numbers or ranges for the rule. Only valid when `protocol` +is `6` (TCP) or `17` (UDP). + +### localAddresses + +
Expand for localAddresses property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +A comma-separated list of local IP addresses or subnets in CIDR notation for the rule — for +example, `192.168.1.0/24,10.0.0.1`. + +### remoteAddresses + +
Expand for remoteAddresses property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +A comma-separated list of remote IP addresses or subnets in CIDR notation for the rule. + +### direction + +
Expand for direction property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +Enum : [Inbound, Outbound] +``` + +
+ +The direction of network traffic the rule applies to. + +| Value | Description | +|:-----------|:--------------------------------------| +| `Inbound` | The rule applies to incoming traffic. | +| `Outbound` | The rule applies to outgoing traffic. | + +### action + +
Expand for action property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +Enum : [Allow, Block] +``` + +
+ +The action taken by the rule when traffic matches. + +| Value | Description | +|:--------|:--------------------------------------------| +| `Allow` | Matching traffic is permitted. | +| `Block` | Matching traffic is denied. | + +### enabled + +
Expand for enabled property metadata + +```yaml +Type : boolean +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Indicates whether the firewall rule is active. A rule that exists but has `enabled: false` doesn't +affect network traffic. + +### profiles + +
Expand for profiles property metadata + +```yaml +Type : array +ItemsType : string +ItemsMustBeUnique : false +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +Enum : [Domain, Private, Public, All] +``` + +
+ +The network location profiles for which the rule is active. Specifying `All` is equivalent to +specifying all three individual profiles. When all three individual profiles (`Domain`, `Private`, +`Public`) are set, the resource normalizes them to `All`. + +### grouping + +
Expand for grouping property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +The grouping string that associates the rule with a named feature or application group, shown in +the Windows Firewall console as the **Program** or **Group** column. + +### interfaceTypes + +
Expand for interfaceTypes property metadata + +```yaml +Type : array +ItemsType : string +ItemsMustBeUnique : false +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +Enum : [RemoteAccess, Wireless, Lan, All] +``` + +
+ +The network interface types for which the rule applies. Specifying `All` is equivalent to +specifying every interface type. + +| Value | Description | +|:---------------|:-----------------------------------------------| +| `RemoteAccess` | The rule applies to remote access connections. | +| `Wireless` | The rule applies to wireless connections. | +| `Lan` | The rule applies to LAN connections. | +| `All` | The rule applies to all interface types. | + +### edgeTraversal + +
Expand for edgeTraversal property metadata + +```yaml +Type : boolean +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +Indicates whether edge traversal is enabled for the rule. When `true`, traffic routed through +Network Address Translation (NAT) edge devices can pass through this rule. + +## Instance validating schema + +The following snippet contains the JSON Schema that validates an instance of the resource. + +```json +{ + "type": "object", + "additionalProperties": false, + "required": ["rules"], + "properties": { + "rules": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { "type": "string" }, + "_exist": { "type": "boolean" }, + "description": { "type": "string" }, + "applicationName": { "type": "string" }, + "serviceName": { "type": "string" }, + "protocol": { "type": "integer" }, + "localPorts": { "type": "string" }, + "remotePorts": { "type": "string" }, + "localAddresses": { "type": "string" }, + "remoteAddresses": { "type": "string" }, + "direction": { "type": "string", "enum": ["Inbound", "Outbound"] }, + "action": { "type": "string", "enum": ["Allow", "Block"] }, + "enabled": { "type": "boolean" }, + "profiles": { + "type": "array", + "items": { "type": "string", "enum": ["Domain", "Private", "Public", "All"] } + }, + "grouping": { "type": "string" }, + "interfaceTypes": { + "type": "array", + "items": { "type": "string", "enum": ["RemoteAccess", "Wireless", "Lan", "All"] } + }, + "edgeTraversal": { "type": "boolean" } + } + } + } + } +} +``` + +## Exit codes + +The resource returns the following exit codes from operations: + +- [0](#exit-code-0) - Success +- [1](#exit-code-1) - Invalid arguments +- [2](#exit-code-2) - Invalid input +- [3](#exit-code-3) - Firewall error + +### Exit code 0 + +Indicates the resource operation completed without errors. + +### Exit code 1 + +Indicates the resource operation failed because required arguments were missing or the operation +name was not recognized. + +### Exit code 2 + +Indicates the resource operation failed because the JSON input could not be deserialized into a +valid `FirewallRuleList` instance. + +### Exit code 3 + +Indicates the resource operation failed due to an error raised by the Windows Firewall COM API, +or the result could not be serialized. + +## See also + +- [Microsoft.Windows/Registry resource][05] +- [Microsoft.Windows/Service resource][06] +- [DSC resource capabilities][01] +- [DSC resource properties][02] + + +[01]: ../../../../../concepts/resources/capabilities.md +[02]: ../../../../../concepts/resources/properties.md +[03]: ./examples/get-firewall-rules.md +[04]: ./examples/configure-firewall-rules.md +[05]: ../Registry/index.md +[06]: ../Service/index.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/OptionalFeatureList/examples/enable-disable-optional-features.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/OptionalFeatureList/examples/enable-disable-optional-features.md new file mode 100644 index 0000000..4655971 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/OptionalFeatureList/examples/enable-disable-optional-features.md @@ -0,0 +1,198 @@ +--- +description: > + Examples showing how to enable and disable Windows Optional features using the + Microsoft.Windows/OptionalFeatureList resource. +ms.date: 04/21/2026 +ms.topic: reference +title: Enable and disable optional features +--- + +# Enable and disable optional features + +This example shows how you can use the `Microsoft.Windows/OptionalFeatureList` resource to enable +and disable Windows Optional features on a system. The examples use `TelnetClient` as a +representative feature name. + +> [!IMPORTANT] +> All operations with `Microsoft.Windows/OptionalFeatureList` require an elevated (administrator) +> session. Run your terminal as administrator before executing these commands. + +## Enable an optional feature + +To enable an optional feature, set its `state` to `Installed` and use the [dsc resource set][01] +command. + +```powershell +$instance = @{ + features = @( + @{ + featureName = 'TelnetClient' + state = 'Installed' + } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource set --resource Microsoft.Windows/OptionalFeatureList --input $instance +``` + +When the resource enables the feature, DSC returns the updated state: + +```yaml +beforeState: + features: + - featureName: TelnetClient + state: NotPresent + displayName: Telnet Client + description: Includes Telnet Client + restartRequired: No +afterState: + features: + - featureName: TelnetClient + state: Installed + displayName: Telnet Client + description: Includes Telnet Client + restartRequired: No +changedProperties: +- features +``` + +If a system restart is required to complete the operation, the response includes a +`_restartRequired` property at the top level: + +```yaml +afterState: + _restartRequired: + - system: MYCOMPUTER + features: + - featureName: SomeFeature + state: InstallPending + ... +changedProperties: +- features +``` + +## Disable an optional feature (keep payload staged) + +To disable a feature while keeping the feature payload on disk (so it can be re-enabled quickly +without source media), set `state` to `NotPresent`. + +```powershell +$instance = @{ + features = @( + @{ + featureName = 'TelnetClient' + state = 'NotPresent' + } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource set --resource Microsoft.Windows/OptionalFeatureList --input $instance +``` + +```yaml +beforeState: + features: + - featureName: TelnetClient + state: Installed + displayName: Telnet Client + description: Includes Telnet Client + restartRequired: No +afterState: + features: + - featureName: TelnetClient + state: NotPresent + displayName: Telnet Client + description: Includes Telnet Client + restartRequired: No +changedProperties: +- features +``` + +## Disable an optional feature and remove its payload + +To disable a feature and completely remove its payload from disk, set `state` to `Removed`. This +frees disk space but requires source media (or Windows Update access) to re-enable the feature +later. + +```powershell +$instance = @{ + features = @( + @{ + featureName = 'TelnetClient' + state = 'Removed' + } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource set --resource Microsoft.Windows/OptionalFeatureList --input $instance +``` + +```yaml +beforeState: + features: + - featureName: TelnetClient + state: Installed + displayName: Telnet Client + description: Includes Telnet Client + restartRequired: No +afterState: + features: + - featureName: TelnetClient + state: Removed + displayName: Telnet Client + description: Includes Telnet Client + restartRequired: No +changedProperties: +- features +``` + +## Manage multiple features in a single operation + +You can enable or disable multiple features in a single **Set** call by specifying multiple entries +in the `features` array. + +```powershell +$instance = @{ + features = @( + @{ + featureName = 'TelnetClient' + state = 'Installed' + } + @{ + featureName = 'TFTP' + state = 'NotPresent' + } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource set --resource Microsoft.Windows/OptionalFeatureList --input $instance +``` + +## Use in a configuration document + +You can also use the resource in a DSC configuration document to declaratively manage optional +features across a system. + +```yaml +# optional-features.config.dsc.yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: + - name: Enable Telnet Client + type: Microsoft.Windows/OptionalFeatureList + properties: + features: + - featureName: TelnetClient + state: Installed + - featureName: TFTP + state: NotPresent +``` + +Apply the configuration with the [dsc config set][02] command: + +```powershell +dsc config set --file ./optional-features.config.dsc.yaml +``` + + +[01]: ../../../../../cli/resource/set.md +[02]: ../../../../../cli/config/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/OptionalFeatureList/examples/export-optional-features.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/OptionalFeatureList/examples/export-optional-features.md new file mode 100644 index 0000000..71078d0 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/OptionalFeatureList/examples/export-optional-features.md @@ -0,0 +1,144 @@ +--- +description: > + Examples showing how to export and filter Windows Optional features using the + Microsoft.Windows/OptionalFeatureList resource. +ms.date: 04/21/2026 +ms.topic: reference +title: Export optional features +--- + +# Export optional features + +This example shows how you can use the `Microsoft.Windows/OptionalFeatureList` resource to +enumerate Windows Optional features on a system, optionally filtering the results by name, state, +display name, or description. + +> [!IMPORTANT] +> All operations with `Microsoft.Windows/OptionalFeatureList` require an elevated (administrator) +> session. Run your terminal as administrator before executing these commands. + +## Export all optional features + +To retrieve a complete list of all optional features on the system, use the +[dsc resource export][01] command without any input. + +```powershell +dsc resource export --resource Microsoft.Windows/OptionalFeatureList +``` + +DSC returns a configuration document that includes all optional features and their current states: + +```yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: +- name: Microsoft.Windows/OptionalFeatureList + type: Microsoft.Windows/OptionalFeatureList + properties: + features: + - featureName: TFTP + state: NotPresent + - featureName: TelnetClient + state: NotPresent + - featureName: Containers-DisposableClientVM + state: NotPresent + # ... additional features +``` + +> [!NOTE] +> When exporting without filters, the resource uses a fast enumeration path that returns only +> `featureName` and `state` for each feature. To retrieve additional properties such as +> `displayName` and `description`, use an export filter as shown in the examples below. + +## Export only installed features + +To list only the features that are currently enabled, provide a filter with `state: Installed`. + +```powershell +$filter = @{ + features = @( + @{ state = 'Installed' } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource export --resource Microsoft.Windows/OptionalFeatureList --input $filter +``` + +```yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: +- name: Microsoft.Windows/OptionalFeatureList + type: Microsoft.Windows/OptionalFeatureList + properties: + features: + - featureName: NetFx4-AdvSrvs + state: Installed + - featureName: WCF-Services45 + state: Installed + # ... additional installed features +``` + +## Export features by name pattern + +You can filter features by name using wildcard (`*`) patterns. The match is case-insensitive. + +```powershell +$filter = @{ + features = @( + @{ featureName = 'Hyper-V*' } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource export --resource Microsoft.Windows/OptionalFeatureList --input $filter +``` + +```yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: +- name: Microsoft.Windows/OptionalFeatureList + type: Microsoft.Windows/OptionalFeatureList + properties: + features: + - featureName: Microsoft-Hyper-V + state: Installed + - featureName: Microsoft-Hyper-V-Management-Clients + state: Installed + - featureName: Microsoft-Hyper-V-Management-PowerShell + state: Installed + - featureName: Microsoft-Hyper-V-Tools-All + state: Installed +``` + +## Export features with full details + +To retrieve full details including `displayName` and `description`, include those properties as +filters. An empty string (`""`) or a wildcard (`*`) matches all values for that field. + +```powershell +$filter = @{ + features = @( + @{ + featureName = 'TelnetClient' + displayName = '*' + } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource export --resource Microsoft.Windows/OptionalFeatureList --input $filter +``` + +```yaml +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: +- name: Microsoft.Windows/OptionalFeatureList + type: Microsoft.Windows/OptionalFeatureList + properties: + features: + - featureName: TelnetClient + state: NotPresent + displayName: Telnet Client + description: Includes Telnet Client + restartRequired: No +``` + + +[01]: ../../../../../cli/resource/export.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/OptionalFeatureList/examples/get-optional-feature.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/OptionalFeatureList/examples/get-optional-feature.md new file mode 100644 index 0000000..8bd2fc2 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/OptionalFeatureList/examples/get-optional-feature.md @@ -0,0 +1,117 @@ +--- +description: > + Examples showing how to retrieve the current state of Windows Optional Features using the + Microsoft.Windows/OptionalFeatureList resource. +ms.date: 04/21/2026 +ms.topic: reference +title: Get optional feature state +--- + +# Get optional feature state + +This example shows how you can use the `Microsoft.Windows/OptionalFeatureList` resource to retrieve +the current state of Windows Optional Features. The examples use `TelnetClient` as a +representative feature name. + +> [!IMPORTANT] +> All operations with `Microsoft.Windows/OptionalFeatureList` require an elevated (administrator) +> session. Run your terminal as administrator before executing these commands. + +## Get a single feature + +The following snippet shows how to retrieve the state of the `TelnetClient` feature using the +[dsc resource get][01] command. + +```powershell +$instance = @{ + features = @( + @{ featureName = 'TelnetClient' } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource get --resource Microsoft.Windows/OptionalFeatureList --input $instance +``` + +When the feature is disabled, DSC returns output similar to the following: + +```yaml +actualState: + features: + - featureName: TelnetClient + state: NotPresent + displayName: Telnet Client + description: Includes Telnet Client + restartRequired: No +``` + +When the feature is enabled, the `state` field reads `Installed`: + +```yaml +actualState: + features: + - featureName: TelnetClient + state: Installed + displayName: Telnet Client + description: Includes Telnet Client + restartRequired: No +``` + +## Get multiple features in a single request + +You can retrieve the state of multiple features in a single call by including multiple entries in +the `features` array. + +```powershell +$instance = @{ + features = @( + @{ featureName = 'TelnetClient' } + @{ featureName = 'TFTP' } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource get --resource Microsoft.Windows/OptionalFeatureList --input $instance +``` + +DSC returns the state of all requested features in a single response: + +```yaml +actualState: + features: + - featureName: TelnetClient + state: NotPresent + displayName: Telnet Client + description: Includes Telnet Client + restartRequired: No + - featureName: TFTP + state: NotPresent + displayName: TFTP Client + description: Includes TFTP Client + restartRequired: No +``` + +## Get a non-existent feature + +When you request a feature name that is not recognized by DISM, the resource returns `_exist: false` +instead of raising an error. + +```powershell +$instance = @{ + features = @( + @{ featureName = 'NonExistent-Feature-XYZ' } + ) +} | ConvertTo-Json -Depth 3 + +dsc resource get --resource Microsoft.Windows/OptionalFeatureList --input $instance +``` + +```yaml +actualState: + features: + - featureName: NonExistent-Feature-XYZ + _exist: false +``` + +The `_exist: false` response indicates the feature name is not recognized by DISM on this system. + + +[01]: ../../../../../cli/resource/get.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/OptionalFeatureList/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/OptionalFeatureList/index.md new file mode 100644 index 0000000..ed3c5a7 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/OptionalFeatureList/index.md @@ -0,0 +1,367 @@ +--- +description: Microsoft.Windows/OptionalFeatureList resource reference documentation +ms.date: 08/13/2026 +ms.topic: reference +title: Microsoft.Windows/OptionalFeatureList +--- + +# Microsoft.Windows/OptionalFeatureList + +## Synopsis + +Manage Windows Optional features using the DISM API. + +## Metadata + +```yaml +Version : 0.1.0 +Kind : resource +Tags : [Windows, dism, optionalfeature, feature] +Author : Microsoft +``` + +## Instance definition syntax + +```yaml +resources: + - name: + type: Microsoft.Windows/OptionalFeatureList + properties: + # Required properties + features: + - featureName: string + # Instance properties + state: Installed | NotPresent | Removed +``` + +## Description + +The `Microsoft.Windows/OptionalFeatureList` resource enables you to idempotently manage Windows +Optional features using the DISM API. Optional features are components built into Windows that can +be enabled or disabled without downloading additional content. Examples include Hyper-V, +Windows Subsystem for Linux, and Internet Information Services (IIS). + +The resource can: + +- Retrieve the current state of one or more optional features by name. +- Enable optional features (`Installed`). +- Disable optional features while keeping the feature payload staged (`NotPresent`). +- Disable optional features and remove the associated payload from the system (`Removed`). +- Export a list of all optional features on the system, optionally filtered by name, state, display + name, or description. + +> [!NOTE] +> This resource is installed with DSC itself on Windows systems. +> +> You can update this resource by updating DSC. When you update DSC, the updated version of this +> resource is automatically available. + +## Requirements + +- The resource is only usable on a Windows system. +- All operations require an elevated (administrator) process context. + +## Capabilities + +The resource has the following capabilities: + +- `get` - You can use the resource to retrieve the actual state of one or more optional feature + instances. +- `set` - You can use the resource to enforce the desired state for one or more optional feature + instances. +- `export` - You can use the resource to enumerate all optional features on the system, with + optional filtering. + +This resource uses the synthetic test functionality of DSC to determine whether an instance is in +the desired state. For more information about resource capabilities, see +[DSC resource capabilities][01]. + +## Examples + +1. [Get optional feature state][02] - Shows how to retrieve the current state of a Windows + Optional Feature. +1. [Enable and disable optional features][03] - Shows how to enable and disable Windows Optional + Features using the `dsc resource set` command. +1. [Export optional features][04] - Shows how to enumerate all optional features on the system, + with and without filters. + +## Properties + +The following list describes the properties for the resource. + +- **Required properties:** The following properties are always + required when defining an instance of the resource. + + - [features](#features) - An array of optional feature entries. + +- **Read-only properties:** The resource returns the following + properties, but they aren't configurable. For more information about read-only properties, see + the "Read-only resource properties" section in [DSC resource properties][05]. + + - [_restartRequired](#_restartrequired) - Indicates that a system restart is required to complete + the state change. + +### features + +
Expand for features property metadata + +```yaml +Type : array +IsRequired : true +IsKey : false +IsReadOnly : false +``` + +
+ +An array of optional feature entries. Each entry is an object describing a Windows Optional Feature. +For the **Get** operation, each entry must specify [`featureName`](#featurename). For the **Set** +operation, each entry must specify both [`featureName`](#featurename) and [`state`](#state). For +the **Export** operation, the array is optional and each entry can filter results using +[`featureName`](#featurename), [`state`](#state), [`displayName`](#displayname), or +[`description`](#description) with wildcard support, or by exact [`state`](#state) value. + +Each entry in `features` has the following properties: + +- [featureName](#featurename) - The name of the optional feature. +- [_exist](#_exist) - Indicates whether the feature is recognized by DISM. +- [state](#state) - The current or desired state of the feature. +- [displayName](#displayname) - The display name of the feature. +- [description](#description) - The description of the feature. +- [restartRequired](#restartrequired) - Whether a restart is required after a state change. + +#### featureName + +
Expand for features[*].featureName property metadata + +```yaml +Type : string +IsRequired : true (get, set) / false (export) +IsKey : false +IsReadOnly : false +``` + +
+ +The name of the Windows Optional Feature. For **Get** and **Set** operations, this property is +required for each entry. For the **Export** operation, it's optional and supports wildcard (`*`) +patterns for case-insensitive filtering. + +Use the `dism /Online /Get-Features` command to list available feature names on your system. + +#### _exist + +
Expand for features[*]._exist property metadata + +```yaml +Type : boolean +IsRequired : false +IsKey : false +IsReadOnly : true +``` + +
+ +Indicates whether the feature exists on the system. The resource sets this property to `false` in +the **Get** response when the requested `featureName` is not recognized by DISM. When `_exist` is +`false`, the `state`, `displayName`, `description`, and `restartRequired` properties are not +returned. + +#### state + +
Expand for features[*].state property metadata + +```yaml +Type : string +IsRequired : true (set) / false (get, export) +IsKey : false +IsReadOnly : false (set input) / true (get/export output) +ValidValues : [NotPresent, UninstallPending, Staged, Removed, Installed, + InstallPending, Superseded, PartiallyInstalled] +SetValues : [Installed, NotPresent, Removed] +``` + +
+ +The state of the optional feature. **Get** and **Export** operations return one of the eight DISM +feature state values. **Set** operations accept only the following three values as desired state: + +| Value | Description | +|:-------------|:--------------------------------------------------------------------------| +| `Installed` | The feature is enabled. The resource enables the feature if not already. | +| `NotPresent` | The feature is disabled but the payload remains on disk (staged). | +| `Removed` | The feature is disabled and the payload is removed from the system. | + +The following table describes all possible state values returned by **Get** and **Export**: + +| Value | Description | +|:---------------------|:--------------------------------------------------------------------| +| `NotPresent` | The feature is disabled but the payload remains on disk (staged). | +| `UninstallPending` | A disable operation is pending, requiring a restart to complete. | +| `Staged` | The feature payload is on disk but the feature is not enabled. | +| `Removed` | The feature is disabled and its source payload has been removed. | +| `Installed` | The feature is enabled and fully operational. | +| `InstallPending` | An enable operation is pending, requiring a restart to complete. | +| `Superseded` | The feature has been replaced by another component. | +| `PartiallyInstalled` | The feature is only partially installed. | + +#### displayName + +
Expand for features[*].displayName property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : true +``` + +
+ +The human-readable display name of the optional feature. This property is returned by **Get** and +**Export** operations. For **Export** operations, you can specify this property as a filter value +with wildcard (`*`) support for case-insensitive matching. + +#### description + +
Expand for features[*].description property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : true +``` + +
+ +A brief description of the optional feature. This property is returned by **Get** and **Export** +operations. For **Export** operations, you can specify this property as a filter value with +wildcard (`*`) support for case-insensitive matching. + +#### restartRequired + +
Expand for features[*].restartRequired property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : true +ValidValues : [No, Possible, Required] +``` + +
+ +Indicates whether a system restart is required after enabling or disabling the feature. This +property is returned by **Get** and **Export** operations and cannot be set. + +| Value | Description | +|:-----------|:----------------------------------------------------------| +| `No` | No restart is required after the state change. | +| `Possible` | A restart may be required depending on system conditions. | +| `Required` | A restart is required to complete the state change. | + +### _restartRequired + +
Expand for _restartRequired property metadata + +```yaml +Type : array +IsRequired : false +IsKey : false +IsReadOnly : true +``` + +
+ +Returned at the top level of the **Set** operation response when DISM reports that a system restart +is required to complete the requested state changes. Each entry in the array is an object with a +`system` property containing the name of the computer. + +When no restart is required, this property is omitted from the response. + +## Instance validating schema + +The following snippet contains the JSON Schema that validates an instance of the resource. + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "required": ["features"], + "additionalProperties": false, + "properties": { + "_restartRequired": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + } + }, + "features": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "featureName": { "type": "string" }, + "_exist": { "type": "boolean" }, + "state": { + "type": "string", + "enum": [ + "NotPresent", "UninstallPending", "Staged", "Removed", + "Installed", "InstallPending", "Superseded", "PartiallyInstalled" + ] + }, + "displayName": { "type": "string" }, + "description": { "type": "string" }, + "restartRequired": { + "type": "string", + "enum": ["No", "Possible", "Required"] + } + } + } + } + } +} +``` + +## Exit codes + +The resource returns the following exit codes from operations: + +- [0](#exit-code-0) - Success +- [1](#exit-code-1) - Error + +### Exit code 0 + +Indicates the resource operation completed without errors. The resource writes the result JSON to +stdout. + +### Exit code 1 + +Indicates the resource operation failed. The resource writes a descriptive error message to stderr. +Common causes include: + +- The `features` array is empty. +- The `featureName` property is missing from a feature entry in a **Get** or **Set** operation. +- The `state` property is missing from a feature entry in a **Set** operation. +- The desired `state` value is not one of the accepted **Set** values (`Installed`, `NotPresent`, + `Removed`). +- The DISM API returned an error while querying or modifying feature state. +- The process is not running with elevated privileges. + +## See also + +- [Microsoft.Windows/FeatureOnDemandList resource][06] +- [Windows Optional Features documentation][07] + + +[01]: ../../../../../concepts/resources/capabilities.md +[02]: ./examples/get-optional-feature.md +[03]: ./examples/enable-disable-optional-features.md +[04]: ./examples/export-optional-features.md +[05]: ../../../../../concepts/resources/properties.md#read-only-resource-properties +[06]: ../FeatureOnDemandList/index.md +[07]: /windows-hardware/manufacture/desktop/dism-operating-system-package-servicing-command-line-options diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/RebootPending/examples/check-for-pending-reboot.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/RebootPending/examples/check-for-pending-reboot.md index b103a27..55c89a3 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/RebootPending/examples/check-for-pending-reboot.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/RebootPending/examples/check-for-pending-reboot.md @@ -1,16 +1,15 @@ --- description: > - Example showing how to use the Microsoft.Windows/RebootPending resource - with DSC to check if a Windows system has a pending reboot. -ms.date: 07/03/2025 + Example showing how to use the Microsoft.Windows/RebootPending resource with DSC to check if a Windows system has a pending reboot. +ms.date: 03/25/2025 ms.topic: reference -title: Check for pending reboot +title: Check for pending reboot --- # Check for pending reboot -This example shows how you can use the `Microsoft.Windows/RebootPending` resource to check whether -a Windows system has a pending reboot. +This example shows how you can use the `Microsoft.Windows/RebootPending` resource to check whether a +Windows system has a pending reboot. ## Check reboot status @@ -45,7 +44,7 @@ The `rebootPending` property indicates whether the system requires a reboot (`tr > operation against the resource and use it in the `Microsoft.Dsc/Assertion` group resource. This > resource relies on the synthetic testing provided by DSC. For more information about synthetic > testing with DSC, see -> [DSC resource capabiltiies](../../../../../../concepts/resources/capabilities.md#test). +> [DSC resource capabilities](../../../../../../concepts/resources/capabilities.md#test). > > For an example using this resource in an assertion, see > [Use the RebootPending resource in a configuration](./use-rebootpending-in-configuration.md). diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/RebootPending/examples/use-rebootpending-in-configuration.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/RebootPending/examples/use-rebootpending-in-configuration.md index 4cbf6bc..37e8f90 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/RebootPending/examples/use-rebootpending-in-configuration.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/RebootPending/examples/use-rebootpending-in-configuration.md @@ -2,9 +2,9 @@ description: > Example showing how to use the Microsoft.Windows/RebootPending resource in a configuration document with an assertion to check for a pending reboot. -ms.date: 07/03/2025 -ms.topic: reference -title: Use RebootPending resource in a configuration +ms.date: 03/25/2025 +ms.topic: reference +title: Use RebootPending resource in a configuration --- # Use the RebootPending resource in a configuration @@ -21,7 +21,7 @@ together with an assertion. The first instance defines the desired state for the `ManagedKey` registry key, ensuring it exists only if no reboot is pending. It uses the `dependsOn` property to reference the assertion resource, which checks the system's reboot status using the `Microsoft.Windows/RebootPending` resource. The -assertion passes when `rebootPending` is `false`,allowing the registry key resource to run. If a +assertion passes when `rebootPending` is `false`, allowing the registry key resource to run. If a reboot is pending, the assertion fails and the registry key is not set. :::code language="yaml" source="pendingReboot.config.dsc.yaml"::: @@ -138,8 +138,8 @@ instance indicates it isn't in the desired state. ## Enforce configuration -To update the system to the desired state, use the [dsc config set][02] command on the -configuration document. +To update the system to the desired state, use the [dsc config set][02] command on the configuration +document. ```powershell dsc config set --file ./pendingReboot.config.dsc.yaml @@ -254,4 +254,4 @@ To return your system to its original state: [01]: ../../../../../cli/config/test.md -[02]: ../../../../../cli/config/set.md \ No newline at end of file +[02]: ../../../../../cli/config/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/RebootPending/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/RebootPending/index.md index 86823ea..59eda8b 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/RebootPending/index.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/RebootPending/index.md @@ -1,6 +1,6 @@ --- description: Microsoft.Windows/RebootPending resource reference documentation -ms.date: 07/03/2025 +ms.date: 03/25/2025 ms.topic: reference title: Microsoft.Windows/RebootPending --- @@ -12,8 +12,8 @@ title: Microsoft.Windows/RebootPending Checks if a Windows system has a pending reboot. > [!IMPORTANT] -> The `Microsoft.Windows/RebootPending` resource are a proof-of-concept example for use with DSC. -> Don't use it in production. +> The `Microsoft.Windows/RebootPending` resource is a proof-of-concept example +> for use with DSC. Don't use it in production. ## Metadata @@ -74,7 +74,7 @@ For more information about resource capabilities, see [DSC resource capabilities 1. [Check for pending reboot][04] - Shows how to check if a system has a pending reboot using the `dsc resource get` command. -2. [Use the RebootPending resource in a configuration][05] - Shows how to include the RebootPending +1. [Use the RebootPending resource in a configuration][05] - Shows how to include the RebootPending resource in a configuration document to check reboot status. ## Properties @@ -175,7 +175,7 @@ Indicates the resource operation failed. - [Use the RebootPending resource in a configuration][05] -[01]: ../registry/index.md +[01]: ../Registry/index.md [02]: ../../../../../concepts/resources/capabilities.md [03]: ../../../../../concepts/resources/properties.md [04]: ./examples/check-for-pending-reboot.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Registry/examples/configure-registry-keys-and-values.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Registry/examples/configure-registry-keys-and-values.md index 2915220..fe3a0fb 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Registry/examples/configure-registry-keys-and-values.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Registry/examples/configure-registry-keys-and-values.md @@ -229,7 +229,7 @@ To return your system to its original state: :::code language="yaml" source="registry.cleanup.config.dsc.yaml"::: -2. Use the **Set** operation on the cleanup configuration document. +1. Use the **Set** operation on the cleanup configuration document. ```powershell dsc config set --file ./registry.cleanup.config.dsc.yaml diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Registry/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Registry/index.md index 2fa3c9f..9a52fd3 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Registry/index.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Registry/index.md @@ -1,6 +1,6 @@ --- description: Microsoft.Windows/Registry resource reference documentation -ms.date: 07/03/2025 +ms.date: 03/25/2025 ms.topic: reference title: Microsoft.Windows/Registry --- @@ -431,7 +431,7 @@ The resource returns the following exit codes from operations: - [1](#exit-code-1) - Invalid parameter - [2](#exit-code-2) - Invalid input - [3](#exit-code-3) - Registry error -- [4](#exit-code-4) - Json serialization failed +- [4](#exit-code-4) - JSON serialization failed ### Exit code 0 @@ -471,6 +471,6 @@ Indicates the resource operation failed because the result couldn't be serialize [06]: ../../../../../concepts/resources/properties.md#required-resource-properties [07]: ../../../../../concepts/resources/properties.md#key-resource-properties [08]: ../../../../../concepts/resources/properties.md#read-only-resource-properties -[09]: /en-us/windows/win32/sysinfo/registry-value-types -[10]: ../../osinfo/index.md +[09]: /windows/win32/sysinfo/registry-value-types +[10]: ../../OSInfo/index.md [11]: /windows/win32/sysinfo/about-the-registry diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Service/examples/configure-windows-service.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Service/examples/configure-windows-service.md new file mode 100644 index 0000000..410fce7 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Service/examples/configure-windows-service.md @@ -0,0 +1,197 @@ +--- +description: > + Example showing how to use the Microsoft.Windows/Service resource in a DSC configuration + document to enforce the desired state of Windows services. +ms.date: 05/08/2026 +ms.topic: reference +title: Configure a Windows service +--- + +# Configure a Windows service + +This example shows how you can use the `Microsoft.Windows/Service` resource in a DSC configuration +document to enforce the desired configuration and runtime status of multiple Windows services. + +> [!IMPORTANT] +> **Set** operations for this resource require an elevated (administrator) process context. Run +> your terminal or PowerShell session as Administrator before using `dsc config set`. + +## Definition + +The configuration document for this example defines two instances of the `Service` resource. + +The first instance ensures that the Print Spooler service (`Spooler`) is stopped and configured +for manual start. The second instance ensures that the Windows Time service (`W32Time`) is running +and configured to start automatically. + +:::code language="yaml" source="service.config.dsc.yaml"::: + +Copy the configuration document and save it as `service.config.dsc.yaml`. + +## Setup + +The output in this example assumes that the system has the `Spooler` service stopped with a manual +startup and the `W32Time` service stopped with an automatic startup. You can set the system to +this starting state with the following commands: + +```powershell +Set-Service -Name Spooler -StartupType Manual -Status Stopped +Set-Service -Name W32Time -StartupType Automatic -Status Stopped +``` + +## Test the configuration + +To see whether the system is already in the desired state, use the [dsc config test][01] command. + +```powershell +dsc config test --file ./service.config.dsc.yaml +``` + +```yaml +executionInformation: + # Elided for brevity +metadata: + # Elided for brevity +results: +- executionInformation: + duration: PT0.1113118S + metadata: + Microsoft.DSC: + duration: PT0.1113118S + name: Ensure Print Spooler is stopped and set to manual start + type: Microsoft.Windows/Service + result: + desiredState: + name: Spooler + status: Stopped + startType: Manual + actualState: + name: Spooler + displayName: Print Spooler + description: This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers. + _exist: true + status: Stopped + startType: Manual + executablePath: C:\Windows\System32\spoolsv.exe + logonAccount: LocalSystem + errorControl: Normal + dependencies: + - RPCSS + inDesiredState: true + differingProperties: [] +- executionInformation: + duration: PT0.0353328S + metadata: + Microsoft.DSC: + duration: PT0.0353328S + name: Ensure Windows Time service is running + type: Microsoft.Windows/Service + result: + desiredState: + name: W32Time + status: Running + startType: Automatic + actualState: + name: W32Time + displayName: Windows Time + description: Maintains date and time synchronization on all clients and servers in the network. If this service is stopped, date and time synchronization will be unavailable. If this service is disabled, any services that explicitly depend on it will fail to start. + _exist: true + status: Stopped + startType: Automatic + executablePath: C:\Windows\system32\svchost.exe -k LocalService + logonAccount: NT AUTHORITY\LocalService + errorControl: Normal + inDesiredState: false + differingProperties: + - status +messages: [] +hadErrors: false +``` + +The `inDesiredState` field for the first instance is `true` because the Print Spooler service is +already `Stopped` with `Manual` start, so no change is required. The second instance is `false`: +the Windows Time service exists and already has `startType: Automatic`, but its `status` is +`Stopped` while the desired state requires `Running`. Only `status` is listed in +`differingProperties`. + +## Set the configuration + +To enforce the desired state, use the [dsc config set][02] command. + +```powershell +dsc config set --file ./service.config.dsc.yaml +``` + +```yaml +executionInformation: + # Elided for brevity +metadata: + # Elided for brevity +results: +- executionInformation: + duration: PT0.0924309S + metadata: + Microsoft.DSC: + duration: PT0.0924309S + name: Ensure Print Spooler is stopped and set to manual start + type: Microsoft.Windows/Service + result: + beforeState: + name: Spooler + status: Stopped + startType: Manual + afterState: + name: Spooler + displayName: Print Spooler + description: This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers. + _exist: true + status: Stopped + startType: Manual + executablePath: C:\Windows\System32\spoolsv.exe + logonAccount: LocalSystem + errorControl: Normal + dependencies: + - RPCSS + changedProperties: null +- executionInformation: + duration: PT0.3682548S + metadata: + Microsoft.DSC: + duration: PT0.3682548S + name: Ensure Windows Time service is running + type: Microsoft.Windows/Service + result: + beforeState: + name: W32Time + displayName: Windows Time + description: Maintains date and time synchronization on all clients and servers in the network. If this service is stopped, date and time synchronization will be unavailable. If this service is disabled, any services that explicitly depend on it will fail to start. + _exist: true + status: Stopped + startType: Automatic + executablePath: C:\Windows\system32\svchost.exe -k LocalService + logonAccount: NT AUTHORITY\LocalService + errorControl: Normal + afterState: + name: W32Time + displayName: Windows Time + description: Maintains date and time synchronization on all clients and servers in the network. If this service is stopped, date and time synchronization will be unavailable. If this service is disabled, any services that explicitly depend on it will fail to start. + _exist: true + status: Running + startType: Automatic + executablePath: C:\Windows\system32\svchost.exe -k LocalService + logonAccount: NT AUTHORITY\LocalService + errorControl: Normal + changedProperties: + - status +messages: [] +hadErrors: false +``` + +The Print Spooler instance shows `changedProperties: null` because it was already in the desired +state and DSC made no changes to it. The Windows Time instance lists only `status` in +`changedProperties` because DSC only needed to start the service. The `startType` was already +`Automatic` and required no update. + + +[01]: ../../../../../cli/config/test.md +[02]: ../../../../../cli/config/set.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Service/examples/get-service-status.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Service/examples/get-service-status.md new file mode 100644 index 0000000..f88b6f7 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Service/examples/get-service-status.md @@ -0,0 +1,87 @@ +--- +description: > + Example showing how to use the Microsoft.Windows/Service resource with DSC to retrieve the + current state of a Windows service. +ms.date: 05/08/2026 +ms.topic: reference +title: Get service status +--- + +# Get service status + +This example shows how you can use the `Microsoft.Windows/Service` resource to retrieve the +current configuration and runtime status of a Windows service. + +## Get the state of a service by name + +The following snippet shows how to use the resource with the [dsc resource get][01] command to +retrieve the current state of the `wuauserv` (Windows Update) service by its key name. + +```powershell +$instance = @{ name = 'wuauserv' } | ConvertTo-Json -Compress + +dsc resource get --resource Microsoft.Windows/Service --input $instance +``` + +When the service exists, DSC returns its full configuration and status: + +```yaml +actualState: + name: wuauserv + displayName: Windows Update + description: Enables the detection, download, and installation of updates for Windows and other programs. If this service is disabled, users of this computer will not be able to use Windows Update or its automatic updating feature, and programs will not be able to use the Windows Update Agent (WUA) API. + _exist: true + status: Stopped + startType: Manual + executablePath: C:\WINDOWS\System32\svchost.exe -k netsvcs -p + logonAccount: LocalSystem + errorControl: Normal + dependencies: + - rpcss +``` + +## Get the state of a service by display name + +You can also identify the service by its display name when you don't know the key name. + +```powershell +$instance = @{ displayName = 'Windows Update' } | ConvertTo-Json -Compress + +dsc resource get --resource Microsoft.Windows/Service --input $instance +``` + +DSC resolves the display name to the corresponding key name and returns the same result. + +## Get the state of a non-existent service + +When you request a service that isn't registered with the SCM, the resource returns `_exist: false` +and leaves all other properties unset. + +```powershell +$instance = @{ name = 'MyMissingService' } | ConvertTo-Json + +dsc resource get --resource Microsoft.Windows/Service --input $instance +``` + +```yaml +actualState: + name: MyMissingService + _exist: false +``` + +## Export all services + +To retrieve the state of every service registered on the system, use the [dsc resource export][02] +command without an input instance. + +```powershell +dsc resource export --resource Microsoft.Windows/Service +``` + +DSC writes a single JSON configuration document to stdout. That document contains a `resources` +array with one entry per service, which you can pipe to a file or process further with other +tools. + + +[01]: ../../../../../cli/resource/get.md +[02]: ../../../../../cli/resource/export.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Service/examples/service.config.dsc.yaml b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Service/examples/service.config.dsc.yaml new file mode 100644 index 0000000..94477c4 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Service/examples/service.config.dsc.yaml @@ -0,0 +1,15 @@ +# yaml-language-server: $schema=https://aka.ms/dsc/schemas/v3/bundled/config/document.vscode.json +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: + - name: Ensure Print Spooler is stopped and set to manual start + type: Microsoft.Windows/Service + properties: + name: Spooler + status: Stopped + startType: Manual + - name: Ensure Windows Time service is running + type: Microsoft.Windows/Service + properties: + name: W32Time + status: Running + startType: Automatic diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Service/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Service/index.md new file mode 100644 index 0000000..ebcb178 --- /dev/null +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/Service/index.md @@ -0,0 +1,424 @@ +--- +description: Microsoft.Windows/Service resource reference documentation +ms.date: 05/08/2026 +ms.topic: reference +title: Microsoft.Windows/Service +--- + +# Microsoft.Windows/Service + +## Synopsis + +Manage Windows services. + +## Metadata + +```yaml +Version : 0.1.0 +Kind : resource +Tags : [Windows] +Author : Microsoft +``` + +## Instance definition syntax + +```yaml +resources: + - name: + type: Microsoft.Windows/Service + properties: + # Key properties + name: string + # Instance properties + description: + dependencies: + displayName: + errorControl: + executablePath: + logonAccount: + startType: + status: +``` + +## Description + +The `Microsoft.Windows/Service` resource enables you to idempotently manage the configuration and +runtime state of Windows services registered with the Service Control Manager (SCM). The resource +can: + +- Retrieve the full configuration and status of a service. +- Change the start type, status, description, display name, logon account, error control, + executable path, and service dependencies. +- Export a list of all services registered on the system. + +> [!NOTE] +> This resource is installed with DSC itself on Windows systems. +> +> You can update this resource by updating DSC. When you update DSC, the updated version of this +> resource is automatically available. + +## Requirements + +- The resource is only usable on a Windows system. +- **Set** operations require an elevated (administrator) process context. Running `dsc` without + elevation when using the **Set** operation causes an access-denied error from the SCM. + +## Capabilities + +The resource has the following capabilities: + +- `get` - You can use the resource to retrieve the actual state of a service instance. +- `set` - You can use the resource to enforce the desired configuration and status of a service. +- `export` - You can use the resource to export a list of all services registered on the system. + +This resource uses the synthetic test functionality of DSC to determine whether an instance is in +the desired state. For more information about resource capabilities, see +[DSC resource capabilities][01]. + +## Examples + +1. [Get service status][02] - Shows how to retrieve the current state of a Windows service with the + `dsc resource` commands. +1. [Configure a Windows service][03] - Shows how to enforce the desired configuration of a Windows + service using a DSC configuration document. + +## Properties + +The following list describes the properties for the resource. + +- **Key properties:** The following properties uniquely identify an + instance. If two instances of a resource have the same values for their key properties, the + instances are conflicting. For more information about key properties, see the "Key resource + properties" section in [DSC resource properties][04]. + + - [name](#name) - The name of the service in the Service Control Manager. + +- **Instance properties:** The following properties are optional. + They define the desired state for an instance of the resource. + + - [dependencies](#dependencies) - A list of service names that this service depends on. + - [description](#description) - A description of the service. + - [displayName](#displayname) - The display name of the service shown in the Services console. + - [errorControl](#errorcontrol) - The error control level for the service. + - [executablePath](#executablepath) - The fully qualified path to the service binary. + - [logonAccount](#logonaccount) - The account under which the service runs. + - [startType](#starttype) - The start type of the service. + - [status](#status) - The current or desired status of the service. + +- **Read-only properties:** The resource returns the following + properties, but they aren't configurable. For more information about read-only properties, see + the "Read-only resource properties" section in [DSC resource properties][05]. + + - [_exist](#_exist) - Indicates whether the service exists in the Service Control Manager. + +### name + +
Expand for name property metadata + +```yaml +Type : string +IsRequired : false +IsKey : true +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +The service key name as registered in the Service Control Manager. This is the short internal name +used to identify the service. For example, `wuauserv` for Windows Update. This value is +case-insensitive. + +When performing a **Get** operation you may supply either `name` or `displayName` (or both) to +identify the service. For **Set** operations you must supply `name`. + +### displayName + +
Expand for displayName property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +The friendly display name of the service shown in the Windows Services console — for example, +`Windows Update`. You can define `displayName` instead of (or alongside) `name` in a **Get** +operation to locate a service when you don't know its key name. If both are provided, DSC verifies +that they refer to the same service and returns an error if they don't match. + +### description + +
Expand for description property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +A human-readable description of the service. Setting this property updates the description shown +in the Services console and the **Description** field in the SCM database. + +### _exist + +
Expand for _exist property metadata + +```yaml +Type : boolean +IsRequired : false +IsKey : false +IsReadOnly : true +IsWriteOnly : false +``` + +
+ +Indicates whether the service exists in the Service Control Manager. This property is returned by +the resource and cannot be set. A value of `true` means the service is registered; `false` means +it is not found. + +### status + +
Expand for status property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +Enum : [Running, Stopped, Paused, StartPending, StopPending, PausePending, ContinuePending] +``` + +
+ +The runtime status of the service. When used as desired state in a **Set** operation, only the +following values are valid: + +| Value | Effect | +|:----------|:---------------------------------------------| +| `Running` | DSC starts the service if it is not running. | +| `Stopped` | DSC stops the service if it is not stopped. | +| `Paused` | DSC pauses the service if it is not paused. | + +The following additional values may be returned by a **Get** or **Export** operation to describe a +transient state, but they must not be used as desired-state values: + +- `StartPending` +- `StopPending` +- `PausePending` +- `ContinuePending` + +### startType + +
Expand for startType property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +Enum : [Automatic, AutomaticDelayedStart, Manual, Disabled] +``` + +
+ +Defines how the service is started. The following values are valid: + +| Value | Description | +|:------------------------|:-------------------------------------------------------------------------------------| +| `Automatic` | The service is started automatically by the SCM at system startup. | +| `AutomaticDelayedStart` | The service starts automatically after other auto-start services have initialized. | +| `Manual` | The service is started only when explicitly requested (e.g., via `sc start`). | +| `Disabled` | The service cannot be started. | + +### executablePath + +
Expand for executablePath property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +The fully qualified path to the service binary, including any command-line arguments registered +with the SCM. For example, `C:\Windows\System32\svchost.exe -k netsvcs`. + +### logonAccount + +
Expand for logonAccount property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +The account under which the service process runs. Only the following built-in service accounts are +supported by the **Set** operation: + +- `LocalSystem` +- `NT AUTHORITY\LocalService` +- `NT AUTHORITY\NetworkService` + +Specifying a regular user account causes the **Set** operation to return an error. + +### errorControl + +
Expand for errorControl property metadata + +```yaml +Type : string +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +Enum : [Ignore, Normal, Severe, Critical] +``` + +
+ +Controls the action taken if the service fails to start during system boot. The following values +are valid: + +| Value | Description | +|:-----------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Ignore` | The error is logged and startup continues. | +| `Normal` | The error is logged, a message box is displayed, and startup continues. | +| `Severe` | The error is logged. If the last-known-good configuration is in use, startup continues; otherwise the system restarts with the last-known-good configuration. | +| `Critical` | The error is logged. If the last-known-good configuration is in use, startup fails; otherwise the system restarts with the last-known-good configuration. | + +### dependencies + +
Expand for dependencies property metadata + +```yaml +Type : array +ItemsType : string +ItemsMustBeUnique : false +IsRequired : false +IsKey : false +IsReadOnly : false +IsWriteOnly : false +``` + +
+ +A list of service key names that this service depends on. The SCM will not start the service until +all listed dependencies are running. Setting this property _replaces_ the existing dependency list +for the service. + +## Instance validating schema + +The following snippet contains the JSON Schema that validates an instance of the resource. + +```json +{ + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "description": { + "type": "string" + }, + "_exist": { + "type": "boolean", + "readOnly": true + }, + "status": { + "type": "string", + "enum": [ + "Running", "Stopped", "Paused", + "StartPending", "StopPending", "PausePending", "ContinuePending" + ] + }, + "startType": { + "type": "string", + "enum": ["Automatic", "AutomaticDelayedStart", "Manual", "Disabled"] + }, + "executablePath": { + "type": "string" + }, + "logonAccount": { + "type": "string" + }, + "errorControl": { + "type": "string", + "enum": ["Ignore", "Normal", "Severe", "Critical"] + }, + "dependencies": { + "type": "array", + "items": { + "type": "string" + } + } + } +} +``` + +## Exit codes + +The resource returns the following exit codes from operations: + +- [0](#exit-code-0) - Success +- [1](#exit-code-1) - Invalid arguments +- [2](#exit-code-2) - Invalid input +- [3](#exit-code-3) - Service error + +### Exit code 0 + +Indicates the resource operation completed without errors. + +### Exit code 1 + +Indicates the resource operation failed because required arguments were missing or the operation +name was not recognized. + +### Exit code 2 + +Indicates the resource operation failed because the JSON input could not be deserialized into a +valid `WindowsService` instance. + +### Exit code 3 + +Indicates the resource operation failed due to an error raised by the Windows Service Control +Manager API, or the result could not be serialized. + +## See also + +- [Microsoft.Windows/Registry resource][06] +- [DSC resource capabilities][01] +- [DSC resource properties][07] + + +[01]: ../../../../../concepts/resources/capabilities.md +[02]: ./examples/get-service-status.md +[03]: ./examples/configure-windows-service.md +[04]: ../../../../../concepts/resources/properties.md#key-resource-properties +[05]: ../../../../../concepts/resources/properties.md#read-only-resource-properties +[06]: ../Registry/index.md +[07]: ../../../../../concepts/resources/properties.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WMI/examples/query-filtered-disk-info.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WMI/examples/query-filtered-disk-info.md index f1c70a3..875686d 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WMI/examples/query-filtered-disk-info.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WMI/examples/query-filtered-disk-info.md @@ -2,9 +2,10 @@ description: > Example showing how to use the Microsoft.Windows/WMI resource adapter to query disk information with filtering using the Win32_LogicalDisk class. -ms.date: 07/03/2025 + +ms.date: 03/25/2025 ms.topic: reference -title: Query filtered disk information using WMI adapter +title: Query filtered disk information using WMI adapter --- # Query filtered disk information using WMI adapter @@ -15,7 +16,8 @@ specific drives using a configuration document. ## Definition -The configuration document for this example defines one instances of the `Win32_LogicalDisk` resource. +The configuration document for this example defines one instance of the `Win32_LogicalDisk` +resource. The instance defines the properties to return in the output. diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WMI/examples/query-operating-system-info.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WMI/examples/query-operating-system-info.md index dd19544..23bff65 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WMI/examples/query-operating-system-info.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WMI/examples/query-operating-system-info.md @@ -3,9 +3,9 @@ description: > Example showing how to use the Microsoft.Windows/WMI resource adapter to query system information using the Win32_ComputerSystem class. -ms.date: 07/03/2025 +ms.date: 03/25/2025 ms.topic: reference -title: Query system information using WMI adapter +title: Query system information using WMI adapter --- # Query system information using WMI adapter diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WMI/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WMI/index.md index 20814b3..181465d 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WMI/index.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WMI/index.md @@ -1,6 +1,6 @@ --- description: Microsoft.Windows/WMI resource adapter reference documentation -ms.date: 07/03/2025 +ms.date: 03/25/2025 ms.topic: reference title: Microsoft.Windows/WMI --- @@ -32,11 +32,8 @@ resources: - name: type: / properties: # adapted resource properties -``` - -## Implicit adapted instance definition syntax -```yaml +# Or from v3.1.0-preview.2 onwards resources: - name: type: / diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md index 13a9e11..6f5daac 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md @@ -2,9 +2,10 @@ description: > Examples showing how you can invoke the Microsoft.Windows/WindowsPowerShell with DSC to manage a Windows service using the PSDesiredStateConfiguration module. -ms.date: 07/03/2025 -ms.topic: reference -title: Manage a Windows service + +ms.date: 03/25/2025 +ms.topic: reference +title: Manage a Windows service --- # Manage a Windows service @@ -14,12 +15,13 @@ This example shows how you can use the `Microsoft.Windows/WindowsPowerShell` res `Spooler` print spooler service. > [!NOTE] -> Run this example in an elevated PowerShell session with `dsc.exe` version 3.1.0 or later. +> Run this example in an elevated PowerShell session with `dsc.exe` version 3.1.0-preview.2 or +> later. ## Test whether a service is running -The following snippet shows how you can use the resource with the [dsc resource test][01] command -to check whether the `Spooler` service is running. +The following snippet shows how you can use the resource with the [dsc resource test][01] command to +check whether the `Spooler` service is running. ```powershell $instance = @{ @@ -44,8 +46,8 @@ differingProperties: ``` The `inDesiredState` field of the result object is set to `false`, indicating that the instance -isn't in the desired state. The `differingProperties` field indicates that the `property` property -is mismatched between the desired state and actual state. +isn't in the desired state. The `differingProperties` field indicates that the `StartupType` +property is mismatched between the desired state and actual state. ## Ensure a service is running with automatic startup diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md index f6ae961..efa59ea 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md @@ -1,6 +1,6 @@ --- description: Microsoft.Windows/WindowsPowerShell resource adapter reference documentation -ms.date: 07/03/2025 +ms.date: 03/25/2025 ms.topic: reference title: Microsoft.Windows/WindowsPowerShell --- @@ -32,11 +32,8 @@ resources: - name: type: / properties: # adapted resource properties -``` - -## Implicit adapted instance definition syntax -```yaml +# Or from v3.1.0-preview.2 onwards resources: - name: type: / @@ -53,7 +50,7 @@ resources. The resource can: - Execute binary DSC resources The adapter manages the PSDSC resources in Windows PowerShell, not PowerShell. To use PowerShell -classes in PowerShell, use the [Microsoft.DSC/PowerShell](../../dsc/powershell/index.md) adapter. +classes in PowerShell, use the [Microsoft.DSC/PowerShell](../../DSC/PowerShell/index.md) adapter. This adapter uses the **PSDesiredStateConfiguration** module v1.1. This module is built-in when you install Windows and is located in `%SystemRoot%\System32\WindowsPowerShell\v1.0\Modules` @@ -224,7 +221,7 @@ For more information about type names in DSC, see ```yaml Type: string Required: true -Pattern: ^\w+(\.\w+){0,3}\/\w+$ +Pattern: ^\w+(\.\w+){0,2}\/\w+$ ``` ### Adapted instance properties diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/builtin.md b/dsc/docs-conceptual/dsc-3.0/reference/resources/builtin.md index 7d989c5..3cb2a76 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/builtin.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/builtin.md @@ -1,75 +1,136 @@ --- description: >- - Lists the builtin DSC resources and links to the reference documentation for those resources. -ms.date: 03/25/2025 -title: Builtin DSC resources reference + Lists the built-in DSC resources and links to the reference documentation for those resources. +ms.date: 08/10/2026 +ms.topic: reference +title: Built-in DSC resources reference --- -# Builtin DSC resources reference +# Built-in DSC resources reference -Each release of DSC includes builtin resources that you can use immediately after you install DSC. +Each release of DSC includes built-in resources that you can use immediately after you install DSC. This document lists the available resources and links to the reference documentation for each. > [!NOTE] -> The team hasn't documented every builtin resource yet. As they add reference documentation for +> The team hasn't documented every built-in resource yet. As they add reference documentation for > these resources, the team will update this article to link to the documentation for those > resources. -## All builtin resources +## All built-in resources -- [Microsoft/OSInfo][01] - Returns information about the operating system. +- [DSC.PackageManagement/Apt][01] - Manage packages with the advanced package tool (APT) on Linux + systems. +- [DSC.PackageManagement/Brew][02] - Manage packages using Homebrew on macOS systems. +- [Microsoft/OSInfo][03] - Returns information about the operating system. +- [Microsoft.Adapter/PowerShell][04] - Adapter for resources implemented as PowerShell DSC classes. +- [Microsoft.Adapter/WindowsPowerShell][05] - Adapter for resources implemented as binary, script, + or PowerShell classes in Windows PowerShell. - `Microsoft.DSC/Assertion` - `Microsoft.DSC/Group` -- `Microsoft.DSC/Include` -- `Microsoft.DSC/PowerShell` -- `Microsoft.DSC.Debug/Echo` -- `Microsoft.DSC.Transitional/RunCommandOnSet` -- `Microsoft.Windows/RebootPending` -- [Microsoft.Windows/Registry][09] - Manage Windows Registry keys and values. -- `Microsoft.Windows/WindowsPowerShell` -- `Microsoft.Windows/WMI` - -## Builtin assertion resources - -You can use the following builtin resources to query the current state of a machine but not to +- [Microsoft.DSC/Include][06] - Includes a nested configuration document, with optional parameters, + into the current configuration. +- [Microsoft.DSC/PowerShell][07] - Adapter for resources implemented as PowerShell classes. +- [Microsoft.DSC.Debug/Echo][08] - A debug resource for testing and troubleshooting DSC behavior. +- [Microsoft.DSC.Transitional/PowerShellScript][09] - Enable running PowerShell 7 scripts inline. +- [Microsoft.DSC.Transitional/RunCommandOnSet][10] - Execute a command during DSC **Set** + operation. +- [Microsoft.DSC.Transitional/WindowsPowerShellScript][11] - Enable running Windows PowerShell 5.1 + scripts inline. +- [Microsoft.Windows/FeatureOnDemandList][12] - Manage Windows features on demand (capabilities) + using the DISM API. +- [Microsoft.Windows/FirewallRuleList][13] - Manage Windows Firewall rules using the netfw.h APIs. +- [Microsoft.Windows/OptionalFeatureList][14] - Manage Windows Optional features using the DISM + API. +- [Microsoft.Windows/RebootPending][15] - Checks if a Windows system has a pending reboot. +- [Microsoft.Windows/Registry][16] - Manage Windows Registry keys and values. +- [Microsoft.Windows/Service][17] - Manage Windows services. +- [Microsoft.Windows/WindowsPowerShell][18] - Adapter for resources implemented as binary, script, + or PowerShell classes. +- [Microsoft.Windows/WMI][19] - Adapter for querying and retrieving information from Windows + Management Instrumentation (WMI). + +## Built-in assertion resources + +You can use the following built-in resources to query the current state of a machine but not to change the state of the machine directly: -- [Microsoft/OSInfo][01] - Returns information about the operating system. +- [Microsoft/OSInfo][03] - Returns information about the operating system. - `Microsoft.DSC/Assertion` -- `Microsoft.Windows/RebootPending` +- [Microsoft.Windows/RebootPending][15] - Checks if a Windows system has a pending reboot. -## Builtin adapter resources +## Built-in adapter resources -You can use the following builtin resources to handle resources that don't have a DSC resource +You can use the following built-in resources to handle resources that don't define a DSC resource manifest: -- `Microsoft.DSC/PowerShell` -- `Microsoft.Windows/WindowsPowerShell` -- `Microsoft.Windows/WMI` - -## Builtin configurable resources - -The following builtin resources to change the state of a machine directly: - -- `Microsoft.DSC.Transitional/RunCommandOnSet` -- [Microsoft.Windows/Registry][09] - Manage Windows Registry keys and values. - -## Builtin debugging resources - -You can use the following builtin resources when debugging or exploring DSC. They don't affect +- [Microsoft.Adapter/PowerShell][04] - Adapter for resources implemented as PowerShell DSC classes. +- [Microsoft.Adapter/WindowsPowerShell][05] - Adapter for resources implemented as binary, script, + or PowerShell classes in Windows PowerShell. +- [Microsoft.DSC/PowerShell][07] - Adapter for resources implemented as PowerShell classes. +- [Microsoft.Windows/WindowsPowerShell][18] - Adapter for resources implemented as binary, script, + or PowerShell classes. +- [Microsoft.Windows/WMI][19] - Adapter for querying and retrieving information from Windows + Management Instrumentation (WMI). + +> [!WARNING] +> `Microsoft.DSC/PowerShell` and `Microsoft.Windows/WindowsPowerShell` will be deprecated in a +> future release. Use `Microsoft.Adapter/PowerShell` and `Microsoft.Adapter/WindowsPowerShell` +> instead. + +## Built-in configurable resources + +You can use the following built-in resources to change the state of a machine directly: + +- [DSC.PackageManagement/Apt][01] - Manage packages with the advanced package tool (APT) on Linux + systems. +- [DSC.PackageManagement/Brew][02] - Manage packages using Homebrew on macOS systems. +- [Microsoft.DSC.Transitional/PowerShellScript][09] - Enable running PowerShell 7 scripts inline. +- [Microsoft.DSC.Transitional/RunCommandOnSet][10] - Execute a command during DSC **Set** + operation. +- [Microsoft.DSC.Transitional/WindowsPowerShellScript][11] - Enable running Windows PowerShell 5.1 + scripts inline. +- [Microsoft.Windows/FeatureOnDemandList][12] - Manage Windows features on demand (capabilities) + using the DISM API. +- [Microsoft.Windows/FirewallRuleList][13] - Manage Windows Firewall rules using the netfw.h APIs. +- [Microsoft.Windows/OptionalFeatureList][14] - Manage Windows Optional features using the DISM + API. +- [Microsoft.Windows/Registry][16] - Manage Windows Registry keys and values. +- [Microsoft.Windows/Service][17] - Manage Windows services. + +## Built-in debugging resources + +You can use the following built-in resources when debugging or exploring DSC. They don't affect the state of the machine. -- `Microsoft.DSC.Debug/Echo` +- [Microsoft.DSC.Debug/Echo][08] - A debug resource for testing and troubleshooting DSC behavior. -## Builtin group resources +## Built-in group resources -You can use the following builtin resources to change how DSC processes a group of nested resource +You can use the following built-in resources to change how DSC processes a group of nested resource instances: - `Microsoft.DSC/Assertion` - `Microsoft.DSC/Group` -- `Microsoft.DSC/Include` +- [Microsoft.DSC/Include][06] - Includes a nested configuration document, with optional parameters, + into the current configuration. -[01]: ./Microsoft/OSInfo/index.md -[09]: ./Microsoft/Windows/Registry/index.md +[01]: ./DSC/PackageManagement/APT/index.md +[02]: ./DSC/PackageManagement/Brew/index.md +[03]: ./Microsoft/OSInfo/index.md +[04]: ./Microsoft/Adapter/PowerShell/index.md +[05]: ./Microsoft/Adapter/WindowsPowerShell/index.md +[06]: ./Microsoft/DSC/Include/index.md +[07]: ./Microsoft/DSC/PowerShell/index.md +[08]: ./Microsoft/DSC/Debug/echo/index.md +[09]: ./Microsoft/DSC/Transitional/PowerShellScript/index.md +[10]: ./Microsoft/DSC/Transitional/RunCommandOnSet/index.md +[11]: ./Microsoft/DSC/Transitional/WindowsPowerShellScript/index.md +[12]: ./Microsoft/Windows/FeatureOnDemandList/index.md +[13]: ./Microsoft/Windows/FirewallRuleList/index.md +[14]: ./Microsoft/Windows/OptionalFeatureList/index.md +[15]: ./Microsoft/Windows/RebootPending/index.md +[16]: ./Microsoft/Windows/Registry/index.md +[17]: ./Microsoft/Windows/Service/index.md +[18]: ./Microsoft/Windows/WindowsPowerShell/index.md +[19]: ./Microsoft/Windows/WMI/index.md diff --git a/dsc/docs-conceptual/dsc-3.0/reference/resources/toc.yml b/dsc/docs-conceptual/dsc-3.0/reference/resources/toc.yml index d279b0d..b154cca 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/resources/toc.yml +++ b/dsc/docs-conceptual/dsc-3.0/reference/resources/toc.yml @@ -1,9 +1,9 @@ items: - - name: Builtin resources + - name: Built-in resources items: - name: Overview href: builtin.md - - name: DSC.PackageManagement/APT + - name: DSC.PackageManagement/Apt items: - name: DSC resource href: DSC/PackageManagement/APT/index.md @@ -11,18 +11,16 @@ items: items: - name: Manage packages href: DSC/PackageManagement/APT/examples/manage-packages-with-apt.md - - name: Microsoft.DSC.Debug/Echo + - name: DSC.PackageManagement/Brew items: - name: DSC resource - href: Microsoft/DSC/Debug/Echo/index.md + href: DSC/PackageManagement/Brew/index.md - name: Examples items: - - name: Basic usage - href: Microsoft/DSC/Debug/Echo/examples/basic-echo-example.md - - name: Microsoft.DSC/PowerShell - items: - - name: DSC resource - href: Microsoft/Dsc/PowerShell/index.md + - name: Install a package + href: DSC/PackageManagement/Brew/examples/install-a-package-with-brew.md + - name: Remove a package + href: DSC/PackageManagement/Brew/examples/remove-a-package.md - name: Microsoft/OSInfo items: - name: DSC resource @@ -32,7 +30,121 @@ items: - name: Validate OS with dsc resource commands href: Microsoft/OSInfo/examples/validate-with-dsc-resource.md - name: Validate OS in a configuration - href: Microsoft/OSInfo/examples/validate-with-dsc-resource.md + href: Microsoft/OSInfo/examples/validate-in-a-configuration.md + - name: Validate a minimum OS version + href: Microsoft/OSInfo/examples/validate-minimum-version.md + - name: Microsoft.Adapter/PowerShell + items: + - name: DSC resource + href: Microsoft/Adapter/PowerShell/index.md + - name: Examples + items: + - name: Invoke a resource + href: Microsoft/Adapter/PowerShell/examples/invoke-a-resource.md + - name: Configure a machine + href: Microsoft/Adapter/PowerShell/examples/configure-a-machine.md + - name: Microsoft.Adapter/WindowsPowerShell + items: + - name: DSC resource + href: Microsoft/Adapter/WindowsPowerShell/index.md + - name: Examples + items: + - name: Manage a Windows service + href: Microsoft/Adapter/WindowsPowerShell/examples/manage-a-windows-service.md + - name: Microsoft.DSC/Include + items: + - name: DSC resource + href: Microsoft/DSC/Include/index.md + - name: Examples + items: + - name: Include a configuration file + href: Microsoft/DSC/Include/examples/include-a-configuration-file.md + - name: Include inline configuration content + href: Microsoft/DSC/Include/examples/include-inline-configuration-content.md + - name: Microsoft.DSC/PowerShell + items: + - name: DSC resource + href: Microsoft/DSC/PowerShell/index.md + - name: Microsoft.DSC.Debug/Echo + items: + - name: DSC resource + href: Microsoft/DSC/Debug/echo/index.md + - name: Examples + items: + - name: Basic usage + href: Microsoft/DSC/Debug/echo/examples/basic-echo-example.md + - name: Microsoft.DSC.Transitional/PowerShellScript + items: + - name: DSC resource + href: Microsoft/DSC/Transitional/PowerShellScript/index.md + - name: Examples + items: + - name: Configure with a script + href: Microsoft/DSC/Transitional/PowerShellScript/examples/configure-with-script.md + - name: Invoke with input data + href: Microsoft/DSC/Transitional/PowerShellScript/examples/invoke-with-input-data.md + - name: Invoke with output data + href: Microsoft/DSC/Transitional/PowerShellScript/examples/invoke-with-output-data.md + - name: Invoke with trace messaging + href: Microsoft/DSC/Transitional/PowerShellScript/examples/invoke-with-messaging.md + - name: Microsoft.DSC.Transitional/RunCommandOnSet + items: + - name: DSC resource + href: Microsoft/DSC/Transitional/RunCommandOnSet/index.md + - name: Examples + items: + - name: Run a simple command + href: Microsoft/DSC/Transitional/RunCommandOnSet/examples/run-a-simple-command.md + - name: Run a PowerShell command + href: Microsoft/DSC/Transitional/RunCommandOnSet/examples/run-powershell-command.md + - name: Microsoft.DSC.Transitional/WindowsPowerShellScript + items: + - name: DSC resource + href: Microsoft/DSC/Transitional/WindowsPowerShellScript/index.md + - name: Examples + items: + - name: Configure with a script + href: Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/configure-with-script.md + - name: Invoke with input data + href: Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/invoke-with-input-data.md + - name: Invoke with output data + href: Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/invoke-with-output-data.md + - name: Invoke with trace messaging + href: Microsoft/DSC/Transitional/WindowsPowerShellScript/examples/invoke-with-messaging.md + - name: Microsoft.Windows/FeatureOnDemandList + items: + - name: DSC resource + href: Microsoft/Windows/FeatureOnDemandList/index.md + - name: Examples + items: + - name: Get feature on demand state + href: Microsoft/Windows/FeatureOnDemandList/examples/get-feature-on-demand.md + - name: Install and remove features + href: Microsoft/Windows/FeatureOnDemandList/examples/install-remove-feature-on-demand.md + - name: Export features on demand + href: Microsoft/Windows/FeatureOnDemandList/examples/export-features-on-demand.md + - name: Microsoft.Windows/FirewallRuleList + items: + - name: DSC resource + href: Microsoft/Windows/FirewallRuleList/index.md + - name: Examples + items: + - name: Get firewall rule state + href: Microsoft/Windows/FirewallRuleList/examples/get-firewall-rules.md + - name: Configure firewall rules + href: Microsoft/Windows/FirewallRuleList/examples/configure-firewall-rules.md + - name: Microsoft.Windows/OptionalFeatureList + items: + - name: DSC resource + href: Microsoft/Windows/OptionalFeatureList/index.md + - name: Examples + items: + - name: Get optional feature state + href: Microsoft/Windows/OptionalFeatureList/examples/get-optional-feature.md + - name: Enable and disable features + href: Microsoft/Windows/OptionalFeatureList/examples/enable-disable-optional-features.md + - name: Export optional features + href: Microsoft/Windows/OptionalFeatureList/examples/export-optional-features.md - name: Microsoft.Windows/RebootPending items: - name: DSC resource @@ -55,6 +167,16 @@ items: href: Microsoft/Windows/Registry/examples/manage-a-registry-value.md - name: Configure keys and values href: Microsoft/Windows/Registry/examples/configure-registry-keys-and-values.md + - name: Microsoft.Windows/Service + items: + - name: DSC resource + href: Microsoft/Windows/Service/index.md + - name: Examples + items: + - name: Get service status + href: Microsoft/Windows/Service/examples/get-service-status.md + - name: Configure a Windows service + href: Microsoft/Windows/Service/examples/configure-windows-service.md - name: Microsoft.Windows/WindowsPowerShell items: - name: DSC resource diff --git a/dsc/docs-conceptual/dsc-3.0/reference/schemas/config/resource.md b/dsc/docs-conceptual/dsc-3.0/reference/schemas/config/resource.md index 86ece6b..74b3853 100644 --- a/dsc/docs-conceptual/dsc-3.0/reference/schemas/config/resource.md +++ b/dsc/docs-conceptual/dsc-3.0/reference/schemas/config/resource.md @@ -1,6 +1,6 @@ --- description: JSON schema reference for a resource instance in a Desired State Configuration document. -ms.date: 07/03/2025 +ms.date: 08/13/2026 ms.topic: reference title: DSC Configuration document resource instance schema --- @@ -143,6 +143,48 @@ ItemsType: string ItemsPattern: ^\[resourceId\(\s*'\w+(\.\w+){0,2}\/\w+'\s*,\s*'[a-zA-Z0-9 ]+'\s*\)\]$ ``` +### directives + +The `directives` property of a resource instance defines per-instance overrides for how DSC should +process the resource. This property was added in DSC version 3.2. + +```yaml +Type: object +Required: false +``` + +You can define the following directives for a resource instance: + +#### requireAdapter + +The `requireAdapter` directive indicates that DSC should use the specified adapter to invoke the +adapted resource instance. The value for this directive must be the fully qualified type name of +the adapter resource, like `Microsoft.Adapter/PowerShell`. + +When this directive isn't specified, DSC invokes the adapted resource through the first discovered +adapter that indicates it can invoke the resource. This directive has no effect on nonadapted +resource instances. + +```yaml +Type: string +Required: false +Pattern: ^\w+(\.\w+){0,2}\/\w+$ +``` + +#### securityContext + +The `securityContext` directive indicates that DSC should validate the current security context +against this directive before invoking the resource. This value overrides the +`metadata.Microsoft.DSC.securityContext` setting for the top level of the configuration document. +This enables you to selectively require or forbid elevated security contexts for a specific +resource instance. + +```yaml +Type: string +Required: false +ValidValues: [Current, Elevated, Restricted] +``` + [01]: ../definitions/resourceType.md [02]: functions/resourceId.md [03]: /powershell/dsc/glossary#nested-resource-instance