4 ConvertFrom-StringData @'
5 SetTargetResourceInstallwhatIfMessage=Trying to install feature {0}
6 SetTargetResourceUnInstallwhatIfMessage=Trying to Uninstall feature {0}
7 FeatureNotFoundError=The requested feature {0} is not found on the target machine.
8 FeatureDiscoveryFailureError=Failure to get the requested feature {0} information from the target machine. Wildcard pattern is not supported in the feature name.
9 FeatureInstallationFailureError=Failure to successfully install the feature {0} .
10 FeatureUnInstallationFailureError=Failure to successfully Unintstall the feature {0} .
11 QueryFeature=Querying for feature {0} using Server Manager cmdlet Get-WindowsFeature.
12 InstallFeature=Trying to install feature {0} using Server Manager cmdlet Add-WindowsFeature.
13 UninstallFeature=Trying to Uninstall feature {0} using Server Manager cmdlet Remove-WindowsFeature.
14 RestartNeeded=The Target machine needs to be restarted.
15 GetTargetResourceStartVerboseMessage=Begin executing Get functionality on the {0} feature.
16 GetTargetResourceEndVerboseMessage=End executing Get functionality on the {0} feature.
17 SetTargetResourceStartVerboseMessage=Begin executing Set functionality on the {0} feature.
18 SetTargetResourceEndVerboseMessage=End executing Set functionality on the {0} feature.
19 TestTargetResourceStartVerboseMessage=Begin executing Test functionality on the {0} feature.
20 TestTargetResourceEndVerboseMessage=End executing Test functionality on the {0} feature.
21 ServerManagerModuleNotFoundDebugMessage=ServerManager module is not installed on the machine.
22 SkuNotSupported=Installing roles and features using PowerShell Desired State Configuration is supported only on Server SKU's. It is not supported on Client SKU.
23 SourcePropertyNotSupportedDebugMessage=Source property in MSFT_RoleResource is not supported on this operating system and it was ignored.
24 EnableServerManagerPSHCmdletsFeature=Windows Server 2008R2 Core operating system detected: ServerManager-PSH-Cmdlets feature has been enabled.
25 UninstallSuccess=Successfully uninstalled the feature {0}.
26 InstallSuccess=Successfully installed the feature {0}.
30 Import-LocalizedData LocalizedData -filename MSFT_RoleResourceStrings
32 # The Get-TargetResource cmdlet is used to fetch the status of role or feature on the target machine.
33 # It gives the feature info of the requested role/feature on the target machine.
34 function Get-TargetResource
38 [parameter(Mandatory = $true)]
39 [ValidateNotNullOrEmpty()]
43 [Parameter(Mandatory=$false)]
44 [System.Management.Automation.PSCredential]
48 $getTargetResourceResult = $null;
50 $getTargetResourceStartVerboseMessage = $($LocalizedData.GetTargetResourceStartVerboseMessage) -f ${Name} ;
51 Write-Debug -Message $getTargetResourceStartVerboseMessage;
53 ValidatePrerequisites ;
55 $qyeryFeatureMessage = $($LocalizedData.QueryFeature) -f ${Name} ;
56 Write-Debug -Message $qyeryFeatureMessage;
58 $isR2Sp1 = IsWinServer2008R2SP1;
59 if($isR2Sp1 -and $psboundparameters.ContainsKey("Credential"))
61 $parameters = $psboundparameters.Remove("Credential");
62 $feature = Invoke-Command -ScriptBlock { Get-WindowsFeature @using:psboundparameters } -ComputerName . -Credential $Credential -ErrorVariable ev
63 $psboundparameters.Add("Credential", $Credential);
67 $feature = Get-WindowsFeature @psboundparameters -ErrorVariable ev
70 if($null -eq $ev -or $ev.Count -eq 0)
74 ValidateFeature $feature $Name;
76 # If a feature does not contain SubFeature then $includeAllSubFeature would be set to $false.
77 # If a feature contains one or more subfeatures then $includeAllSubFeature would be set to
78 # $true only if all the subfeatures are installed, or else $includeAllSubFeature would be set to $false.
79 $includeAllSubFeature = $true;
81 if($feature.SubFeatures.Count -eq 0)
83 $includeAllSubFeature = $false;
87 foreach($currentSubFeature in $feature.SubFeatures)
89 if($foundError -eq $false)
91 $parameters = $psboundparameters.Remove("Name");
92 $psboundparameters.Add("Name", $currentSubFeature);
94 $isR2Sp1 = IsWinServer2008R2SP1;
95 if($isR2Sp1 -and $psboundparameters.ContainsKey("Credential"))
97 $parameters = $psboundparameters.Remove("Credential");
98 $subFeature = Invoke-Command -ScriptBlock { Get-WindowsFeature @using:psboundparameters } -ComputerName . -Credential $Credential -ErrorVariable errorVar
99 $psboundparameters.Add("Credential", $Credential);
103 $subFeature = Get-WindowsFeature @psboundparameters -ErrorVariable errorVar
106 if($null -eq $errorVar -or $errorVar.Count -eq 0)
108 ValidateFeature $subFeature $currentSubFeature;
110 if(!$subFeature.Installed)
112 $includeAllSubFeature = $false;
118 $foundError = $true;;
124 if($foundError -eq $false)
126 if($feature.Installed)
128 $ensureResult = "Present";
132 $ensureResult = "Absent";
135 # Add all feature properties to the hash table
136 $getTargetResourceResult = @{
137 Name = $feature.Name;
138 DisplayName = $feature.DisplayName;
139 Ensure = $ensureResult;
140 IncludeAllSubFeature = $includeAllSubFeature;
143 $getTargetResourceEndVerboseMessage = $($LocalizedData.GetTargetResourceEndVerboseMessage) -f ${Name} ;
144 Write-Debug -Message $getTargetResourceEndVerboseMessage;
146 $getTargetResourceResult;
152 # The Set-TargetResource cmdlet is used to install or uninstall a role on the target machine.
153 # It also supports installing & uninstalling the role or feature specific subfeatures.
154 function Set-TargetResource
156 [CmdletBinding(SupportsShouldProcess=$true, DefaultParameterSetName = "FeatureName")]
160 [parameter(Mandatory=$true, ParameterSetName = "FeatureName")]
161 [ValidateNotNullOrEmpty()]
166 [ValidateSet("Present", "Absent")]
171 [ValidateNotNullOrEmpty()]
177 $IncludeAllSubFeature,
179 [Parameter(Mandatory=$false)]
180 [System.Management.Automation.PSCredential]
183 [ValidateNotNullOrEmpty()]
188 $getTargetResourceResult = $null;
190 $inputParameter = $null;
192 $setTargetResourceStartVerboseMessage = $($LocalizedData.SetTargetResourceStartVerboseMessage) -f ${Name} ;
193 Write-Debug -Message $setTargetResourceStartVerboseMessage;
195 ValidatePrerequisites ;
197 # -Source Parameter is not applicable to Windows Server 2008 R2 SP1. Hence removing it.
198 # all role/feature spcific binaries are avaliable inboc on Windows Server 2008 R2 SP1, hence
199 # -Source is not supported on Windows Server 2008 R2 SP1.
200 $isR2Sp1 = IsWinServer2008R2SP1;
201 if($isR2Sp1 -and $psboundparameters.ContainsKey("Source"))
203 $sourcePropertyNotSupportedDebugMessage = $($LocalizedData.SourcePropertyNotSupportedDebugMessage) ;
204 Write-Debug -Message $sourcePropertyNotSupportedDebugMessage;
206 $parameters = $psboundparameters.Remove("Source");
210 if($Ensure -eq "Present")
212 $parameters = $psboundparameters.Remove("Ensure");
214 $installFeatureMessage = $($LocalizedData.InstallFeature) -f ${Name} ;
215 Write-Debug -Message $installFeatureMessage;
217 $isR2Sp1 = IsWinServer2008R2SP1;
218 if($isR2Sp1 -and $psboundparameters.ContainsKey("Credential"))
220 $parameters = $psboundparameters.Remove("Credential");
221 $feature = Invoke-Command -ScriptBlock { Add-WindowsFeature @using:psboundparameters } -ComputerName . -Credential $Credential -ErrorVariable ev
222 $psboundparameters.Add("Credential", $Credential);
226 $feature = Add-WindowsFeature @psboundparameters -ErrorVariable ev
229 if($feature -ne $null -and $feature.Success -eq $true)
231 Write-Verbose ($LocalizedData.InstallSuccess -f $Name)
233 # Check if reboot is required, if so notify CA.
234 if($feature.RestartNeeded -eq "Yes")
236 $restartNeededMessage = $($LocalizedData.RestartNeeded);
237 Write-Verbose -Message $restartNeededMessage;
239 $global:DSCMachineStatus = 1;
244 # Add-WindowsFeature cmdlet falied to successfully install the requested feature.
245 # If there are errors from the Add-WindowsFeature cmdlet. We surface those errors.
246 # If Add-WindwosFeature cmdlet does not surface any errors. Then the provider throws a
248 if($null -eq $ev -or $ev.Count -eq 0)
250 $errorId = "FeatureInstallationFailure";
251 $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation;
252 $errorMessage = $($LocalizedData.FeatureInstallationFailureError) -f ${Name} ;
253 $exception = New-Object System.InvalidOperationException $errorMessage ;
254 $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null
256 $PSCmdlet.ThrowTerminatingError($errorRecord);
262 $parameters = $psboundparameters.Remove("Ensure");
263 $parameters = $psboundparameters.Remove("IncludeAllSubFeature");
264 $parameters = $psboundparameters.Remove("Source");
266 $uninstallFeatureMessage = $($LocalizedData.UninstallFeature) -f ${Name} ;
267 Write-Debug -Message $uninstallFeatureMessage;
269 $isR2Sp1 = IsWinServer2008R2SP1;
270 if($isR2Sp1 -and $psboundparameters.ContainsKey("Credential"))
272 $parameters = $psboundparameters.Remove("Credential");
273 $feature = Invoke-Command -ScriptBlock { Remove-WindowsFeature @using:psboundparameters } -ComputerName . -Credential $Credential -ErrorVariable ev
274 $psboundparameters.Add("Credential", $Credential);
278 $feature = Remove-WindowsFeature @psboundparameters -ErrorVariable ev
281 if($feature -ne $null -and $feature.Success -eq $true)
283 Write-Verbose ($LocalizedData.UninstallSuccess -f $Name)
285 # Check if reboot is required, if so notify CA.
286 if($feature.RestartNeeded -eq "Yes")
288 $restartNeededMessage = $($LocalizedData.RestartNeeded);
289 Write-Verbose -Message $restartNeededMessage;
291 $global:DSCMachineStatus = 1;
296 # Remove-WindowsFeature cmdlet falied to successfully Uninstall the requested feature.
297 # If there are errors from the Remove-WindowsFeature cmdlet. We surface those errors.
298 # If Remove-WindwosFeature cmdlet does not surface any errors. Then the provider throws a
300 if($null -eq $ev -or $ev.Count -eq 0)
302 $errorId = "FeatureUnInstallationFailure";
303 $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation;
304 $errorMessage = $($LocalizedData.FeatureUnInstallationFailureError) -f ${Name} ;
305 $exception = New-Object System.InvalidOperationException $errorMessage ;
306 $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null
308 $PSCmdlet.ThrowTerminatingError($errorRecord);
313 $setTargetResourceEndVerboseMessage = $($LocalizedData.SetTargetResourceEndVerboseMessage) -f ${Name} ;
314 Write-Debug -Message $setTargetResourceEndVerboseMessage;
317 # The Test-TargetResource cmdlet is used to validate if the role or feature is in a state as expected in the instance document.
318 function Test-TargetResource
322 [parameter(Mandatory = $true)]
323 [ValidateNotNullOrEmpty()]
328 [ValidateSet("Present", "Absent")]
333 [ValidateNotNullOrEmpty()]
339 $IncludeAllSubFeature,
342 [System.Management.Automation.PSCredential]
345 [ValidateNotNullOrEmpty()]
351 $testTargetResourceStartVerboseMessage = $($LocalizedData.TestTargetResourceStartVerboseMessage) -f ${Name} ;
352 Write-Debug -Message $testTargetResourceStartVerboseMessage;
354 ValidatePrerequisites ;
356 $testTargetResourceResult = $false;
358 $parameters = $psboundparameters.Remove("Ensure");
359 $parameters = $psboundparameters.Remove("IncludeAllSubFeature");
360 $parameters = $psboundparameters.Remove("Source");
362 $qyeryFeatureMessage = $($LocalizedData.QueryFeature) -f ${Name} ;
363 Write-Debug -Message $qyeryFeatureMessage;
365 $isR2Sp1 = IsWinServer2008R2SP1;
366 if($isR2Sp1 -and $psboundparameters.ContainsKey("Credential"))
368 $parameters = $psboundparameters.Remove("Credential");
369 $feature = Invoke-Command -ScriptBlock { Get-WindowsFeature @using:psboundparameters } -ComputerName . -Credential $Credential -ErrorVariable ev
370 $psboundparameters.Add("Credential", $Credential);
374 $feature = Get-WindowsFeature @psboundparameters -ErrorVariable ev
378 if($null -eq $ev -or $ev.Count -eq 0)
380 ValidateFeature $feature $Name;
383 # Check if the feature is in the requested Ensure state.
384 # If so then check if then check if the subfeature is in the requested Ensure state.
385 if(($Ensure -eq "Present" -and $feature.Installed -eq $true) -or
386 ($Ensure -eq "Absent" -and $feature.Installed -eq $false))
388 $testTargetResourceResult = $true;
390 # IncludeAllSubFeature is set to $true, so we need to make
391 # sure that all Sub Features are alsi installed.
392 if($IncludeAllSubFeature)
395 foreach($currentSubFeature in $feature.SubFeatures)
397 $parameters = $psboundparameters.Remove("Name");
398 $parameters = $psboundparameters.Remove("Ensure");
399 $parameters = $psboundparameters.Remove("IncludeAllSubFeature");
400 $parameters = $psboundparameters.Remove("Source");
401 $psboundparameters.Add("Name", $currentSubFeature);
403 $isR2Sp1 = IsWinServer2008R2SP1;
404 if($isR2Sp1 -and $psboundparameters.ContainsKey("Credential"))
406 $parameters = $psboundparameters.Remove("Credential");
407 $subFeature = Invoke-Command -ScriptBlock { Get-WindowsFeature @using:psboundparameters } -ComputerName . -Credential $Credential -ErrorVariable errorVar
408 $psboundparameters.Add("Credential", $Credential);
412 $subFeature = Get-WindowsFeature @psboundparameters -ErrorVariable errorVar
416 if($null -eq $errorVar -or $errorVar.Count -eq 0)
418 ValidateFeature $subFeature $currentSubFeature;
420 if(!$subFeature.Installed)
422 $testTargetResourceResult = $false;
430 $testTargetResourceEndVerboseMessage = $($LocalizedData.TestTargetResourceEndVerboseMessage) -f ${Name} ;
431 Write-Debug -Message $testTargetResourceEndVerboseMessage;
433 $testTargetResourceResult;
438 # ValidateFeature is a helper function used to validate the results of SM+ cmdlets
439 # Get-Windowsfeature for the user supplied feature name.
440 function ValidateFeature
449 if($null -eq $feature)
451 $errorId = "FeatureNotFound";
452 $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation
453 $errorMessage = $($LocalizedData.FeatureNotFoundError) -f ${Name}
454 $exception = New-Object System.InvalidOperationException $errorMessage
455 $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null
457 $PSCmdlet.ThrowTerminatingError($errorRecord);
460 # WildCard pattern is not supported by the role provider.
461 # Hence we restrict user to request only one feature information in a single request.
462 if($feature.Count -gt 1)
464 $errorId = "FeatureDiscoveryFailure";
465 $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult
466 $errorMessage = $($LocalizedData.FeatureDiscoveryFailureError) -f ${Name}
467 $exception = New-Object System.InvalidOperationException $errorMessage
468 $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null
470 $PSCmdlet.ThrowTerminatingError($errorRecord);
474 # ValidatePrerequisites is a helper function used to validate if the MSFT_RoleResource is supported on the target machine.
475 # MSFT_RoleResource is supported only on Server SKU's. MSFT_RoleResource depend on ServerManagerModule which is avaliable
476 # only on Server SKU's.
477 function ValidatePrerequisites
483 #Enable ServerManager-PSH-Cmdlets feature if os is WS2008R2 Core.
484 $datacenterServerCore = 12
485 $standardServerCore = 13
486 $EnterpriseServerCore = 14
488 $operatingSystem = Get-WmiObject -Class Win32_operatingsystem
489 if($operatingSystem.Version.StartsWith('6.1.') -and
490 (($operatingSystem.OperatingSystemSKU -eq $datacenterServerCore) -or ($operatingSystem.OperatingSystemSKU -eq $standardServerCore) -or ($operatingSystem.OperatingSystemSKU -eq $EnterpriseServerCore)))
492 Write-Verbose -Message $($LocalizedData.EnableServerManagerPSHCmdletsFeature)
494 # Update:ServerManager-PSH-Cmdlets has a depndency on Powershell 2 update: MicrosoftWindowsPowerShell
495 # Hence enabling MicrosoftWindowsPowerShell.
496 dism /online /enable-feature /FeatureName:MicrosoftWindowsPowerShell | Out-Null
497 dism /online /enable-feature /FeatureName:ServerManager-PSH-Cmdlets | Out-Null
500 if(Import-Module ServerManager -PassThru -Verbose:$false -ErrorAction Ignore)
506 $serverManagerModuleNotFoundDebugMessage = $($LocalizedData.ServerManagerModuleNotFoundDebugMessage);
507 Write-Debug -Message $serverManagerModuleNotFoundDebugMessage;
509 $errorId = "SkuNotSupported";
510 $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation
511 $errorMessage = $($LocalizedData.SkuNotSupported)
512 $exception = New-Object System.InvalidOperationException $errorMessage
513 $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null
515 $PSCmdlet.ThrowTerminatingError($errorRecord);
520 # IsWinServer2008R2SP1 is a helper function to detect if the target machine is a Win 2008 R2 SP1.
521 function IsWinServer2008R2SP1
527 # We are already checking for the Presence of ServerManager module before using this helper function.
528 # Hence checking for the version shoudl be good enough to confirm that the target machine is
529 # Windows Server 2008 R2 machine.
530 if([Environment]::OSVersion.Version.ToString().Contains("6.1."))
538 Export-ModuleMember -function Get-TargetResource, Set-TargetResource, Test-TargetResource