Public/Set-PowercfgSettings.ps1
<#
.Synopsis Sets PowerCfg settings .DESCRIPTION Set setting values to PowerCfg or pipe settings from Get-PowercfgSettings and set values. .EXAMPLE Set-PowercfgSettings -ComputerName <computername> -PowerScheme 'High Performance' -SubGroup display -setting 'Turn off' -SetAC -SetDC -Value 120 Sets "Turn off display after" from the "Display" SubGroup to 120. .EXAMPLE Get-PowerCfgSettings -SubGroup display -Setting "Display Brightness" | Set-PowerCfgSettings -SetAC -Value 400 -Force Gets the "Display Brightness" setting from the "Display" Subgroup and passes it to Set-PowerCfgSettings where it's AC value is set to 400. .INPUTS ComputerName PowerScheme SubGroup Setting [PowerCfgSetting] .OUTPUTS [PowerCfgSetting] .NOTES Relies on WinRM to use Invoke-Command when targeting remote computers. .FUNCTIONALITY Configures powercfg #> function Set-PowercfgSettings { [CmdletBinding( SupportsShouldProcess, ConfirmImpact="High", DefaultParameterSetName="Manual" )] [Alias("spcs")] Param ( [Parameter( ValueFromPipelineByPropertyName, ParameterSetName="Pipeline" )] [Parameter( ValueFromPipeline=$false, ParameterSetName="Manual" )] [ValidateNotNullOrEmpty()] [Alias("CN")] [String] $ComputerName, [Parameter( ParameterSetName="Manual", Position=0 )] [String] $PowerScheme, [Parameter( ParameterSetName="Manual", Position=1, Mandatory )] [String] $SubGroup, [Parameter( ParameterSetName="Manual", Position=2, Mandatory )] [String] $Setting, [Parameter( Mandatory, Position=3 )] [int] $Value, [Parameter( DontShow, ValueFromPipeline, ParameterSetName="Pipeline" )] [PowerCfgSetting] $p_Setting, [Switch] $SetAC, [Switch] $SetDC, [Switch] $Force#, #[Switch] #$PassThru ) Begin{ if(!($SetAC -or $SetDC)){ $PSCmdlet.ThrowTerminatingError( [System.Management.Automation.ErrorRecord]::new( [System.ArgumentNullException]::new( "-SetAC, -SetDC", "Setting type not specified. Use one or both." ), "PowerScheme.TypeSetting", [System.Management.Automation.ErrorCategory]::NotSpecified, "" ) ) } } Process { # Computername handler first in Process block for pipeline compatibility if($ComputerName){ Try{ $cfg = Invoke-Command $ComputerName { powercfg /l } } Catch{ throw } } Else{ $cfg = powercfg /l } # Parse out the heading $cfg = $cfg[3..(($cfg.count)-1)] # Manual entry (no pipeline) requires dedicated string parsing as if we were using Get-PowercfgSetting. if($PSCmdlet.ParameterSetName -eq "Manual"){ # Get PowerScheme if(!$PowerScheme){ $cfg = $cfg.where({$_ -match "(.+)\s{1}\*$"}) } $schemeTable = @() foreach($scheme in $cfg){ $null = $scheme -match "\((.+)\)";$name = $Matches[1] $null = $scheme -match "\s{1}(\S+\d+\S+)\s{1}";$guid = $Matches[1] if($scheme -match "\*$"){$active = $true} elseif($scheme -notmatch "\*$"){$active = $false} $temp = [PSCustomObject]@{ Name=$name Guid=[Guid]$guid Active=[bool]$active } [PowerCfgPlan]$temp = $temp $schemeTable += $temp $null = Remove-Variable temp -Force } if(!$PowerScheme){ $PowerScheme = $schemeTable.Name } $selPowerScheme = ($schemeTable.Where({$_.Name -like "*$PowerScheme*"}).Guid.Guid) if($selPowerScheme.count -gt 1){ $PSCmdlet.ThrowTerminatingError( [System.Management.Automation.ErrorRecord]::new( [System.ArgumentOutOfRangeException]::new( "-PowerScheme", "$PowerScheme matches multiple values." ), "PowerScheme.>1", [System.Management.Automation.ErrorCategory]::LimitsExceeded, $PowerScheme ) ) } # Get Power Plan if($ComputerName){ Try{ $QueryScheme = Invoke-Command $ComputerName { powercfg /q $using:selPowerScheme } } Catch{ throw } } Else{ $QueryScheme = powercfg /q $selPowerScheme } # The error if a bad PowerScheme name is entered. if ((!$?) -or ($null -eq $selPowerScheme)) { $PSCmdlet.ThrowTerminatingError( [System.Management.Automation.ErrorRecord]::new( [System.ArgumentException]::new( "$PowerScheme not found", "-PowerScheme" ), "PowerScheme.notfound", [System.Management.Automation.ErrorCategory]::ObjectNotFound, $PowerScheme ) ) } # Get SubGroup $subgroups = (($QueryScheme) -match "SubGroup GUID: ").TrimStart().Trim() # $subgroups being an array doesn't assign matches to $Matches, but instead returns the result. # We forced a boolean return and then run it again to collect the string output. if([bool]($subgroups -match $SubGroup)){ $p_SubGroup = $subgroups -match $SubGroup } else{ $PSCmdlet.ThrowTerminatingError( [System.Management.Automation.ErrorRecord]::new( [System.ArgumentException]::new( "$SubGroup not found", "-SubGroup" ), "SubGroup.notfound", [System.Management.Automation.ErrorCategory]::ObjectNotFound, $SubGroup ) ) # The error for if a bad SubGroup name is specified. } # Get Setting $settings = (($QueryScheme) -match "Power Setting Guid: ").TrimStart().Trim() if([bool]($settings -match $Setting)){ Remove-Variable p_Setting -Force $p_Setting = $settings -match $Setting } else{ $PSCmdlet.ThrowTerminatingError( [System.Management.Automation.ErrorRecord]::new( [System.ArgumentException]::new( "$Setting not found", "-Setting" ), "Setting.notfound", [System.Management.Automation.ErrorCategory]::ObjectNotFound, $Setting ) ) # The error for if a bad SubGroup name is specified. } # Get GUIDs $null = $p_SubGroup[0] -match "\s{1}(\S+\d+\S+)\s{1}";$Groupguid = $Matches[1] $null = $p_Setting[0] -match "\s{1}(\S+\d+\S+)\s{1}";$Settingguid = $Matches[1] # Get Names $null = $p_SubGroup[0] -match "\((.+)\)";$Groupname = $Matches[1] $null = $p_Setting[0] -match "\((.+)\)";$Settingname = $Matches[1] # $selPowerScheme, $Groupguid, $Settingguid # Until renamed, these are the vars for Plan, SubGroup, and Setting $commands = @() if($ComputerName){ $Target = "$ComputerName -> $Groupname -> $Settingname" } else{ $Target = "$Groupname -> $Settingname" } if($SetAC){ if(($Force) -or ($pscmdlet.ShouldProcess($Target, "Set AC value to $value"))){ $commands += {powercfg /setacvalueindex ($selPowerScheme) ($Groupguid) ($Settingguid) $value} } } if($SetDC){ if(($Force) -or ($PSCmdlet.ShouldProcess($Target, "Set DC value to $value"))){ $commands += {powercfg /setdcvalueindex ($selPowerScheme) ($Groupguid) ($Settingguid) $value} } } $PassThru = @{PowerScheme = $PowerScheme;SubGroup = $Groupname;Setting = $Settingname} if(!($ComputerName)){ $commands | ForEach-Object{ & $_ Get-PowercfgSettings @PassThru } } else{ $PassThru += @{ComputerName = $ComputerName} Try{ Invoke-Command -ComputerName $ComputerName { param( $selPowerScheme, $Groupguid, $Settingguid, $Value ) if($using:SetDC){ & powercfg /setdcvalueindex $selPowerScheme $Groupguid $Settingguid $Value } if($using:SetAC){ & powercfg /setacvalueindex $selPowerScheme $Groupguid $Settingguid $Value } } -ArgumentList $selPowerScheme,$Groupguid,$Settingguid,$Value Get-PowercfgSettings @PassThru } Catch{ throw } } } # Pipeline entry - where a [PowerCfgSetting] is sent over, it holds all necessary arguments for local execution. if($PSCmdlet.ParameterSetName -eq "Pipeline"){ if($p_Setting.count -gt 1){ $PSCmdlet.ThrowTerminatingError( [System.Management.Automation.ErrorRecord]::new( [System.ArgumentOutOfRangeException]::new( "Multiple Settings Found. Specify One." ), "Setting.>1", [System.Management.Automation.ErrorCategory]::NotSpecified, "" ) ) } # Currently, not handling multiple settings. Plan to add piping entire subgroups and plans. # Breaking up the variable properties into their own vars $p_PowerScheme = $p_Setting.Plan $p_SubGroup = $p_Setting.SubGroup $commands = @() if($ComputerName){ $Target = "$ComputerName -> $($p_SubGroup.Name) -> $($p_Setting.Name)" } else{ $Target = "$($p_SubGroup.Name) -> $($p_Setting.Name)" } if($SetAC){ if(($Force) -or ($pscmdlet.ShouldProcess($Target, "Set AC value to $value"))){ $commands += {powercfg /setacvalueindex $p_PowerScheme.guid.guid $p_SubGroup.guid.guid $p_Setting.guid.guid $value} } } if($SetDC){ if(($Force) -or ($PSCmdlet.ShouldProcess($Target, "Set DC value to $value"))){ $commands += {powercfg /setdcvalueindex $p_PowerScheme.guid.guid $p_SubGroup.guid.guid $p_Setting.guid.guid $value} } } $PassThru = @{PowerScheme = $p_PowerScheme.name;SubGroup = $p_SubGroup.name;Setting = $p_Setting.name} if(!($ComputerName)){ $commands | ForEach-Object{ & $_ Get-PowercfgSettings @PassThru } } else{ $PassThru += @{ComputerName = $ComputerName} Try{ Invoke-Command -ComputerName $ComputerName { param( $p_PowerScheme, $p_SubGroup, $p_Setting, $Value ) if($using:SetDC){ & powercfg /setdcvalueindex $p_PowerScheme $p_SubGroup $p_Setting $Value } if($using:SetAC){ & powercfg /setacvalueindex $p_PowerScheme $p_SubGroup $p_Setting $Value } } -ArgumentList $p_PowerScheme.guid.guid,$p_SubGroup.guid.guid,$p_Setting.guid.guid,$Value Get-PowercfgSettings @PassThru } Catch{ throw } } } } End { } } |