From 3955d0966bd638445c8fcdbb2858f37ab1d885eb Mon Sep 17 00:00:00 2001 From: "G.Reijn" Date: Thu, 29 May 2025 12:04:19 +0200 Subject: [PATCH 01/11] Implement export in WinPS adapter --- .github/workflows/rust.yml | 2 +- .../Tests/win_powershellgroup.tests.ps1 | 24 +++ .../psDscAdapter/psDscAdapter.psm1 | 14 +- .../psDscAdapter/win_psDscAdapter.psm1 | 27 +++ .../windowspowershell.dsc.resource.json | 158 ++++++++++-------- test.yaml | 8 + 6 files changed, 147 insertions(+), 86 deletions(-) create mode 100644 test.yaml diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 620fdcde6..aca2363bb 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,7 +2,7 @@ name: Rust on: push: - branches: [ "main" ] + branches: [ "*" ] pull_request: branches: [ "main" ] paths-ignore: diff --git a/powershell-adapter/Tests/win_powershellgroup.tests.ps1 b/powershell-adapter/Tests/win_powershellgroup.tests.ps1 index ec305840c..e2258888a 100644 --- a/powershell-adapter/Tests/win_powershellgroup.tests.ps1 +++ b/powershell-adapter/Tests/win_powershellgroup.tests.ps1 @@ -322,6 +322,22 @@ class PSClassResource { [void] Set() { } + + static [PSClassResource[]] Export() + { + $resultList = [System.Collections.Generic.List[PSClassResource]]::new() + $resultCount = 5 + if ($env:PSClassResourceResultCount) { + $resultCount = $env:PSClassResourceResultCount + } + 1..$resultCount | %{ + $obj = New-Object PSClassResource + $obj.Name = "Object$_" + $resultList.Add($obj) + } + + return $resultList.ToArray() + } } '@ @@ -350,4 +366,12 @@ class PSClassResource { $LASTEXITCODE | Should -Be 0 $out.afterstate.InDesiredState | Should -Be $true } + + It 'Export works with class-based PS DSC resources' -Skip:(!$IsWindows) { + + $out = dsc resource export -r PSClassResource/PSClassResource | ConvertFrom-Json + $LASTEXITCODE | Should -Be 0 + $out | Should -Not -BeNullOrEmpty + $out.resources.count | Should -Be 5 + } } \ No newline at end of file diff --git a/powershell-adapter/psDscAdapter/psDscAdapter.psm1 b/powershell-adapter/psDscAdapter/psDscAdapter.psm1 index ffee99d94..95576b1a4 100644 --- a/powershell-adapter/psDscAdapter/psDscAdapter.psm1 +++ b/powershell-adapter/psDscAdapter/psDscAdapter.psm1 @@ -464,19 +464,7 @@ function Invoke-DscOperation { $addToActualState.properties = [psobject]@{'InDesiredState' = $Result } } 'Export' { - $t = $dscResourceInstance.GetType() - $methods = $t.GetMethods() | Where-Object { $_.Name -eq 'Export' } - $method = foreach ($mt in $methods) { - if ($mt.GetParameters().Count -eq 0) { - $mt - break - } - } - - if ($null -eq $method) { - "Export method not implemented by resource '$($DesiredState.Type)'" | Write-DscTrace -Operation Error - exit 1 - } + $method = ValidateMethod -operation $Operation -class $dscResourceInstance $resultArray = @() $raw_obj_array = $method.Invoke($null, $null) foreach ($raw_obj in $raw_obj_array) { diff --git a/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 b/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 index a6cd6e439..8904b8dea 100644 --- a/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 +++ b/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 @@ -532,6 +532,33 @@ function GetTypeInstanceFromModule { return $instance } +# ValidateMethod checks if the specified method exists in the class +function ValidateMethod { + param ( + [Parameter(Mandatory = $true)] + [ValidateSet('Export', 'WhatIf')] + [string] $operation, + [Parameter(Mandatory = $true)] + [object] $class + ) + + $t = $class.GetType() + $methods = $t.GetMethods() | Where-Object -Property Name -EQ $operation + $method = foreach ($mt in $methods) { + if ($mt.GetParameters().Count -eq 0) { + $mt + break + } + } + + if ($null -eq $method) { + "Method '$operation' not implemented by resource '$($t.Name)'" | Write-DscTrace -Operation Error + exit 1 + } + + return $method +} + # cached resource class dscResourceCacheEntry { [string] $Type diff --git a/powershell-adapter/windowspowershell.dsc.resource.json b/powershell-adapter/windowspowershell.dsc.resource.json index ba6aabfb0..9121be753 100644 --- a/powershell-adapter/windowspowershell.dsc.resource.json +++ b/powershell-adapter/windowspowershell.dsc.resource.json @@ -1,41 +1,14 @@ { - "$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json", - "type": "Microsoft.Windows/WindowsPowerShell", - "version": "0.1.0", - "kind": "adapter", - "description": "Resource adapter to classic DSC Powershell resources in Windows PowerShell.", - "tags": [ - "PowerShell" - ], - "adapter": { - "list": { - "executable": "powershell", - "args": [ - "-NoLogo", - "-NonInteractive", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-Command", - "./psDscAdapter/powershell.resource.ps1 List" - ] - }, - "config": "full" - }, - "get": { - "executable": "powershell", - "args": [ - "-NoLogo", - "-NonInteractive", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-Command", - "$Input | ./psDscAdapter/powershell.resource.ps1 Get" - ], - "input": "stdin" - }, - "set": { + "$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json", + "type": "Microsoft.Windows/WindowsPowerShell", + "version": "0.1.0", + "kind": "adapter", + "description": "Resource adapter to classic DSC Powershell resources in Windows PowerShell.", + "tags": [ + "PowerShell" + ], + "adapter": { + "list": { "executable": "powershell", "args": [ "-NoLogo", @@ -44,39 +17,80 @@ "-ExecutionPolicy", "Bypass", "-Command", - "$Input | ./psDscAdapter/powershell.resource.ps1 Set" - ], - "input": "stdin", - "preTest": true - }, - "test": { - "executable": "powershell", - "args": [ - "-NoLogo", - "-NonInteractive", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-Command", - "$Input | ./psDscAdapter/powershell.resource.ps1 Test" - ], - "input": "stdin", - "return": "state" - }, - "validate": { - "executable": "powershell", - "args": [ - "-NoLogo", - "-NonInteractive", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-Command", - "$Input | ./psDscAdapter/powershell.resource.ps1 Validate" - ] - }, - "exitCodes": { - "0": "Success", - "1": "Error" - } + "./psDscAdapter/powershell.resource.ps1 List" + ] + }, + "config": "full" + }, + "get": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Get" + ], + "input": "stdin" + }, + "set": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Set" + ], + "input": "stdin", + "preTest": true + }, + "test": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Test" + ], + "input": "stdin", + "return": "state" + }, + "export": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Export" + ], + "input": "stdin", + "return": "state" + }, + "validate": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Validate" + ] + }, + "exitCodes": { + "0": "Success", + "1": "Error" } +} \ No newline at end of file diff --git a/test.yaml b/test.yaml new file mode 100644 index 000000000..b1dc4dd77 --- /dev/null +++ b/test.yaml @@ -0,0 +1,8 @@ +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: +- name: Class-resource Info + type: PSClassResource/PSClassResource +# $schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +# resources: +# - name: Class-resource Info +# type: TestClassResource/TestClassResource \ No newline at end of file From 5845fcc8575552661095caaa5995dcf56f262e33 Mon Sep 17 00:00:00 2001 From: "G.Reijn" Date: Thu, 29 May 2025 13:08:57 +0200 Subject: [PATCH 02/11] Add documentation --- .github/workflows/rust.yml | 2 +- .../examples/manage-a-windows-service.md | 228 ++++++++++++++++++ .../Windows/WindowsPowerShell/index.md | 133 ++++++++++ 3 files changed, 362 insertions(+), 1 deletion(-) create mode 100644 docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index aca2363bb..620fdcde6 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,7 +2,7 @@ name: Rust on: push: - branches: [ "*" ] + branches: [ "main" ] pull_request: branches: [ "main" ] paths-ignore: diff --git a/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md b/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md new file mode 100644 index 000000000..fdefffd11 --- /dev/null +++ b/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md @@ -0,0 +1,228 @@ +--- +description: > + Examples showing how you can invoke the Microsoft.Windows/WindowsPowerShell with DSC to manage + a Windows service using the PSDesiredStateConfiguration module. + +ms.date: 03/25/2025 +ms.topic: reference +title: Manage a Windows service +--- + +This example shows how you can use the `Microsoft.Windows/WindowsPowerShell` resource with the `PSDesiredStateConfiguration` module 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.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. + +```powershell +$instance = @{ + Name = 'Spooler' + StartupType = 'Automatic' +} | ConvertTo-Json + +dsc resource test --resource PSDesiredStateConfiguration/Service --input $instance +``` + +When the service isn't running or has a different startup type, DSC returns the following result: + +```yaml +desiredState: + Name: Spooler + StartupType: Manual +actualState: + InDesiredState: false +inDesiredState: false +differingProperties: +- StartupType +``` + +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. + +## Ensure a service is running with automatic startup + +To set the system to the desired state and configure the service, use the [dsc resource set][02] command. + +```powershell +dsc resource set --resource PSDesiredStateConfiguration/Service --input $instance +``` + +When the resource configures the service, DSC returns the following result: + +```yaml +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 +``` + +You can test the instance again to confirm that the service is configured correctly: + +```powershell +dsc resource test --resource PSDesiredStateConfiguration/Service --input $instance +``` + +```yaml +desiredState: + Name: Spooler / + StartupType: Manual +actualState: + InDesiredState: true +inDesiredState: true +differingProperties: [] +``` + +## Stop a service + +The following snippet shows how you can configure the `Spooler` service to be stopped with manual startup. + +```powershell +$stopInstance = @{ + Name = 'Spooler' + State = 'Stopped' + StartupType = 'Manual' +} | ConvertTo-Json + +dsc resource set --resource PSDesiredStateConfiguration/Service --input $stopInstance +``` + +When the resource stops the service, DSC returns the following result: + +```yaml +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: Manual + State: Stopped + ModuleVersion: '1.1' + ModuleName: PSDesiredStateConfiguration + Path: C:\WINDOWS\System32\spoolsv.exe + Dependencies: + - RPCSS + - http +changedProperties: +- State +``` + +## Verify the current state of a service + +To check the current state of the service, use the `dsc resource get` command. + +```powershell +dsc resource get --resource PSDesiredStateConfiguration/Service --input $instance +``` + +```yaml +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: Stopped + ModuleVersion: '1.1' + ModuleName: PSDesiredStateConfiguration + Path: C:\WINDOWS\System32\spoolsv.exe + Dependencies: + - RPCSS + - http +``` + +## Restore the original service configuration + +If you want to restore the service to its original running state, you can reapply the first configuration. + +```powershell +dsc resource set --resource Microsoft.Windows/WindowsPowerShell --input $instance +``` + + +[01]: ../../../../../cli/resource/test.md +[02]: ../../../../../cli/resource/set.md \ No newline at end of file diff --git a/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md b/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md index e69de29bb..724e6a92a 100644 --- a/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md +++ b/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md @@ -0,0 +1,133 @@ +--- +description: Microsoft.Windows/WindowsPowerShell resource adapter reference documentation +ms.date: 03/25/2025 +ms.topic: reference +title: Microsoft.Windows/WindowsPowerShell +--- + +# Microsoft.Windows/WindowsPowerShell + +## Synopsis + +Manage PowerShell DSC resources. This adapter enables you to use class-based, script-based, or binary PowerShell DSC resources available on the system. + +## Metadata + +```yaml +Version : 0.1.0 +Kind : resource +Tags : [Windows] +Author : Microsoft +``` + +## Instance definition syntax + +```yaml +resources: + - name: + type: Microsoft.Windows/WindowsPowerShell + properties: + resources: + - name: + type: / + properties: + # Instance properties + Ensure: Present + +# Or from v3.1.0-preview.2 onwards +resources: +- name: + type: / + properties: + # Instance properties + Ensure: Present +``` + +## Description + +The `Microsoft.Windows/WindowsPowerShell` resource adapter enables you to invoke PSDSC resources. The resource can: + +- Execute script-based DSC resources +- Run class-based DSC resource methods +- Execute binary DSC resources + +> [!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. +- The resource must run in a process context that has appropriate permissions for the DSC resource to be executed. +- The PowerShell modules exposing DSC resources should be installed in + `%PROGRAMFILES%\WindowsPowerShell\Modules` or + `%SystemRoot%\System32\WindowsPowerShell\v1.0\Modules` + +## Capabilities + +The resource adapter has the following capabilities: + +- `get` - You can use the resource to retrieve the actual state of a DSC resource instance. +- `set` - You can use the resource to enforce the desired state for a DSC resource instance. +- `test` - You can use the resource to determine whether a DSC resource instance is in the desired state. +- `export` - You can use the resource to discover and enumerate DSC resource instances currently installed and available on the system. +- `list` - Lists available PowerShell DSC resources on your system that can be used with `dsc.exe`. + +> [!NOTE] +> The `export` capability is only available with class-based DSC resources. +> Script-based and binary DSC resources do not support the export operation. + +## Examples + +1. [Manage a Windows Service][01] - Shows how to manage a Windows service + +## Properties + +Unlike standard resources, the `Microsoft.Windows/WindowsPowerShell` resource adapter doesn't have directly exposed properties +in its schema because it acts as a bridge to PowerShell DSC resource. Instead, the adapter: + +1. Dynamically discovers the property schema for each PowerShell DSC resource +2. Stores the schema properties in a cache file for improved performance in subsequent operations +3. Passes properties to the underlying PowerShell DSC resource + +The adapter maintains a cache of resource schemas at: + +- Windows: `%LOCALAPPDATA%\dsc\WindowsPSAdapterCache.json` + +To list the schema properties for a PowerShell DSC resource, you can run the following command: + +```powershell +dsc resource list --adapter Microsoft.Windows/WindowsPowerShell / | + ConvertFrom-Json | + Select-Object properties +``` + +You can also retrieve more information by directly reading it from the cache file: + +```powershell +$cache = Get-Content -Path "$env:LOCALAPPDATA\dsc\WindowsPSAdapterCache.json" | + ConvertFrom-Json + +($cache.ResourceCache | Where-Object -Property type -EQ '/').DscResourceInfo.Properties +``` + +## 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. + +### Exit code 1 + +Indicates the resource operation failed because the underlying DSC resource method or Invoke-DscResource call did not succeed. +When the resource returns this exit code, it also emits an error message with details about the failure. + + +[01]: ./examples/manage-a-windows-service.md \ No newline at end of file From 0861dea3b85fa26617b335910a15e8d1b937a5b4 Mon Sep 17 00:00:00 2001 From: "G.Reijn" Date: Thu, 29 May 2025 13:09:42 +0200 Subject: [PATCH 03/11] Remove test file --- test.yaml | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 test.yaml diff --git a/test.yaml b/test.yaml deleted file mode 100644 index b1dc4dd77..000000000 --- a/test.yaml +++ /dev/null @@ -1,8 +0,0 @@ -$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json -resources: -- name: Class-resource Info - type: PSClassResource/PSClassResource -# $schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json -# resources: -# - name: Class-resource Info -# type: TestClassResource/TestClassResource \ No newline at end of file From 14358507b094a077a329f7f84102a39789f91043 Mon Sep 17 00:00:00 2001 From: "G.Reijn" Date: Thu, 29 May 2025 15:43:54 +0200 Subject: [PATCH 04/11] Added wrong adapter --- .../psDscAdapter/psDscAdapter.psm1 | 14 +++++++++++++- .../psDscAdapter/win_psDscAdapter.psm1 | 18 +++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/powershell-adapter/psDscAdapter/psDscAdapter.psm1 b/powershell-adapter/psDscAdapter/psDscAdapter.psm1 index 95576b1a4..ffee99d94 100644 --- a/powershell-adapter/psDscAdapter/psDscAdapter.psm1 +++ b/powershell-adapter/psDscAdapter/psDscAdapter.psm1 @@ -464,7 +464,19 @@ function Invoke-DscOperation { $addToActualState.properties = [psobject]@{'InDesiredState' = $Result } } 'Export' { - $method = ValidateMethod -operation $Operation -class $dscResourceInstance + $t = $dscResourceInstance.GetType() + $methods = $t.GetMethods() | Where-Object { $_.Name -eq 'Export' } + $method = foreach ($mt in $methods) { + if ($mt.GetParameters().Count -eq 0) { + $mt + break + } + } + + if ($null -eq $method) { + "Export method not implemented by resource '$($DesiredState.Type)'" | Write-DscTrace -Operation Error + exit 1 + } $resultArray = @() $raw_obj_array = $method.Invoke($null, $null) foreach ($raw_obj in $raw_obj_array) { diff --git a/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 b/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 index 8904b8dea..6bd1b32dd 100644 --- a/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 +++ b/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 @@ -438,9 +438,21 @@ function Invoke-DscOperation { $addToActualState.properties = [psobject]@{'InDesiredState' = $Result } } 'Export' { - $t = $dscResourceInstance.GetType() - $method = $t.GetMethod('Export') - $resultArray = $method.Invoke($null, $null) + $method = ValidateMethod -operation $Operation -class $dscResourceInstance + $resultArray = @() + $raw_obj_array = $method.Invoke($null, $null) + foreach ($raw_obj in $raw_obj_array) { + $Result_obj = @{} + $ValidProperties | ForEach-Object { + if ($raw_obj.$_ -is [System.Enum]) { + $Result_obj[$_] = $raw_obj.$_.ToString() + } + else { + $Result_obj[$_] = $raw_obj.$_ + } + } + $resultArray += $Result_obj + } $addToActualState = $resultArray } } From 390b431a81ea47a9863293526e7ee08daddbcc09 Mon Sep 17 00:00:00 2001 From: "G.Reijn" Date: Thu, 29 May 2025 12:04:19 +0200 Subject: [PATCH 05/11] Implement export in WinPS adapter --- .github/workflows/rust.yml | 2 +- .../Tests/win_powershellgroup.tests.ps1 | 24 +++ .../psDscAdapter/psDscAdapter.psm1 | 14 +- .../psDscAdapter/win_psDscAdapter.psm1 | 27 +++ .../windowspowershell.dsc.resource.json | 158 ++++++++++-------- test.yaml | 8 + 6 files changed, 147 insertions(+), 86 deletions(-) create mode 100644 test.yaml diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 620fdcde6..aca2363bb 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,7 +2,7 @@ name: Rust on: push: - branches: [ "main" ] + branches: [ "*" ] pull_request: branches: [ "main" ] paths-ignore: diff --git a/powershell-adapter/Tests/win_powershellgroup.tests.ps1 b/powershell-adapter/Tests/win_powershellgroup.tests.ps1 index ec305840c..e2258888a 100644 --- a/powershell-adapter/Tests/win_powershellgroup.tests.ps1 +++ b/powershell-adapter/Tests/win_powershellgroup.tests.ps1 @@ -322,6 +322,22 @@ class PSClassResource { [void] Set() { } + + static [PSClassResource[]] Export() + { + $resultList = [System.Collections.Generic.List[PSClassResource]]::new() + $resultCount = 5 + if ($env:PSClassResourceResultCount) { + $resultCount = $env:PSClassResourceResultCount + } + 1..$resultCount | %{ + $obj = New-Object PSClassResource + $obj.Name = "Object$_" + $resultList.Add($obj) + } + + return $resultList.ToArray() + } } '@ @@ -350,4 +366,12 @@ class PSClassResource { $LASTEXITCODE | Should -Be 0 $out.afterstate.InDesiredState | Should -Be $true } + + It 'Export works with class-based PS DSC resources' -Skip:(!$IsWindows) { + + $out = dsc resource export -r PSClassResource/PSClassResource | ConvertFrom-Json + $LASTEXITCODE | Should -Be 0 + $out | Should -Not -BeNullOrEmpty + $out.resources.count | Should -Be 5 + } } \ No newline at end of file diff --git a/powershell-adapter/psDscAdapter/psDscAdapter.psm1 b/powershell-adapter/psDscAdapter/psDscAdapter.psm1 index ffee99d94..95576b1a4 100644 --- a/powershell-adapter/psDscAdapter/psDscAdapter.psm1 +++ b/powershell-adapter/psDscAdapter/psDscAdapter.psm1 @@ -464,19 +464,7 @@ function Invoke-DscOperation { $addToActualState.properties = [psobject]@{'InDesiredState' = $Result } } 'Export' { - $t = $dscResourceInstance.GetType() - $methods = $t.GetMethods() | Where-Object { $_.Name -eq 'Export' } - $method = foreach ($mt in $methods) { - if ($mt.GetParameters().Count -eq 0) { - $mt - break - } - } - - if ($null -eq $method) { - "Export method not implemented by resource '$($DesiredState.Type)'" | Write-DscTrace -Operation Error - exit 1 - } + $method = ValidateMethod -operation $Operation -class $dscResourceInstance $resultArray = @() $raw_obj_array = $method.Invoke($null, $null) foreach ($raw_obj in $raw_obj_array) { diff --git a/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 b/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 index a6cd6e439..8904b8dea 100644 --- a/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 +++ b/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 @@ -532,6 +532,33 @@ function GetTypeInstanceFromModule { return $instance } +# ValidateMethod checks if the specified method exists in the class +function ValidateMethod { + param ( + [Parameter(Mandatory = $true)] + [ValidateSet('Export', 'WhatIf')] + [string] $operation, + [Parameter(Mandatory = $true)] + [object] $class + ) + + $t = $class.GetType() + $methods = $t.GetMethods() | Where-Object -Property Name -EQ $operation + $method = foreach ($mt in $methods) { + if ($mt.GetParameters().Count -eq 0) { + $mt + break + } + } + + if ($null -eq $method) { + "Method '$operation' not implemented by resource '$($t.Name)'" | Write-DscTrace -Operation Error + exit 1 + } + + return $method +} + # cached resource class dscResourceCacheEntry { [string] $Type diff --git a/powershell-adapter/windowspowershell.dsc.resource.json b/powershell-adapter/windowspowershell.dsc.resource.json index ba6aabfb0..9121be753 100644 --- a/powershell-adapter/windowspowershell.dsc.resource.json +++ b/powershell-adapter/windowspowershell.dsc.resource.json @@ -1,41 +1,14 @@ { - "$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json", - "type": "Microsoft.Windows/WindowsPowerShell", - "version": "0.1.0", - "kind": "adapter", - "description": "Resource adapter to classic DSC Powershell resources in Windows PowerShell.", - "tags": [ - "PowerShell" - ], - "adapter": { - "list": { - "executable": "powershell", - "args": [ - "-NoLogo", - "-NonInteractive", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-Command", - "./psDscAdapter/powershell.resource.ps1 List" - ] - }, - "config": "full" - }, - "get": { - "executable": "powershell", - "args": [ - "-NoLogo", - "-NonInteractive", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-Command", - "$Input | ./psDscAdapter/powershell.resource.ps1 Get" - ], - "input": "stdin" - }, - "set": { + "$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json", + "type": "Microsoft.Windows/WindowsPowerShell", + "version": "0.1.0", + "kind": "adapter", + "description": "Resource adapter to classic DSC Powershell resources in Windows PowerShell.", + "tags": [ + "PowerShell" + ], + "adapter": { + "list": { "executable": "powershell", "args": [ "-NoLogo", @@ -44,39 +17,80 @@ "-ExecutionPolicy", "Bypass", "-Command", - "$Input | ./psDscAdapter/powershell.resource.ps1 Set" - ], - "input": "stdin", - "preTest": true - }, - "test": { - "executable": "powershell", - "args": [ - "-NoLogo", - "-NonInteractive", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-Command", - "$Input | ./psDscAdapter/powershell.resource.ps1 Test" - ], - "input": "stdin", - "return": "state" - }, - "validate": { - "executable": "powershell", - "args": [ - "-NoLogo", - "-NonInteractive", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-Command", - "$Input | ./psDscAdapter/powershell.resource.ps1 Validate" - ] - }, - "exitCodes": { - "0": "Success", - "1": "Error" - } + "./psDscAdapter/powershell.resource.ps1 List" + ] + }, + "config": "full" + }, + "get": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Get" + ], + "input": "stdin" + }, + "set": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Set" + ], + "input": "stdin", + "preTest": true + }, + "test": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Test" + ], + "input": "stdin", + "return": "state" + }, + "export": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Export" + ], + "input": "stdin", + "return": "state" + }, + "validate": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Validate" + ] + }, + "exitCodes": { + "0": "Success", + "1": "Error" } +} \ No newline at end of file diff --git a/test.yaml b/test.yaml new file mode 100644 index 000000000..b1dc4dd77 --- /dev/null +++ b/test.yaml @@ -0,0 +1,8 @@ +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: +- name: Class-resource Info + type: PSClassResource/PSClassResource +# $schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +# resources: +# - name: Class-resource Info +# type: TestClassResource/TestClassResource \ No newline at end of file From c229ff76a83d12afa2c4ad09b566d5b0743d7f33 Mon Sep 17 00:00:00 2001 From: "G.Reijn" Date: Thu, 29 May 2025 13:08:57 +0200 Subject: [PATCH 06/11] Add documentation --- .github/workflows/rust.yml | 2 +- .../examples/manage-a-windows-service.md | 228 ++++++++++++++++++ .../Windows/WindowsPowerShell/index.md | 133 ++++++++++ 3 files changed, 362 insertions(+), 1 deletion(-) create mode 100644 docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index aca2363bb..620fdcde6 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,7 +2,7 @@ name: Rust on: push: - branches: [ "*" ] + branches: [ "main" ] pull_request: branches: [ "main" ] paths-ignore: diff --git a/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md b/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md new file mode 100644 index 000000000..fdefffd11 --- /dev/null +++ b/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md @@ -0,0 +1,228 @@ +--- +description: > + Examples showing how you can invoke the Microsoft.Windows/WindowsPowerShell with DSC to manage + a Windows service using the PSDesiredStateConfiguration module. + +ms.date: 03/25/2025 +ms.topic: reference +title: Manage a Windows service +--- + +This example shows how you can use the `Microsoft.Windows/WindowsPowerShell` resource with the `PSDesiredStateConfiguration` module 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.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. + +```powershell +$instance = @{ + Name = 'Spooler' + StartupType = 'Automatic' +} | ConvertTo-Json + +dsc resource test --resource PSDesiredStateConfiguration/Service --input $instance +``` + +When the service isn't running or has a different startup type, DSC returns the following result: + +```yaml +desiredState: + Name: Spooler + StartupType: Manual +actualState: + InDesiredState: false +inDesiredState: false +differingProperties: +- StartupType +``` + +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. + +## Ensure a service is running with automatic startup + +To set the system to the desired state and configure the service, use the [dsc resource set][02] command. + +```powershell +dsc resource set --resource PSDesiredStateConfiguration/Service --input $instance +``` + +When the resource configures the service, DSC returns the following result: + +```yaml +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 +``` + +You can test the instance again to confirm that the service is configured correctly: + +```powershell +dsc resource test --resource PSDesiredStateConfiguration/Service --input $instance +``` + +```yaml +desiredState: + Name: Spooler / + StartupType: Manual +actualState: + InDesiredState: true +inDesiredState: true +differingProperties: [] +``` + +## Stop a service + +The following snippet shows how you can configure the `Spooler` service to be stopped with manual startup. + +```powershell +$stopInstance = @{ + Name = 'Spooler' + State = 'Stopped' + StartupType = 'Manual' +} | ConvertTo-Json + +dsc resource set --resource PSDesiredStateConfiguration/Service --input $stopInstance +``` + +When the resource stops the service, DSC returns the following result: + +```yaml +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: Manual + State: Stopped + ModuleVersion: '1.1' + ModuleName: PSDesiredStateConfiguration + Path: C:\WINDOWS\System32\spoolsv.exe + Dependencies: + - RPCSS + - http +changedProperties: +- State +``` + +## Verify the current state of a service + +To check the current state of the service, use the `dsc resource get` command. + +```powershell +dsc resource get --resource PSDesiredStateConfiguration/Service --input $instance +``` + +```yaml +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: Stopped + ModuleVersion: '1.1' + ModuleName: PSDesiredStateConfiguration + Path: C:\WINDOWS\System32\spoolsv.exe + Dependencies: + - RPCSS + - http +``` + +## Restore the original service configuration + +If you want to restore the service to its original running state, you can reapply the first configuration. + +```powershell +dsc resource set --resource Microsoft.Windows/WindowsPowerShell --input $instance +``` + + +[01]: ../../../../../cli/resource/test.md +[02]: ../../../../../cli/resource/set.md \ No newline at end of file diff --git a/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md b/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md index e69de29bb..724e6a92a 100644 --- a/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md +++ b/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md @@ -0,0 +1,133 @@ +--- +description: Microsoft.Windows/WindowsPowerShell resource adapter reference documentation +ms.date: 03/25/2025 +ms.topic: reference +title: Microsoft.Windows/WindowsPowerShell +--- + +# Microsoft.Windows/WindowsPowerShell + +## Synopsis + +Manage PowerShell DSC resources. This adapter enables you to use class-based, script-based, or binary PowerShell DSC resources available on the system. + +## Metadata + +```yaml +Version : 0.1.0 +Kind : resource +Tags : [Windows] +Author : Microsoft +``` + +## Instance definition syntax + +```yaml +resources: + - name: + type: Microsoft.Windows/WindowsPowerShell + properties: + resources: + - name: + type: / + properties: + # Instance properties + Ensure: Present + +# Or from v3.1.0-preview.2 onwards +resources: +- name: + type: / + properties: + # Instance properties + Ensure: Present +``` + +## Description + +The `Microsoft.Windows/WindowsPowerShell` resource adapter enables you to invoke PSDSC resources. The resource can: + +- Execute script-based DSC resources +- Run class-based DSC resource methods +- Execute binary DSC resources + +> [!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. +- The resource must run in a process context that has appropriate permissions for the DSC resource to be executed. +- The PowerShell modules exposing DSC resources should be installed in + `%PROGRAMFILES%\WindowsPowerShell\Modules` or + `%SystemRoot%\System32\WindowsPowerShell\v1.0\Modules` + +## Capabilities + +The resource adapter has the following capabilities: + +- `get` - You can use the resource to retrieve the actual state of a DSC resource instance. +- `set` - You can use the resource to enforce the desired state for a DSC resource instance. +- `test` - You can use the resource to determine whether a DSC resource instance is in the desired state. +- `export` - You can use the resource to discover and enumerate DSC resource instances currently installed and available on the system. +- `list` - Lists available PowerShell DSC resources on your system that can be used with `dsc.exe`. + +> [!NOTE] +> The `export` capability is only available with class-based DSC resources. +> Script-based and binary DSC resources do not support the export operation. + +## Examples + +1. [Manage a Windows Service][01] - Shows how to manage a Windows service + +## Properties + +Unlike standard resources, the `Microsoft.Windows/WindowsPowerShell` resource adapter doesn't have directly exposed properties +in its schema because it acts as a bridge to PowerShell DSC resource. Instead, the adapter: + +1. Dynamically discovers the property schema for each PowerShell DSC resource +2. Stores the schema properties in a cache file for improved performance in subsequent operations +3. Passes properties to the underlying PowerShell DSC resource + +The adapter maintains a cache of resource schemas at: + +- Windows: `%LOCALAPPDATA%\dsc\WindowsPSAdapterCache.json` + +To list the schema properties for a PowerShell DSC resource, you can run the following command: + +```powershell +dsc resource list --adapter Microsoft.Windows/WindowsPowerShell / | + ConvertFrom-Json | + Select-Object properties +``` + +You can also retrieve more information by directly reading it from the cache file: + +```powershell +$cache = Get-Content -Path "$env:LOCALAPPDATA\dsc\WindowsPSAdapterCache.json" | + ConvertFrom-Json + +($cache.ResourceCache | Where-Object -Property type -EQ '/').DscResourceInfo.Properties +``` + +## 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. + +### Exit code 1 + +Indicates the resource operation failed because the underlying DSC resource method or Invoke-DscResource call did not succeed. +When the resource returns this exit code, it also emits an error message with details about the failure. + + +[01]: ./examples/manage-a-windows-service.md \ No newline at end of file From bb4f6c2ebdc70185e044eed00a35fd05108b6534 Mon Sep 17 00:00:00 2001 From: "G.Reijn" Date: Thu, 29 May 2025 13:09:42 +0200 Subject: [PATCH 07/11] Remove test file --- test.yaml | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 test.yaml diff --git a/test.yaml b/test.yaml deleted file mode 100644 index b1dc4dd77..000000000 --- a/test.yaml +++ /dev/null @@ -1,8 +0,0 @@ -$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json -resources: -- name: Class-resource Info - type: PSClassResource/PSClassResource -# $schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json -# resources: -# - name: Class-resource Info -# type: TestClassResource/TestClassResource \ No newline at end of file From 353b76d7db72c9e401bacd9f5220330260ec0de2 Mon Sep 17 00:00:00 2001 From: "G.Reijn" Date: Thu, 29 May 2025 15:43:54 +0200 Subject: [PATCH 08/11] Added wrong adapter --- .../psDscAdapter/psDscAdapter.psm1 | 14 +++++++++++++- .../psDscAdapter/win_psDscAdapter.psm1 | 18 +++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/powershell-adapter/psDscAdapter/psDscAdapter.psm1 b/powershell-adapter/psDscAdapter/psDscAdapter.psm1 index 95576b1a4..ffee99d94 100644 --- a/powershell-adapter/psDscAdapter/psDscAdapter.psm1 +++ b/powershell-adapter/psDscAdapter/psDscAdapter.psm1 @@ -464,7 +464,19 @@ function Invoke-DscOperation { $addToActualState.properties = [psobject]@{'InDesiredState' = $Result } } 'Export' { - $method = ValidateMethod -operation $Operation -class $dscResourceInstance + $t = $dscResourceInstance.GetType() + $methods = $t.GetMethods() | Where-Object { $_.Name -eq 'Export' } + $method = foreach ($mt in $methods) { + if ($mt.GetParameters().Count -eq 0) { + $mt + break + } + } + + if ($null -eq $method) { + "Export method not implemented by resource '$($DesiredState.Type)'" | Write-DscTrace -Operation Error + exit 1 + } $resultArray = @() $raw_obj_array = $method.Invoke($null, $null) foreach ($raw_obj in $raw_obj_array) { diff --git a/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 b/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 index 8904b8dea..6bd1b32dd 100644 --- a/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 +++ b/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 @@ -438,9 +438,21 @@ function Invoke-DscOperation { $addToActualState.properties = [psobject]@{'InDesiredState' = $Result } } 'Export' { - $t = $dscResourceInstance.GetType() - $method = $t.GetMethod('Export') - $resultArray = $method.Invoke($null, $null) + $method = ValidateMethod -operation $Operation -class $dscResourceInstance + $resultArray = @() + $raw_obj_array = $method.Invoke($null, $null) + foreach ($raw_obj in $raw_obj_array) { + $Result_obj = @{} + $ValidProperties | ForEach-Object { + if ($raw_obj.$_ -is [System.Enum]) { + $Result_obj[$_] = $raw_obj.$_.ToString() + } + else { + $Result_obj[$_] = $raw_obj.$_ + } + } + $resultArray += $Result_obj + } $addToActualState = $resultArray } } From a320223be5a09b4c7df691f2012f6a5d8f0ea135 Mon Sep 17 00:00:00 2001 From: "G.Reijn" Date: Tue, 3 Jun 2025 05:46:06 +0200 Subject: [PATCH 09/11] Removed documentation --- .../examples/manage-a-windows-service.md | 228 ------------------ .../Windows/WindowsPowerShell/index.md | 133 ---------- 2 files changed, 361 deletions(-) delete mode 100644 docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md diff --git a/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md b/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md deleted file mode 100644 index fdefffd11..000000000 --- a/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md +++ /dev/null @@ -1,228 +0,0 @@ ---- -description: > - Examples showing how you can invoke the Microsoft.Windows/WindowsPowerShell with DSC to manage - a Windows service using the PSDesiredStateConfiguration module. - -ms.date: 03/25/2025 -ms.topic: reference -title: Manage a Windows service ---- - -This example shows how you can use the `Microsoft.Windows/WindowsPowerShell` resource with the `PSDesiredStateConfiguration` module 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.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. - -```powershell -$instance = @{ - Name = 'Spooler' - StartupType = 'Automatic' -} | ConvertTo-Json - -dsc resource test --resource PSDesiredStateConfiguration/Service --input $instance -``` - -When the service isn't running or has a different startup type, DSC returns the following result: - -```yaml -desiredState: - Name: Spooler - StartupType: Manual -actualState: - InDesiredState: false -inDesiredState: false -differingProperties: -- StartupType -``` - -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. - -## Ensure a service is running with automatic startup - -To set the system to the desired state and configure the service, use the [dsc resource set][02] command. - -```powershell -dsc resource set --resource PSDesiredStateConfiguration/Service --input $instance -``` - -When the resource configures the service, DSC returns the following result: - -```yaml -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 -``` - -You can test the instance again to confirm that the service is configured correctly: - -```powershell -dsc resource test --resource PSDesiredStateConfiguration/Service --input $instance -``` - -```yaml -desiredState: - Name: Spooler / - StartupType: Manual -actualState: - InDesiredState: true -inDesiredState: true -differingProperties: [] -``` - -## Stop a service - -The following snippet shows how you can configure the `Spooler` service to be stopped with manual startup. - -```powershell -$stopInstance = @{ - Name = 'Spooler' - State = 'Stopped' - StartupType = 'Manual' -} | ConvertTo-Json - -dsc resource set --resource PSDesiredStateConfiguration/Service --input $stopInstance -``` - -When the resource stops the service, DSC returns the following result: - -```yaml -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: Manual - State: Stopped - ModuleVersion: '1.1' - ModuleName: PSDesiredStateConfiguration - Path: C:\WINDOWS\System32\spoolsv.exe - Dependencies: - - RPCSS - - http -changedProperties: -- State -``` - -## Verify the current state of a service - -To check the current state of the service, use the `dsc resource get` command. - -```powershell -dsc resource get --resource PSDesiredStateConfiguration/Service --input $instance -``` - -```yaml -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: Stopped - ModuleVersion: '1.1' - ModuleName: PSDesiredStateConfiguration - Path: C:\WINDOWS\System32\spoolsv.exe - Dependencies: - - RPCSS - - http -``` - -## Restore the original service configuration - -If you want to restore the service to its original running state, you can reapply the first configuration. - -```powershell -dsc resource set --resource Microsoft.Windows/WindowsPowerShell --input $instance -``` - - -[01]: ../../../../../cli/resource/test.md -[02]: ../../../../../cli/resource/set.md \ No newline at end of file diff --git a/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md b/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md index 724e6a92a..e69de29bb 100644 --- a/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md +++ b/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md @@ -1,133 +0,0 @@ ---- -description: Microsoft.Windows/WindowsPowerShell resource adapter reference documentation -ms.date: 03/25/2025 -ms.topic: reference -title: Microsoft.Windows/WindowsPowerShell ---- - -# Microsoft.Windows/WindowsPowerShell - -## Synopsis - -Manage PowerShell DSC resources. This adapter enables you to use class-based, script-based, or binary PowerShell DSC resources available on the system. - -## Metadata - -```yaml -Version : 0.1.0 -Kind : resource -Tags : [Windows] -Author : Microsoft -``` - -## Instance definition syntax - -```yaml -resources: - - name: - type: Microsoft.Windows/WindowsPowerShell - properties: - resources: - - name: - type: / - properties: - # Instance properties - Ensure: Present - -# Or from v3.1.0-preview.2 onwards -resources: -- name: - type: / - properties: - # Instance properties - Ensure: Present -``` - -## Description - -The `Microsoft.Windows/WindowsPowerShell` resource adapter enables you to invoke PSDSC resources. The resource can: - -- Execute script-based DSC resources -- Run class-based DSC resource methods -- Execute binary DSC resources - -> [!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. -- The resource must run in a process context that has appropriate permissions for the DSC resource to be executed. -- The PowerShell modules exposing DSC resources should be installed in - `%PROGRAMFILES%\WindowsPowerShell\Modules` or - `%SystemRoot%\System32\WindowsPowerShell\v1.0\Modules` - -## Capabilities - -The resource adapter has the following capabilities: - -- `get` - You can use the resource to retrieve the actual state of a DSC resource instance. -- `set` - You can use the resource to enforce the desired state for a DSC resource instance. -- `test` - You can use the resource to determine whether a DSC resource instance is in the desired state. -- `export` - You can use the resource to discover and enumerate DSC resource instances currently installed and available on the system. -- `list` - Lists available PowerShell DSC resources on your system that can be used with `dsc.exe`. - -> [!NOTE] -> The `export` capability is only available with class-based DSC resources. -> Script-based and binary DSC resources do not support the export operation. - -## Examples - -1. [Manage a Windows Service][01] - Shows how to manage a Windows service - -## Properties - -Unlike standard resources, the `Microsoft.Windows/WindowsPowerShell` resource adapter doesn't have directly exposed properties -in its schema because it acts as a bridge to PowerShell DSC resource. Instead, the adapter: - -1. Dynamically discovers the property schema for each PowerShell DSC resource -2. Stores the schema properties in a cache file for improved performance in subsequent operations -3. Passes properties to the underlying PowerShell DSC resource - -The adapter maintains a cache of resource schemas at: - -- Windows: `%LOCALAPPDATA%\dsc\WindowsPSAdapterCache.json` - -To list the schema properties for a PowerShell DSC resource, you can run the following command: - -```powershell -dsc resource list --adapter Microsoft.Windows/WindowsPowerShell / | - ConvertFrom-Json | - Select-Object properties -``` - -You can also retrieve more information by directly reading it from the cache file: - -```powershell -$cache = Get-Content -Path "$env:LOCALAPPDATA\dsc\WindowsPSAdapterCache.json" | - ConvertFrom-Json - -($cache.ResourceCache | Where-Object -Property type -EQ '/').DscResourceInfo.Properties -``` - -## 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. - -### Exit code 1 - -Indicates the resource operation failed because the underlying DSC resource method or Invoke-DscResource call did not succeed. -When the resource returns this exit code, it also emits an error message with details about the failure. - - -[01]: ./examples/manage-a-windows-service.md \ No newline at end of file From 08cb23b2a68e085e6593d867f77caecb7551c53a Mon Sep 17 00:00:00 2001 From: "G.Reijn" Date: Tue, 3 Jun 2025 05:47:02 +0200 Subject: [PATCH 10/11] Removed documentation --- .../examples/manage-a-windows-service.md | 228 ------------------ .../Windows/WindowsPowerShell/index.md | 133 ---------- 2 files changed, 361 deletions(-) delete mode 100644 docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md diff --git a/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md b/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md deleted file mode 100644 index fdefffd11..000000000 --- a/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/examples/manage-a-windows-service.md +++ /dev/null @@ -1,228 +0,0 @@ ---- -description: > - Examples showing how you can invoke the Microsoft.Windows/WindowsPowerShell with DSC to manage - a Windows service using the PSDesiredStateConfiguration module. - -ms.date: 03/25/2025 -ms.topic: reference -title: Manage a Windows service ---- - -This example shows how you can use the `Microsoft.Windows/WindowsPowerShell` resource with the `PSDesiredStateConfiguration` module 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.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. - -```powershell -$instance = @{ - Name = 'Spooler' - StartupType = 'Automatic' -} | ConvertTo-Json - -dsc resource test --resource PSDesiredStateConfiguration/Service --input $instance -``` - -When the service isn't running or has a different startup type, DSC returns the following result: - -```yaml -desiredState: - Name: Spooler - StartupType: Manual -actualState: - InDesiredState: false -inDesiredState: false -differingProperties: -- StartupType -``` - -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. - -## Ensure a service is running with automatic startup - -To set the system to the desired state and configure the service, use the [dsc resource set][02] command. - -```powershell -dsc resource set --resource PSDesiredStateConfiguration/Service --input $instance -``` - -When the resource configures the service, DSC returns the following result: - -```yaml -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 -``` - -You can test the instance again to confirm that the service is configured correctly: - -```powershell -dsc resource test --resource PSDesiredStateConfiguration/Service --input $instance -``` - -```yaml -desiredState: - Name: Spooler / - StartupType: Manual -actualState: - InDesiredState: true -inDesiredState: true -differingProperties: [] -``` - -## Stop a service - -The following snippet shows how you can configure the `Spooler` service to be stopped with manual startup. - -```powershell -$stopInstance = @{ - Name = 'Spooler' - State = 'Stopped' - StartupType = 'Manual' -} | ConvertTo-Json - -dsc resource set --resource PSDesiredStateConfiguration/Service --input $stopInstance -``` - -When the resource stops the service, DSC returns the following result: - -```yaml -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: Manual - State: Stopped - ModuleVersion: '1.1' - ModuleName: PSDesiredStateConfiguration - Path: C:\WINDOWS\System32\spoolsv.exe - Dependencies: - - RPCSS - - http -changedProperties: -- State -``` - -## Verify the current state of a service - -To check the current state of the service, use the `dsc resource get` command. - -```powershell -dsc resource get --resource PSDesiredStateConfiguration/Service --input $instance -``` - -```yaml -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: Stopped - ModuleVersion: '1.1' - ModuleName: PSDesiredStateConfiguration - Path: C:\WINDOWS\System32\spoolsv.exe - Dependencies: - - RPCSS - - http -``` - -## Restore the original service configuration - -If you want to restore the service to its original running state, you can reapply the first configuration. - -```powershell -dsc resource set --resource Microsoft.Windows/WindowsPowerShell --input $instance -``` - - -[01]: ../../../../../cli/resource/test.md -[02]: ../../../../../cli/resource/set.md \ No newline at end of file diff --git a/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md b/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md index 724e6a92a..e69de29bb 100644 --- a/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md +++ b/docs/reference/resources/Microsoft/Windows/WindowsPowerShell/index.md @@ -1,133 +0,0 @@ ---- -description: Microsoft.Windows/WindowsPowerShell resource adapter reference documentation -ms.date: 03/25/2025 -ms.topic: reference -title: Microsoft.Windows/WindowsPowerShell ---- - -# Microsoft.Windows/WindowsPowerShell - -## Synopsis - -Manage PowerShell DSC resources. This adapter enables you to use class-based, script-based, or binary PowerShell DSC resources available on the system. - -## Metadata - -```yaml -Version : 0.1.0 -Kind : resource -Tags : [Windows] -Author : Microsoft -``` - -## Instance definition syntax - -```yaml -resources: - - name: - type: Microsoft.Windows/WindowsPowerShell - properties: - resources: - - name: - type: / - properties: - # Instance properties - Ensure: Present - -# Or from v3.1.0-preview.2 onwards -resources: -- name: - type: / - properties: - # Instance properties - Ensure: Present -``` - -## Description - -The `Microsoft.Windows/WindowsPowerShell` resource adapter enables you to invoke PSDSC resources. The resource can: - -- Execute script-based DSC resources -- Run class-based DSC resource methods -- Execute binary DSC resources - -> [!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. -- The resource must run in a process context that has appropriate permissions for the DSC resource to be executed. -- The PowerShell modules exposing DSC resources should be installed in - `%PROGRAMFILES%\WindowsPowerShell\Modules` or - `%SystemRoot%\System32\WindowsPowerShell\v1.0\Modules` - -## Capabilities - -The resource adapter has the following capabilities: - -- `get` - You can use the resource to retrieve the actual state of a DSC resource instance. -- `set` - You can use the resource to enforce the desired state for a DSC resource instance. -- `test` - You can use the resource to determine whether a DSC resource instance is in the desired state. -- `export` - You can use the resource to discover and enumerate DSC resource instances currently installed and available on the system. -- `list` - Lists available PowerShell DSC resources on your system that can be used with `dsc.exe`. - -> [!NOTE] -> The `export` capability is only available with class-based DSC resources. -> Script-based and binary DSC resources do not support the export operation. - -## Examples - -1. [Manage a Windows Service][01] - Shows how to manage a Windows service - -## Properties - -Unlike standard resources, the `Microsoft.Windows/WindowsPowerShell` resource adapter doesn't have directly exposed properties -in its schema because it acts as a bridge to PowerShell DSC resource. Instead, the adapter: - -1. Dynamically discovers the property schema for each PowerShell DSC resource -2. Stores the schema properties in a cache file for improved performance in subsequent operations -3. Passes properties to the underlying PowerShell DSC resource - -The adapter maintains a cache of resource schemas at: - -- Windows: `%LOCALAPPDATA%\dsc\WindowsPSAdapterCache.json` - -To list the schema properties for a PowerShell DSC resource, you can run the following command: - -```powershell -dsc resource list --adapter Microsoft.Windows/WindowsPowerShell / | - ConvertFrom-Json | - Select-Object properties -``` - -You can also retrieve more information by directly reading it from the cache file: - -```powershell -$cache = Get-Content -Path "$env:LOCALAPPDATA\dsc\WindowsPSAdapterCache.json" | - ConvertFrom-Json - -($cache.ResourceCache | Where-Object -Property type -EQ '/').DscResourceInfo.Properties -``` - -## 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. - -### Exit code 1 - -Indicates the resource operation failed because the underlying DSC resource method or Invoke-DscResource call did not succeed. -When the resource returns this exit code, it also emits an error message with details about the failure. - - -[01]: ./examples/manage-a-windows-service.md \ No newline at end of file From 583f69176c795309fb9fa6c8223073183373b099 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Tue, 3 Jun 2025 13:10:23 -0700 Subject: [PATCH 11/11] Update powershell-adapter/windowspowershell.dsc.resource.json Co-authored-by: Mikey Lombardi (He/Him) --- powershell-adapter/windowspowershell.dsc.resource.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell-adapter/windowspowershell.dsc.resource.json b/powershell-adapter/windowspowershell.dsc.resource.json index 9121be753..297b44d05 100644 --- a/powershell-adapter/windowspowershell.dsc.resource.json +++ b/powershell-adapter/windowspowershell.dsc.resource.json @@ -93,4 +93,4 @@ "0": "Success", "1": "Error" } -} \ No newline at end of file +}