diff --git a/CHANGELOG.md b/CHANGELOG.md index bc3d3d3..be67af3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +* WindowsFeature + * Added Source parameter to support installation of windows feature which + need additional feature files. The specified path must be accessible by + the target computer. + ## 2.12.0.0 * Ports style fixes that were recently made in xPSDesiredStateConfiguration diff --git a/DscResources/MSFT_WindowsFeature/MSFT_WindowsFeature.psm1 b/DscResources/MSFT_WindowsFeature/MSFT_WindowsFeature.psm1 index fa75844..12488d2 100644 --- a/DscResources/MSFT_WindowsFeature/MSFT_WindowsFeature.psm1 +++ b/DscResources/MSFT_WindowsFeature/MSFT_WindowsFeature.psm1 @@ -6,7 +6,7 @@ $errorActionPreference = 'Stop' Set-StrictMode -Version 'Latest' Import-Module -Name (Join-Path -Path (Split-Path -Path $PSScriptRoot -Parent) ` - -ChildPath 'CommonResourceHelper.psm1') + -ChildPath 'CommonResourceHelper.psm1') # Localized messages for verbose and error messages in this resource $script:localizedData = Get-LocalizedData -ResourceName 'MSFT_WindowsFeature' @@ -34,16 +34,16 @@ function Get-TargetResource [OutputType([System.Collections.Hashtable])] param ( - [Parameter(Mandatory = $true)] - [ValidateNotNullOrEmpty()] - [System.String] - $Name, - - [Parameter()] - [ValidateNotNullOrEmpty()] - [System.Management.Automation.PSCredential] - [System.Management.Automation.Credential()] - $Credential + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [System.String] + $Name, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [System.Management.Automation.PSCredential] + [System.Management.Automation.Credential()] + $Credential ) Write-Verbose -Message ($script:localizedData.GetTargetResourceStartMessage -f $Name) @@ -56,8 +56,8 @@ function Get-TargetResource if ($isWinServer2008R2SP1 -and $PSBoundParameters.ContainsKey('Credential')) { $feature = Invoke-Command -ScriptBlock { Get-WindowsFeature -Name $Name } ` - -ComputerName . ` - -Credential $Credential ` + -ComputerName . ` + -Credential $Credential } else { @@ -82,7 +82,7 @@ function Get-TargetResource if ($PSBoundParameters.ContainsKey('Credential')) { - $getWindowsFeatureParameters['Credential'] = $Credential + $getWindowsFeatureParameters['Credential'] = $Credential } if ($isWinServer2008R2SP1 -and $PSBoundParameters.ContainsKey('Credential')) @@ -93,8 +93,8 @@ function Get-TargetResource attribute on this server. #> $subFeature = Invoke-Command -ScriptBlock { Get-WindowsFeature -Name $currentSubFeatureName } ` - -ComputerName . ` - -Credential $Credential ` + -ComputerName . ` + -Credential $Credential } else { @@ -124,9 +124,9 @@ function Get-TargetResource # Add all feature properties to the hash table return @{ - Name = $Name - DisplayName = $feature.DisplayName - Ensure = $ensureResult + Name = $Name + DisplayName = $feature.DisplayName + Ensure = $ensureResult IncludeAllSubFeature = $includeAllSubFeature } } @@ -144,6 +144,10 @@ function Get-TargetResource or uninstalled ('Absent'). By default this is set to Present. + .PARAMETER Source + Specifies a path to additional feature source files if necessary for the installation + of the stated roles or features. + .PARAMETER IncludeAllSubFeature Specifies whether or not all subfeatures should be installed or uninstalled with the specified role or feature. Default is false. @@ -164,30 +168,35 @@ function Set-TargetResource [CmdletBinding()] param ( - [Parameter(Mandatory = $true)] - [ValidateNotNullOrEmpty()] - [System.String] - $Name, - - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - - [Parameter()] - [System.Boolean] - $IncludeAllSubFeature = $false, - - [Parameter()] - [ValidateNotNullOrEmpty()] - [System.Management.Automation.PSCredential] - [System.Management.Automation.Credential()] - $Credential, - - [Parameter()] - [ValidateNotNullOrEmpty()] - [System.String] - $LogPath + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [System.String] + $Name, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [ValidateNotNullOrEmpty()] + [System.String] + $Source, + + [Parameter()] + [System.Boolean] + $IncludeAllSubFeature = $false, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [System.Management.Automation.PSCredential] + [System.Management.Automation.Credential()] + $Credential, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [System.String] + $LogPath ) Write-Verbose -Message ($script:localizedData.SetTargetResourceStartMessage -f $Name) @@ -199,17 +208,22 @@ function Set-TargetResource if ($Ensure -eq 'Present') { $addWindowsFeatureParameters = @{ - Name = $Name + Name = $Name IncludeAllSubFeature = $IncludeAllSubFeature } if ($PSBoundParameters.ContainsKey('LogPath')) { - $addWindowsFeatureParameters['LogPath'] = $LogPath + $addWindowsFeatureParameters['LogPath'] = $LogPath } Write-Verbose -Message ($script:localizedData.InstallFeature -f $Name) + if (($isWinServer2008R2SP1 -eq $false) -and $PSBoundParameters.ContainsKey('Source')) + { + $addWindowsFeatureParameters['Source'] = $Source + } + if ($isWinServer2008R2SP1 -and $PSBoundParameters.ContainsKey('Credential')) { <# @@ -218,14 +232,14 @@ function Set-TargetResource attribute on this server. #> $feature = Invoke-Command -ScriptBlock { Add-WindowsFeature @addWindowsFeatureParameters } ` - -ComputerName . ` - -Credential $Credential + -ComputerName . ` + -Credential $Credential } else { if ($PSBoundParameters.ContainsKey('Credential')) { - $addWindowsFeatureParameters['Credential'] = $Credential + $addWindowsFeatureParameters['Credential'] = $Credential } $feature = Add-WindowsFeature @addWindowsFeatureParameters @@ -256,7 +270,7 @@ function Set-TargetResource if ($PSBoundParameters.ContainsKey('LogPath')) { - $removeWindowsFeatureParameters['LogPath'] = $LogPath + $removeWindowsFeatureParameters['LogPath'] = $LogPath } Write-Verbose -Message ($script:localizedData.UninstallFeature -f $Name) @@ -269,14 +283,14 @@ function Set-TargetResource attribute on this server. #> $feature = Invoke-Command -ScriptBlock { Remove-WindowsFeature @removeWindowsFeatureParameters } ` - -ComputerName . ` - -Credential $Credential + -ComputerName . ` + -Credential $Credential } else { if ($PSBoundParameters.ContainsKey('Credential')) { - $addWindowsFeatureParameters['Credential'] = $Credential + $addWindowsFeatureParameters['Credential'] = $Credential } $feature = Remove-WindowsFeature @removeWindowsFeatureParameters @@ -314,6 +328,11 @@ function Set-TargetResource or uninstalled ('Absent'). By default this is set to Present. + .PARAMETER Source + Specifies a path to additional feature source files if necessary for the installation + of the stated roles or features. + Not used in Test-TargetResource. + .PARAMETER IncludeAllSubFeature Specifies whether or not the installation state of all subfeatures should be tested with the specified role or feature. Default is false. @@ -348,6 +367,11 @@ function Test-TargetResource [System.String] $Ensure = 'Present', + [Parameter()] + [ValidateNotNullOrEmpty()] + [System.String] + $Source, + [Parameter()] [System.Boolean] $IncludeAllSubFeature = $false, @@ -377,7 +401,7 @@ function Test-TargetResource if ($PSBoundParameters.ContainsKey('Credential')) { - $getWindowsFeatureParameters['Credential'] = $Credential + $getWindowsFeatureParameters['Credential'] = $Credential } Write-Verbose -Message ($script:localizedData.QueryFeature -f $Name) @@ -391,8 +415,8 @@ function Test-TargetResource attribute on this server. #> $feature = Invoke-Command -ScriptBlock { Get-WindowsFeature -Name $Name } ` - -ComputerName . ` - -Credential $Credential + -ComputerName . ` + -Credential $Credential } else { @@ -422,8 +446,8 @@ function Test-TargetResource attribute on this server. #> $subFeature = Invoke-Command -ScriptBlock { Get-WindowsFeature -Name $currentSubFeatureName } ` - -ComputerName . ` - -Credential $Credential + -ComputerName . ` + -Credential $Credential } else { @@ -514,7 +538,7 @@ function Import-ServerManager # Check if this operating system needs an update to the ServerManager cmdlets if ($operatingSystem.Version.StartsWith('6.1.') -and ` - $serverCoreOSCodes -contains $operatingSystem.OperatingSystemSKU) + $serverCoreOSCodes -contains $operatingSystem.OperatingSystemSKU) { Write-Verbose -Message $script:localizedData.EnableServerManagerPSHCmdletsFeature diff --git a/DscResources/MSFT_WindowsFeature/MSFT_WindowsFeature.schema.mof b/DscResources/MSFT_WindowsFeature/MSFT_WindowsFeature.schema.mof index b53c91b..a185c52 100644 --- a/DscResources/MSFT_WindowsFeature/MSFT_WindowsFeature.schema.mof +++ b/DscResources/MSFT_WindowsFeature/MSFT_WindowsFeature.schema.mof @@ -1,10 +1,11 @@ -[ClassVersion("1.0.0.0"), FriendlyName("WindowsFeature")] +[ClassVersion("1.0.0.0"), FriendlyName("WindowsFeature")] class MSFT_WindowsFeature : OMI_BaseResource { [Key, Description("The name of the role or feature to install or uninstall.")] String Name; [Write, Description("Specifies whether the role or feature should be installed or uninstalled. To install the feature, set this property to Present. To uninstall the feature, set the property to Absent."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] String Ensure; [Write, Description("Specifies whether the subfeatures of the main feature should also be installed.")] Boolean IncludeAllSubFeature; + [Write, Description("Specifies the path to a source-directory to install certain features.")] String Source; [Write, Description("The path to the log file to log this operation.")] String LogPath; [Write, Description("A credential, if needed, to install or uninstall the role or feature."), EmbeddedInstance("MSFT_Credential")] String Credential; [Read, Description("The display name of the retrieved role or feature.")] String DisplayName; diff --git a/Examples/Sample_WindowsFeature_WithSource.ps1 b/Examples/Sample_WindowsFeature_WithSource.ps1 new file mode 100644 index 0000000..30b8b1a --- /dev/null +++ b/Examples/Sample_WindowsFeature_WithSource.ps1 @@ -0,0 +1,21 @@ +<# + .SYNOPSIS + Installs the .NET 3.5 Framework feature, which needs additional files from the installation medium + which are specified by the Source-Parameter. +#> +Configuration WindowsFeatureExample_Install_WithSource +{ + [CmdletBinding()] + param () + + Import-DscResource -ModuleName 'PSDscResources' + + WindowsFeatureSet WindowsFeatureSet1 + { + Name = 'NET-Framework-Core' + Ensure = 'Present' + IncludeAllSubFeature = $false + Source = 'E:\sources\sxs' + } +} + diff --git a/README.md b/README.md index d6360a3..f2742e0 100644 --- a/README.md +++ b/README.md @@ -403,6 +403,7 @@ This resource **is not supported** on Nano Server. * **[String] Ensure** _(Write)_: Specifies whether the feature should be installed (Present) or uninstalled (Absent) { *Present* | Absent }. * **[Boolean] IncludeAllSubFeature** _(Write)_: Specifies whether or not all subfeatures should be installed with the specified role or feature. The default value is false. * **[String] LogPath** _(Write)_: Indicates the path to a log file to log the operation. +* **[String] Source** _(Write)_: Indicates the location of the source file to use for installation, if necessary. #### Read-Only Properties from Get-TargetResource