adding all service updates

This commit is contained in:
Mariah Breakey
2016-12-15 14:03:39 -08:00
parent d4adb24c32
commit ddcd7e8e95
15 changed files with 3010 additions and 2313 deletions
+18 -50
View File
@@ -1,60 +1,28 @@
<#
.SYNOPSIS
If the service with the name Service1 does not exist, creates the service with the name
Service1 and the executable/binary path 'C:\FilePath\MyServiceExecutable.exe'. The new
service will be started by default.
If the service with the name Service1 already exists, sets executable/binary path of the
service with the name Service1 to 'C:\FilePath\MyServiceExecutable.exe' and starts the
service by default if it is not running already.
#>
Configuration Sample_Service_CreateService
{
[CmdletBinding()]
param
(
[System.String[]]
$nodeName = 'localhost',
()
[System.String]
$Name,
[System.String]
[ValidateSet('Automatic', 'Manual', 'Disabled')]
$StartupType='Automatic',
Import-DscResource -ModuleName 'PSDscResources'
[System.String]
[ValidateSet('LocalSystem', 'LocalService', 'NetworkService')]
$BuiltInAccount='LocalSystem',
[System.Management.Automation.PSCredential]
$Credential,
[System.String]
[ValidateSet('Running', 'Stopped')]
$State='Running',
[System.String]
[ValidateSet('Present', 'Absent')]
$Ensure='Present',
[System.String]
$Path,
[System.String]
$DisplayName,
[System.String]
$Description,
[System.String[]]
$Dependencies
)
Import-DscResource -Name MSFT_ServiceResource -ModuleName PSDscResources
Node $nodeName
Node localhost
{
Service service
Service ServiceResource1
{
Name = $Name
Ensure = $Ensure
Path = $Path
Name = 'Service1'
Ensure = 'Present'
Path = 'C:\FilePath\MyServiceExecutable.exe'
}
}
}
Sample_Service_CreateService -Name 'Sample Service' -Ensure 'Present' -Path 'C:\DSC\TestService.exe'
+11 -49
View File
@@ -1,59 +1,21 @@
<#
.SYNOPSIS
Stops and then removes the service with the name Service1.
#>
Configuration Sample_Service_DeleteService
{
[CmdletBinding()]
param
(
[System.String[]]
$nodeName = 'localhost',
()
[System.String]
$Name,
[System.String]
[ValidateSet('Automatic', 'Manual', 'Disabled')]
$StartupType,
Import-DscResource -ModuleName 'PSDscResources'
[System.String]
[ValidateSet('LocalSystem', 'LocalService', 'NetworkService')]
$BuiltInAccount,
[System.Management.Automation.PSCredential]
$Credential ,
[System.String]
[ValidateSet('Running', 'Stopped')]
$State='Running',
[System.String]
[ValidateSet('Present', 'Absent')]
$Ensure='Present',
[System.String]
$Path,
[System.String]
$DisplayName,
[System.String]
$Description,
[System.String[]]
$Dependencies
)
Import-DscResource -Name MSFT_ServiceResource -ModuleName PSDscResources
Node $nodeName
Node localhost
{
Service service
Service ServiceResource1
{
Name = $Name
Ensure = $Ensure
Name = 'Service1'
Ensure = 'Absent'
}
}
}
Sample_Service_DeleteService -Name 'Sample Service' -Ensure 'Absent'
@@ -1,68 +0,0 @@
Configuration Sample_Service_ServiceWithCredential
{
param
(
[System.String[]]
$nodeName = 'localhost',
[System.String]
$Name,
[System.String]
[ValidateSet('Automatic', 'Manual', 'Disabled')]
$StartupType='Automatic',
[System.String]
[ValidateSet('LocalSystem', 'LocalService', 'NetworkService')]
$BuiltInAccount='LocalSystem',
[System.Management.Automation.PSCredential]
$Credential,
[System.String]
[ValidateSet('Running', 'Stopped')]
$State='Running',
[System.String]
[ValidateSet('Present', 'Absent')]
$Ensure='Present',
[System.String]
$Path,
[System.String]
$DisplayName,
[System.String]
$Description,
[System.String[]]
$Dependencies
)
Import-DscResource -Name MSFT_ServiceResource -ModuleName PSDscResources
Node $nodeName
{
Service service
{
Name = $Name
DisplayName = $DisplayName
Ensure = $Ensure
Path = $Path
StartupType = $StartupType
Credential = $credential
DesktopInteract = 'False'
}
}
}
# To use the sample(s) with credentials, see blog at http://blogs.msdn.com/b/powershell/archive/2014/01/31/want-to-secure-credentials-in-windows-powershell-desired-state-configuration.aspx
@@ -0,0 +1,28 @@
<#
.SYNOPSIS
If the service with the name Service1 does not exist, this configuration would throw an
error since the Path is not included here.
If the service with the name Service1 already exists, sets the startup type of the service
with the name Service1 to Manual and ignores the state that the service is currently in.
If State is not specified, the configuration will ensure that the state of the service is
Running by default.
#>
Configuration Sample_Service_UpdateStartupTypeIgnoreState
{
[CmdletBinding()]
param ()
Import-DscResource -ModuleName 'PSDscResources'
Node localhost
{
Service ServiceResource1
{
Name = 'Service1'
Ensure = 'Present'
StartupType = 'Manual'
State = 'Ignore'
}
}
}
+7 -4
View File
@@ -37,9 +37,9 @@ Please check out the common DSC Resources [contributing guidelines](https://gith
* [Group](#group): Provides a mechanism to manage local groups on a target node.
* [Service](#service): Provides a mechanism to configure and manage Windows services on a target node.
* [User](#user): Provides a mechanism to manage local users on a target node.
* [WindowsFeature](#windowsfeature): Provides a mechanism to install or uninstall windows roles or features on a target node.
* [WindowsFeature](#windowsfeature): Provides a mechanism to install or uninstall Windows roles or features on a target node.
* [WindowsOptionalFeature](#windowsoptionalfeature): Provides a mechanism to enable or disable optional features on a target node.
* [WindowsPackageCab](#windowspackagecab): Provides a mechanism to install or uninstall a package from a windows cabinet (cab) file on a target node.
* [WindowsPackageCab](#windowspackagecab): Provides a mechanism to install or uninstall a package from a Windows cabinet (cab) file on a target node.
* [WindowsProcess](#windowsprocess): Provides a mechanism to start and stop a Windows process.
### Resources that Work on Nano Server
@@ -111,6 +111,7 @@ None
* [Create a service](https://github.com/PowerShell/PSDscResources/blob/master/Examples/Sample_Service_CreateService.ps1)
* [Delete a service](https://github.com/PowerShell/PSDscResources/blob/master/Examples/Sample_Service_DeleteService.ps1)
* [Update a service with StartupType set to 'Ignore'](https://github.com/PowerShell/PSDscResources/blob/master/Examples/Sample_Service_UpdateStartupTypeIgnoreState)
### User
@@ -196,11 +197,11 @@ This resource works on Nano Server.
#### Examples
* [Enable the specified windows optional feature and output logs to the specified path](https://github.com/PowerShell/PSDscResources/blob/master/Examples/Sample_WindowsOptionalFeature.ps1)
* [Enable the specified Windows optional feature and output logs to the specified path](https://github.com/PowerShell/PSDscResources/blob/master/Examples/Sample_WindowsOptionalFeature.ps1)
### WindowsPackageCab
Provides a mechanism to install or uninstall a package from a windows cabinet (cab) file on a target node.
Provides a mechanism to install or uninstall a package from a Windows cabinet (cab) file on a target node.
This resource works on Nano Server.
#### Requirements
@@ -268,6 +269,8 @@ None
* CommonTestHelper:
* Added Get-AppVeyorAdministratorCredential
* Added Set-StrictMode -'Latest' and $errorActionPreference -'Stop'
* Service:
* Updated resource module, tests, and examples to reflect the changes made in xPSDesiredStateConfiguration
### 2.1.0.0
@@ -1,14 +1,25 @@
<#
These tests should only be run in AppVeyor since they currently require the AppVeyor
administrator account credential to run.
Also please note that these tests are currently dependent on each other.
They must be run in the order given and if one test fails, subsequent tests will
also fail.
#>
if ($PSVersionTable.PSVersion.Major -lt 5 -or $PSVersionTable.PSVersion.Minor -lt 1)
{
Write-Warning -Message 'Cannot run PSDscResources integration tests on PowerShell versions lower than 5.1'
return
}
$script:DscResourceName = 'MSFT_ServiceResource'
$errorActionPreference = 'Stop'
Set-StrictMode -Version 'Latest'
Import-Module -Name (Join-Path -Path (Split-Path -Path $PSScriptRoot -Parent) `
-ChildPath (Join-Path -Path 'TestHelpers' `
-ChildPath 'CommonTestHelper.psm1'))
# Import CommonTestHelper for Enter-DscResourceTestEnvironment, Exit-DscResourceTestEnvironment
$script:moduleRootPath = Split-Path -Path $PSScriptRoot -Parent
$script:testHelpersPath = Join-Path -Path $script:moduleRootPath -ChildPath 'TestHelpers'
Import-Module -Name (Join-Path -Path $script:testHelpersPath -ChildPath 'CommonTestHelper.psm1')
$script:testEnvironment = Enter-DscResourceTestEnvironment `
-DscResourceModuleName 'PSDscResources' `
@@ -17,174 +28,386 @@ $script:testEnvironment = Enter-DscResourceTestEnvironment `
try
{
$script:testServiceName = 'DscTestService'
$script:testServiceCodePath = Join-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -ChildPath 'TestHelpers\DscTestService.cs'
$script:testServiceDisplayName = 'DSC test service display name'
$script:testServiceDescription = 'This is a DSC test service used for integration testing MSFT_ServiceResource'
$script:testServiceDependsOn = 'winrm'
$script:testServiceExecutablePath = Join-Path -Path $ENV:Temp -ChildPath 'DscTestService.exe'
$script:testServiceNewCodePath = Join-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -ChildPath 'TestHelpers\DscTestService.cs'
$script:testServiceNewDisplayName = 'New: DSC test service display name'
$script:testServiceNewDescription = 'New: This is a DSC test service used for integration testing MSFT_ServiceResource'
$script:testServiceNewDependsOn = 'spooler'
$script:testServiceNewExecutablePath = Join-Path -Path $ENV:Temp -ChildPath 'NewDscTestService.exe'
<#
Nano Server doesn't recognize 'spooler', so if these tests are being run on Nano
this value must stay as 'winrm'
#>
if ($PSVersionTable.PSEdition -ieq 'Core') { $script:testServiceNewDependsOn = 'winrm' }
Describe 'Service Integration Tests' {
BeforeAll {
# Import CommonResourceHelper for Test-IsNanoServer, Get-AppveyorAdministratorCredential
$moduleRootFilePath = Split-Path -Path $script:testsFolderFilePath -Parent
$dscResourcesFolderFilePath = Join-Path -Path $moduleRootFilePath -ChildPath 'DscResources'
$commonResourceHelperFilePath = Join-Path -Path $dscResourcesFolderFilePath -ChildPath 'CommonResourceHelper.psm1'
Import-Module -Name $commonResourceHelperFilePath
Import-Module -Name (Join-Path -Path (Split-Path -Path $PSScriptRoot -Parent) `
-ChildPath 'TestHelpers\MSFT_ServiceResource.TestHelper.psm1') `
-Force
# Import DscResource.Tests TestHelper for Reset-Dsc
$dscResourceTestsFilePath = Join-Path -Path $moduleRootFilePath -ChildPath 'DscResource.Tests'
$dscResourceTestHelperFilePath = Join-Path -Path $dscResourceTestsFilePath -ChildPath 'TestHelper.psm1'
Import-Module -Name $dscResourceTestHelperFilePath
Stop-Service $script:testServiceName -ErrorAction SilentlyContinue
# Import Service test helper for New-ServiceBinary, Test-ServiceExists, Remove-ServiceWithTimeout
$serviceTestHelperFilePath = Join-Path -Path $script:testsHelpersFilePath -ChildPath 'MSFT_ServiceResource.TestHelper.psm1'
Import-Module -Name $serviceTestHelperFilePath
# Create new Service binaries for the new service.
New-ServiceBinary `
-ServiceName $script:testServiceName `
-ServiceCodePath $script:testServiceCodePath `
-ServiceDisplayName $script:testServiceDisplayName `
-ServiceDescription $script:testServiceDescription `
-ServiceDependsOn $script:testServiceDependsOn `
-ServiceExecutablePath $script:testServiceExecutablePath
# Import Service resource module for Test-TargetResource
$serviceResourceFolderFilePath = Join-Path -Path $dscResourcesFolderFilePath -ChildPath 'MSFT_ServiceResource'
$serviceResourceModuleFilePath = Join-Path -Path $serviceResourceFolderFilePath -ChildPath 'MSFT_ServiceResource.psm1'
Import-Module -Name $serviceResourceModuleFilePath
New-ServiceBinary `
-ServiceName $script:testServiceName `
-ServiceCodePath $script:testServiceNewCodePath `
-ServiceDisplayName $script:testServiceNewDisplayName `
-ServiceDescription $script:testServiceNewDescription `
-ServiceDependsOn $script:testServiceNewDependsOn `
-ServiceExecutablePath $script:testServiceExecutablePath
# Configuration file paths
$script:configurationAllExceptCredentialFilePath = Join-Path -Path $PSScriptRoot -ChildPath 'MSFT_ServiceResource_AllExceptCredential.config.ps1'
$script:configurationCredentialOnlyFilePath = Join-Path -Path $PSScriptRoot -ChildPath 'MSFT_ServiceResource_CredentialOnly.config.ps1'
#region Integration Tests
$configFile = Join-Path -Path $PSScriptRoot -ChildPath "$($script:DscResourceName)_Add.config.ps1"
. $configFile
# Create test service binary to be the existing service
$script:existingServiceProperties = @{
Name = 'TestService'
DisplayName = 'TestDisplayName'
Description = 'Test service description'
Dependencies = @( 'winrm' )
Path = Join-Path -Path $TestDrive -ChildPath 'DscTestService.exe'
}
Describe "$($script:DscResourceName) Add Service" {
$existingServiceNewExecutableParameters = @{
ServiceName = $script:existingServiceProperties.Name
ServiceCodePath = Join-Path -Path $script:testsHelpersPath -ChildPath 'DscTestService.cs'
ServiceDisplayName = $script:existingServiceProperties.DisplayName
ServiceDescription = $script:existingServiceProperties.Description
ServiceDependsOn = $script:existingServiceProperties.Dependencies -join ', '
OutputPath = $script:existingServiceProperties.Path
}
It 'Should compile and apply the MOF without throwing' {
New-ServiceExecutable @existingServiceNewExecutableParameters
# Create test service binary to be the new service with the same name as the existing service
$script:newServiceProperties = @{
Name = $script:existingServiceProperties.Name
DisplayName = 'NewTestDisplayName'
Description = 'New test service description'
Dependencies = @( 'spooler' )
Path = Join-Path -Path $TestDrive -ChildPath 'NewDscTestService.exe'
}
if (Test-IsNanoServer)
{
& "$($script:DscResourceName)_Add_Config" `
-OutputPath $script:testEnvironment.WorkingFolder `
-ServiceName $script:testServiceName `
-ServicePath $script:testServiceExecutablePath `
-ServiceDisplayName $script:testServiceDisplayName `
-ServiceDescription $script:testServiceDescription `
-ServiceDependsOn $script:testServiceDependsOn
# Nano Server does not recognize 'spooler', so keep the dependencies value as 'winrm'
$newServiceProperties['Dependencies'] = @( 'winrm' )
}
Start-DscConfiguration -Path $script:testEnvironment.WorkingFolder `
-ComputerName localhost -Wait -Verbose -Force
} | Should Not Throw
$newServiceNewExecutableParameters = @{
ServiceName = $script:newServiceProperties.Name
ServiceCodePath = Join-Path -Path $script:testHelpersPath -ChildPath 'DscTestServiceNew.cs'
ServiceDisplayName = $script:newServiceProperties.DisplayName
ServiceDescription = $script:newServiceProperties.Description
ServiceDependsOn = $script:newServiceProperties.Dependencies -join ', '
OutputPath = $script:newServiceProperties.Path
}
New-ServiceExecutable @newServiceNewExecutableParameters
$script:testServiceNames = @( $script:existingServiceProperties.Name )
$script:testServiceExecutables = @( $script:existingServiceProperties.Path, $script:newServiceProperties.Path )
}
It 'Should be able to call Get-DscConfiguration without throwing' {
{ Get-DscConfiguration -Verbose -ErrorAction Stop } | Should Not Throw
AfterAll {
# Remove any created services
foreach ($testServiceName in $script:testServiceNames)
{
if (Test-ServiceExists -Name $testServiceName)
{
Remove-ServiceWithTimeout -Name $testServiceName
}
}
}
$script:service = Get-CimInstance -ClassName Win32_Service -Filter "Name='$($script:testServiceName)'"
It 'Should return a service of type CimInstance' {
$script:service | Should BeOfType 'Microsoft.Management.Infrastructure.CimInstance'
Context 'Create a service' {
Reset-DSC
$configurationName = 'TestCreateService'
$resourceParameters = $script:existingServiceProperties
It 'Should compile and apply the MOF without throwing' {
{
. $script:configurationAllExceptCredentialFilePath -ConfigurationName $configurationName
& $configurationName -OutputPath $TestDrive @resourceParameters
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
}
$service = Get-Service -Name $resourceParameters.Name -ErrorAction 'SilentlyContinue'
$serviceCimInstance = Get-CimInstance -ClassName 'Win32_Service' -Filter "Name='$($resourceParameters.Name)'" -ErrorAction 'SilentlyContinue'
It 'Should have created a new service with the specified name' {
$service | Should Not Be $null
$serviceCimInstance | Should Not Be $null
$service.Name | Should Be $resourceParameters.Name
$serviceCimInstance.Name | Should Be $resourceParameters.Name
}
It 'Should have created a new service with the specified path' {
$serviceCimInstance.PathName | Should Be $resourceParameters.Path
}
It 'Should have created a new service with the specified display name' {
$service.DisplayName | Should Be $resourceParameters.DisplayName
}
It 'Should have created a new service with the specified description' {
$serviceCimInstance.Description | Should Be $resourceParameters.Description
}
It 'Should have created a new service with the specified dependencies' {
$differentDependencies = Compare-Object -ReferenceObject $resourceParameters.Dependencies -DifferenceObject $service.ServicesDependedOn.Name
$differentDependencies | Should Be $null
}
It 'Should have created a new service with the default state as Running' {
$service.Status | Should Be 'Running'
}
It 'Should have created a new service with the default startup type as Auto' {
$serviceCimInstance.StartMode | Should Be 'Auto'
}
It 'Should have created a new service with the default startup account name as LocalSystem' {
$serviceCimInstance.StartName | Should Be 'LocalSystem'
}
It 'Should have created a new service with the default desktop interaction setting as False' {
$serviceCimInstance.DesktopInteract | Should Be $false
}
It 'Should return true from Test-TargetResource with the same parameters' {
MSFT_ServiceResource\Test-TargetResource @resourceParameters | Should Be $true
}
}
It 'Should have set the resource and all the parameters should match' {
# Get the current service details
$script:service.status | Should Be 'OK'
$script:service.pathname | Should Be $script:testServiceExecutablePath
$script:service.description | Should Be $script:testServiceDescription
$script:service.displayname | Should Be $script:testServiceDisplayName
$script:service.started | Should Be $true
$script:service.state | Should Be 'Running'
$script:service.desktopinteract | Should Be $true
$script:service.startname | Should Be 'LocalSystem'
$script:service.startmode | Should Be 'Auto'
Context 'Edit the service path, display name, description, and dependencies' {
Reset-DSC
$configurationName = 'TestCreateService'
$resourceParameters = $script:newServiceProperties
It 'Should compile and apply the MOF without throwing' {
{
. $script:configurationAllExceptCredentialFilePath -ConfigurationName $configurationName
& $configurationName -OutputPath $TestDrive @resourceParameters
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
}
$service = Get-Service -Name $resourceParameters.Name -ErrorAction 'SilentlyContinue'
$serviceCimInstance = Get-CimInstance -ClassName 'Win32_Service' -Filter "Name='$($resourceParameters.Name)'" -ErrorAction 'SilentlyContinue'
It 'Should not have removed service with specified name' {
$service | Should Not Be $null
$serviceCimInstance | Should Not Be $null
$service.Name | Should Be $resourceParameters.Name
$serviceCimInstance.Name | Should Be $resourceParameters.Name
}
It 'Should have edited service to have the specified path' {
$serviceCimInstance.PathName | Should Be $resourceParameters.Path
}
It 'Should have edited service to have the specified display name' {
$service.DisplayName | Should Be $resourceParameters.DisplayName
}
It 'Should have edited service to have the specified description' {
$serviceCimInstance.Description | Should Be $resourceParameters.Description
}
It 'Should have edited service to have the specified dependencies' {
$differentDependencies = Compare-Object -ReferenceObject $resourceParameters.Dependencies -DifferenceObject $service.ServicesDependedOn.Name
$differentDependencies | Should Be $null
}
It 'Should not have changed the service state from Running' {
$service.Status | Should Be 'Running'
}
It 'Should not have changed the service startup type from Auto' {
$serviceCimInstance.StartMode | Should Be 'Auto'
}
It 'Should not have changed the service startup account name from LocalSystem' {
$serviceCimInstance.StartName | Should Be 'LocalSystem'
}
It 'Should not have changed the service desktop interaction setting from False' {
$serviceCimInstance.DesktopInteract | Should Be $false
}
It 'Should return true from Test-TargetResource with the same parameters' {
MSFT_ServiceResource\Test-TargetResource @resourceParameters | Should Be $true
}
}
Context 'Edit the service startup type and state' {
Reset-DSC
$configurationName = 'TestCreateService'
$resourceParameters = @{
Name = $script:existingServiceProperties.Name
Path = $script:newServiceProperties.Path
StartupType = 'Manual'
State = 'Stopped'
}
It 'Should compile and apply the MOF without throwing' {
{
. $script:configurationAllExceptCredentialFilePath -ConfigurationName $configurationName
& $configurationName -OutputPath $TestDrive @resourceParameters
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
}
$service = Get-Service -Name $resourceParameters.Name -ErrorAction 'SilentlyContinue'
$serviceCimInstance = Get-CimInstance -ClassName 'Win32_Service' -Filter "Name='$($resourceParameters.Name)'" -ErrorAction 'SilentlyContinue'
It 'Should not have removed service with specified name' {
$service | Should Not Be $null
$serviceCimInstance | Should Not Be $null
$service.Name | Should Be $resourceParameters.Name
$serviceCimInstance.Name | Should Be $resourceParameters.Name
}
It 'Should have edited the service to have the specified state' {
$service.Status | Should Be $resourceParameters.State
}
It 'Should have edited the service to have the specified startup type' {
$serviceCimInstance.StartMode | Should Be $resourceParameters.StartupType
}
It 'Should return true from Test-TargetResource with the same parameters' {
MSFT_ServiceResource\Test-TargetResource @resourceParameters | Should Be $true
}
}
Context 'Edit the service start name and start password with Credential' {
Reset-DSC
$configData = @{
AllNodes = @(
@{
NodeName = 'localhost'
PSDscAllowPlainTextPassword = $true
}
)
}
$configurationName = 'TestCreateService'
$resourceParameters = @{
Name = 'TestService'
Credential = Get-AppVeyorAdministratorCredential
}
It 'Should compile and apply the MOF without throwing' {
{
. $script:configurationCredentialOnlyFilePath -ConfigurationName $configurationName
& $configurationName -OutputPath $TestDrive -ConfigurationData $configData @resourceParameters
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
}
$service = Get-Service -Name $resourceParameters.Name -ErrorAction 'SilentlyContinue'
$serviceCimInstance = Get-CimInstance -ClassName 'Win32_Service' -Filter "Name='$($resourceParameters.Name)'" -ErrorAction 'SilentlyContinue'
It 'Should not have removed service with specified name' {
$service | Should Not Be $null
$serviceCimInstance | Should Not Be $null
$service.Name | Should Be $resourceParameters.Name
$serviceCimInstance.Name | Should Be $resourceParameters.Name
}
It 'Should have edited the service to have the specified startup account name' {
$expectedStartName = $resourceParameters.Credential.UserName
if ($expectedStartName.StartsWith("$env:COMPUTERNAME\"))
{
$expectedStartName = $expectedStartName.TrimStart("$env:COMPUTERNAME\")
}
$serviceCimInstance.StartName | Should Be ".\$expectedStartName"
}
It 'Should return true from Test-TargetResource with the same parameters' {
MSFT_ServiceResource\Test-TargetResource @resourceParameters | Should Be $true
}
}
Context 'Edit the service start name and start password with BuiltInAccount' {
Reset-DSC
$configurationName = 'TestCreateService'
$resourceParameters = @{
Name = 'TestService'
Path = $script:newServiceProperties.Path
BuiltInAccount = 'LocalService'
}
It 'Should compile and apply the MOF without throwing' {
{
. $script:configurationAllExceptCredentialFilePath -ConfigurationName $configurationName
& $configurationName -OutputPath $TestDrive @resourceParameters
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
}
$service = Get-Service -Name $resourceParameters.Name -ErrorAction 'SilentlyContinue'
$serviceCimInstance = Get-CimInstance -ClassName 'Win32_Service' -Filter "Name='$($resourceParameters.Name)'" -ErrorAction 'SilentlyContinue'
It 'Should not have removed service with specified name' {
$service | Should Not Be $null
$serviceCimInstance | Should Not Be $null
$service.Name | Should Be $resourceParameters.Name
$serviceCimInstance.Name | Should Be $resourceParameters.Name
}
It 'Should have edited the service to have the specified startup account name' {
$serviceCimInstance.StartName | Should Be 'NT Authority\LocalService'
}
It 'Should return true from Test-TargetResource with the same parameters' {
MSFT_ServiceResource\Test-TargetResource @resourceParameters | Should Be $true
}
}
Context 'Remove the service' {
Reset-DSC
$configurationName = 'TestCreateService'
$resourceParameters = @{
Name = $script:existingServiceProperties.Name
Path = $script:existingServiceProperties.Path
Ensure = 'Absent'
}
It 'Should compile and apply the MOF without throwing' {
{
. $script:configurationAllExceptCredentialFilePath -ConfigurationName $configurationName
& $configurationName -OutputPath $TestDrive @resourceParameters
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
}
$service = Get-Service -Name $resourceParameters.Name -ErrorAction 'SilentlyContinue'
$serviceCimInstance = Get-CimInstance -ClassName 'Win32_Service' -Filter "Name='$($resourceParameters.Name)'" -ErrorAction 'SilentlyContinue'
It 'Should have removed the service with specified name' {
$service | Should Be $null
$serviceCimInstance | Should Be $null
}
It 'Should return true from Test-TargetResource with the same parameters' {
MSFT_ServiceResource\Test-TargetResource @resourceParameters | Should Be $true
}
}
}
Reset-DSC
$configFile = Join-Path -Path $PSScriptRoot -ChildPath "$($script:DscResourceName)_Edit.config.ps1"
. $configFile
Describe "$($script:DscResourceName) Edit Service" {
It 'Should compile and apply the MOF without throwing' {
{
& "$($script:DscResourceName)_Edit_Config" `
-OutputPath $script:testEnvironment.WorkingFolder `
-ServiceName $script:testServiceName `
-ServicePath $script:testServiceNewExecutablePath `
-ServiceDisplayName $script:testServiceNewDisplayName `
-ServiceDescription $script:testServiceNewDescription `
-ServiceDependsOn $script:testServiceNewDependsOn
Start-DscConfiguration -Path $script:testEnvironment.WorkingFolder `
-ComputerName localhost -Wait -Verbose -Force
} | Should Not Throw
}
It 'Should be able to call Get-DscConfiguration without throwing' {
{ Get-DscConfiguration -Verbose -ErrorAction Stop } | Should Not Throw
}
# Get the current service details
$script:service = Get-CimInstance -ClassName Win32_Service -Filter "Name='$($script:testServiceName)'"
It 'Should return a service or type CimInstance' {
$script:service | Should BeOfType 'Microsoft.Management.Infrastructure.CimInstance'
}
It 'Should have set the resource and all the parameters should match' {
# Get the current service details
$script:service.status | Should Be 'OK'
$script:service.pathname | Should Be $script:testServiceNewExecutablePath
$script:service.description | Should Be $script:testServiceNewDescription
$script:service.displayname | Should Be $script:testServiceNewDisplayName
$script:service.started | Should Be $false
$script:service.state | Should Be 'Stopped'
$script:service.desktopinteract | Should Be $false
$script:service.startname | Should Be 'NT Authority\LocalService'
$script:service.startmode | Should Be 'Manual'
}
}
Reset-DSC
$configFile = Join-Path -Path $PSScriptRoot -ChildPath "$($script:DscResourceName)_Remove.config.ps1"
. $configFile
Describe "$($script:DscResourceName) Remove Service" {
It 'Should compile and apply the MOF without throwing' {
{
& "$($script:DscResourceName)_Remove_Config" `
-OutputPath $script:testEnvironment.WorkingFolder `
-ServiceName $script:testServiceName
Start-DscConfiguration -Path $script:testEnvironment.WorkingFolder `
-ComputerName localhost -Wait -Verbose -Force
} | Should not throw
}
It 'Should be able to call Get-DscConfiguration without throwing' {
{ Get-DscConfiguration -Verbose -ErrorAction Stop } | Should Not throw
}
# Get the current service details
$script:service = Get-CimInstance -ClassName Win32_Service -Filter "Name='$($script:testServiceName)'"
It 'Should return the service as null' {
$script:service | Should BeNullOrEmpty
}
}
#endregion
}
finally
{
# Clean up
Remove-TestService `
-ServiceName $script:testServiceName `
-ServiceExecutablePath $script:testServiceExecutablePath
Exit-DscResourceTestEnvironment -TestEnvironment $script:testEnvironment
}
@@ -0,0 +1,89 @@
param
(
[Parameter(Mandatory = $true)]
[String]
$ConfigurationName
)
Configuration $ConfigurationName
{
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$Name,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$Path,
[ValidateSet('Present', 'Absent')]
[ValidateNotNullOrEmpty()]
[String]
$Ensure = 'Present',
[Parameter()]
[ValidateNotNullOrEmpty()]
[String]
$DisplayName = "$Name DisplayName",
[Parameter()]
[String]
$Description = 'TestDescription',
[Parameter()]
[String[]]
[AllowEmptyCollection()]
$Dependencies = @(),
[Parameter()]
[ValidateSet('LocalSystem', 'LocalService', 'NetworkService')]
[String]
$BuiltInAccount = 'LocalSystem',
[Parameter()]
[Boolean]
$DesktopInteract = $false,
[Parameter()]
[ValidateSet('Automatic', 'Manual', 'Disabled')]
[String]
$StartupType = 'Automatic',
[Parameter()]
[ValidateSet('Running', 'Stopped', 'Ignore')]
[String]
$State = 'Running',
[Parameter()]
[UInt32]
$StartupTimeout = 30000,
[Parameter()]
[UInt32]
$TerminateTimeout = 30000
)
Import-DscResource -ModuleName 'PSDscResources'
Node localhost
{
Service Service1
{
Name = $Name
Ensure = $Ensure
Path = $Path
StartupType = $StartupType
BuiltInAccount = $BuiltInAccount
DesktopInteract = $DesktopInteract
State = $State
DisplayName = $DisplayName
Description = $Description
Dependencies = $Dependencies
StartupTimeout = $StartupTimeout
TerminateTimeout = $TerminateTimeout
}
}
}
@@ -0,0 +1,39 @@
param
(
[Parameter(Mandatory = $true)]
[String]
$ConfigurationName
)
Configuration $ConfigurationName
{
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$Name,
[ValidateSet('Present', 'Absent')]
[ValidateNotNullOrEmpty()]
[String]
$Ensure = 'Present',
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.PSCredential]
$Credential
)
Import-DscResource -ModuleName 'PSDscResources'
Node localhost
{
Service Service1
{
Name = $Name
Ensure = $Ensure
Credential = $Credential
}
}
}
@@ -1,27 +0,0 @@
Configuration MSFT_ServiceResource_Add_Config {
param
(
$ServiceName,
$ServicePath,
$ServiceDisplayName,
$ServiceDescription,
$ServiceDependsOn
)
Import-DscResource -ModuleName PSDscResources
node localhost {
Service AddService {
Name = $ServiceName
Ensure = 'Present'
Path = $ServicePath
StartupType = 'Automatic'
BuiltInAccount = 'LocalSystem'
DesktopInteract = $true
State = 'Running'
DisplayName = $ServiceDisplayName
Description = $ServiceDescription
Dependencies = $ServiceDependsOn
}
}
}
@@ -1,27 +0,0 @@
Configuration MSFT_ServiceResource_Edit_Config {
param
(
$ServiceName,
$ServicePath,
$ServiceDisplayName,
$ServiceDescription,
$ServiceDependsOn
)
Import-DscResource -ModuleName PSDscResources
node localhost {
Service EditService {
Name = $ServiceName
Ensure = 'Present'
Path = $ServicePath
StartupType = 'Manual'
BuiltInAccount = 'LocalService'
DesktopInteract = $false
State = 'Stopped'
DisplayName = $ServiceDisplayName
Description = $ServiceDescription
Dependencies = $ServiceDependsOn
}
}
}
@@ -1,15 +0,0 @@
Configuration MSFT_ServiceResource_Remove_Config {
param
(
$ServiceName
)
Import-DscResource -ModuleName PSDscResources
node localhost {
Service RemoveService {
Name = $ServiceName
Ensure = 'Absent'
}
}
}
+2 -1
View File
@@ -1,4 +1,4 @@
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')]
param ()
$errorActionPreference = 'Stop'
@@ -87,6 +87,7 @@ function Test-IsLocalMachine
NOTE: This is likely overkill; consider removing it.
#>
$networkAdapters = @(Get-CimInstance Win32_NetworkAdapterConfiguration)
foreach ($networkAdapter in $networkAdapters)
{
if ($null -ne $networkAdapter.IPAddress)
@@ -1,153 +1,140 @@
$errorActionPreference = 'Stop'
Set-StrictMode -Version 'Latest'
<#
.SYNOPSIS
Creates a service binary file.
Creates a service executable.
.PARAMETER ServiceName
The name of the service to create the binary file for.
The name of the service to create the executable for.
.PARAMETER ServiceCodePath
The path to the code for the service to create the binary file for.
The path to the code for the service to create the executable for.
.PARAMETER ServiceDisplayName
The display name of the service to create the binary file for.
The display name of the service to create the executable for.
.PARAMETER ServiceDescription
The description of the service to create the binary file for.
The description of the service to create the executable for.
.PARAMETER ServiceDependsOn
Dependencies of the service to create the binary file for.
The names of the dependencies of the service to create the executable for.
.PARAMETER ServiceExecutablePath
The path to write the service executable to.
.PARAMETER OutputPath
The path to write the outputed service executable to.
#>
function New-ServiceBinary
function New-ServiceExecutable
{
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$ServiceName,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$ServiceCodePath,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$ServiceDisplayName,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$ServiceDescription,
[Parameter(Mandatory = $true)]
[Parameter()]
[ValidateNotNullOrEmpty()]
[String]
$ServiceDependsOn,
$ServiceDependsOn = "''",
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$ServiceExecutablePath
$OutputPath
)
if (Get-Service $ServiceName -ErrorAction Ignore)
{
Stop-Service $ServiceName -ErrorAction SilentlyContinue
Remove-TestService -ServiceName $ServiceName -ServiceExecutablePath $ServiceExecutablePath
}
$fileText = Get-Content $ServiceCodePath -Raw
$fileText = Get-Content -Path $ServiceCodePath -Raw
$fileText = $fileText.Replace('TestServiceReplacementName', $ServiceName)
$fileText = $fileText.Replace('TestServiceReplacementDisplayName', $ServiceDisplayName)
$fileText = $fileText.Replace('TestServiceReplacementDescription', $ServiceDescription)
$fileText = $fileText.Replace('TestServiceReplacementDependsOn', $ServiceDependsOn)
Add-Type $fileText `
-OutputAssembly $ServiceExecutablePath `
-OutputType WindowsApplication `
-ReferencedAssemblies @('System.ServiceProcess', 'System.Configuration.Install')
$addTypeParameters = @{
TypeDefinition = $fileText
OutputAssembly = $OutputPath
OutputType = 'WindowsApplication'
ReferencedAssemblies = @( 'System.ServiceProcess', 'System.Configuration.Install' )
}
$null = Add-Type @addTypeParameters
}
<#
.SYNOPSIS
Retrieves the path to the install utility.
Deletes the service with the given name and waits 5 seconds maximum for the service to be
deleted.
.PARAMETER Name
The name of the service to delete.
#>
function Get-InstallUtilPath
{
[CmdletBinding()]
param ()
if ($env:Processor_Architecture -ieq 'amd64')
{
$frameworkName = 'Framework64'
}
else
{
$frameworkName = 'Framework'
}
return Join-Path -Path (Resolve-Path "$env:WinDir\Microsoft.Net\$frameworkName\v4*") `
-ChildPath 'installUtil.exe'
}
<#
.SYNOPSIS
Removes a service.
.PARAMETER ServiceName
The name of the service to remove.
.PARAMETER ServiceExecutablePath
The path to the executable of the service to remove.
#>
function Remove-TestService
{
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[String]
$ServiceName,
[Parameter(Mandatory = $true)]
[String]
$ServiceExecutablePath
)
if (Get-Service -Name $ServiceName -ErrorAction SilentlyContinue)
{
$installUtility = Get-InstallUtilPath
& $installUtility /u $ServiceExecutablePath
}
Remove-Item $ServiceExecutablePath -Force -ErrorAction SilentlyContinue
Remove-Item *.InstallLog -Force -ErrorAction SilentlyContinue
Remove-Item $ServiceName -Force -Recurse -ErrorAction SilentlyContinue
}
function Get-InvalidArgumentRecord
function Remove-ServiceWithTimeout
{
[CmdletBinding()]
param
(
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[System.String]
$ErrorId,
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[System.String]
$ErrorMessage
[Parameter(Mandatory = $true)]
[ValidateNotNullorEmpty()]
[String]
$Name
)
$exception = New-Object -TypeName System.InvalidOperationException `
-ArgumentList $ErrorMessage
$errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation
$errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord `
-ArgumentList $exception, $ErrorId, $errorCategory, $null
return $errorRecord
Stop-Service -Name $Name
& 'sc.exe' 'delete' $Name
$serviceDeleted = $false
$start = [DateTime]::Now
while (-not $serviceDeleted -and ([DateTime]::Now - $start).TotalMilliseconds -lt 5000)
{
$service = Get-Service -Name $Name -ErrorAction 'SilentlyContinue'
if ($null -eq $service)
{
$serviceDeleted = $true
}
else
{
Start-Sleep -Seconds 1
}
}
}
Export-ModuleMember -Function `
New-ServiceBinary, `
New-TestService, `
Remove-TestService, `
Get-InvalidArgumentRecord
<#
.SYNOPSIS
Tests if the service with the specified name exists.
.PARAMETER Name
The name of the service.
#>
function Test-ServiceExists
{
[OutputType([Boolean])]
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[String]
$Name
)
$service = Get-Service -Name $Name -ErrorAction 'SilentlyContinue'
return $null -ne $service
}
Export-ModuleMember -Function @( 'New-ServiceExecutable', 'Remove-ServiceWithTimeout', 'Test-ServiceExists' )
File diff suppressed because it is too large Load Diff