DscResources/Carbon_IniFile/Carbon_IniFile.psm1
# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. $psModulesPath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\Modules' -Resolve Import-Module -Name (Join-Path -Path $psModulesPath -ChildPath 'Carbon' -Resolve) ` -Function @('Remove-CIniEntry', 'Set-CIniEntry', 'Split-CIni') function Get-TargetResource { [CmdletBinding()] [OutputType([Collections.Hashtable])] param ( [Parameter(Mandatory=$true)] [String] # The path to the file to update. $Path, [String] # The section of the INI file where the setting can be found. $Section, [Parameter(Mandatory=$true)] [String] # The name of the INI setting. $Name, [String] # The value of the INI setting. $Value, [switch] # The INI file being modified is case-sensitive. $CaseSensitive, [switch] # If `$true`, creates the INI file if it doesn't exist. $Force, [ValidateSet("Present","Absent")] [String] # Create or delete the INI setting? $Ensure = 'Present' ) Set-StrictMode -Version 'Latest' $ini = @{ } if( (Test-Path -Path $Path -PathType Leaf) ) { $ini = Split-CIni -Path $Path -AsHashtable -CaseSensitive:$CaseSensitive } else { if( -not $Force ) { Write-Error ('INI file ''{0}'' not found. Set the `Force` property to `true` to create this INI file when it doesn''t exist.' -f $Path) return } } $key = $Name if( $Section ) { $key = '{0}.{1}' -f $Section,$Name } $currentValue = $null $Ensure = 'Absent' if( $ini.ContainsKey( $key ) ) { $currentValue = $ini[$key].Value $Ensure = 'Present'; } @{ Path = $Path; Section = $Section; Name = $Name; Value = $currentValue; CaseSensitive = [bool]$CaseSensitive; Force = [bool]$Force Ensure = $Ensure; } } function Set-TargetResource { <# .SYNOPSIS DSC resource for managing settings in INI files. .DESCRIPTION The `Carbon_IniFile` resource sets or removes settings from INI files. `Carbon_IniFile` is new in Carbon 2.0. .LINK Remove-CIniEntry .LINK Set-CIniEntry .LINK Split-CIni .EXAMPLE > Demonstrates how to create/set a setting in sectionless INI file. Carbon_IniFile SetNpmPrefix { Path = 'C:\Program Files\nodejs\node_modules\npm\npmrc' Name = 'prefix'; Value = 'C:\node-global-modules'; CaseSensitive = $true; } In this case, we're setting the `prefix` NPM setting to `C:\node-global-modules` in the `C:\Program Files\nodejs\node_modules\npm\npmrc` file. It is expected this file exists and you'll get an error if it doesn't. NPM configuration files are case-sensitive, so the `CaseSensitive` property is set to `$true`. This line will be added to the INI file: prefix = C:\node-global-modules .EXAMPLE > Demonstrates how to create/set a setting in an INI file with sections. Carbon_IniFile SetBuildUserMercurialUsername { Path = 'C:\Users\BuildUser\mercurial.ini' Section = 'ui'; Name = 'username'; Force = $true; Value = 'Build User <builduser@example.com>'; } In this case, we're setting the 'username' setting in the 'ui' section of the `C:\Users\BuildUser\mercurial.ini` file to `Build User <builduser@example.com>`. Since the `$Force` property is `$true`, if the file doesn't exist, it will be created. These lines will be added to the ini file: [ui] username = Build User <builduser@example.com> .EXAMPLE > Demonstrates how to remove a setting from a case-sensitive INI file. Carbon_IniFile RemoveNpmPrefix { Path = 'C:\Program Files\nodejs\node_modules\npm\npmrc' Name = 'prefix'; CaseSensitive = $true; Ensure = 'Absent'; } .EXAMPLE > Demonstrates how to remove a setting from an INI file that organizes settings into sections. Carbon_IniFile RemoveBuildUserMercurialUsername { Path = 'C:\Users\BuildUser\mercurial.ini' Section = 'ui'; Name = 'username'; Ensure = 'Absent'; } #> [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [String] # The path to the file to update. $Path, [String] # The section of the INI file where the setting can be found. $Section, [Parameter(Mandatory=$true)] [String] # The name of the INI setting. $Name, [String] # The value of the INI setting. $Value, [switch] # The INI file being modified is case-sensitive. $CaseSensitive, [switch] # If `$true`, creates the INI file if it doesn't exist. $Force, [ValidateSet("Present","Absent")] [String] # Create or delete the INI setting? $Ensure = 'Present' ) Set-StrictMode -Version 'Latest' $resource = Get-TargetResource -Path $Path -Section $Section -Name $Name -Force:$Force -CaseSensitive:$CaseSensitive if( -not $resource ) { return } if( -not (Test-Path -Path $Path -PathType Leaf) -and $Force ) { New-Item -Path $Path -ItemType 'File' -Force | Out-Null } $fullName = $Name if( $Section ) { $fullName = '{0}.{1}' -f $Section,$Name } if( $resource.Ensure -eq 'Present' -and $Ensure -eq 'Absent' ) { Write-Verbose ('{0}: {1}: removing' -f $Path,$fullName) Remove-CIniEntry -Path $Path -Section $Section -Name $Name -CaseSensitive:$CaseSensitive return } if( $Ensure -eq 'Present' ) { Write-Verbose ('{0}: {1}: setting' -f $Path,$fullName) Set-CIniEntry -Path $Path -Section $Section -Name $Name -Value $Value -CaseSensitive:$CaseSensitive } } function Test-TargetResource { [CmdletBinding()] [OutputType([bool])] param ( [Parameter(Mandatory=$true)] [String] # The path to the file to update. $Path, [String] # The section of the INI file where the setting can be found. $Section, [Parameter(Mandatory=$true)] [String] # The name of the INI setting. $Name, [String] # The value of the INI setting. $Value, [switch] # The INI file being modified is case-sensitive. $CaseSensitive, [switch] # If `$true`, creates the INI file if it doesn't exist. $Force, [ValidateSet("Present","Absent")] [String] # Create or delete the INI setting? $Ensure = 'Present' ) Set-StrictMode -Version 'Latest' $resource = Get-TargetResource -Path $Path -Section $Section -Name $Name -Force:$Force if( -not $resource ) { return $false } $fullName = $Name if( $Section ) { $fullName = '{0}.{1}' -f $Section,$Name } if( $Ensure -eq 'Present' ) { $result = ($resource.Value -eq $Value) if( $CaseSensitive ) { $result = ($resource.Value -ceq $Value) } if( $result ) { Write-Verbose ('{0}: {1}: current value unchanged' -f $Path,$fullName) } else { Write-Verbose ('{0}: {1}: current value differs' -f $Path,$fullName) } } else { $result = ($resource.Ensure -eq 'Absent') if( $result ) { Write-Verbose ('{0}: {1}: not found' -f $Path,$fullName) } else { Write-Verbose ('{0}: {1}: found' -f $Path,$fullName) } } return $result } Export-ModuleMember -Function '*-TargetResource' |