Modules/xBitlocker.Common/xBitlocker.Common.psm1
<#
.SYNOPSIS Enables Bitlocker and Bitlocker features on the requested disk. .PARAMETER MountPoint The MountPoint name as reported in Get-BitLockerVolume. .PARAMETER PrimaryProtector The type of key protector that will be used as the primary key protector. .PARAMETER AdAccountOrGroup Specifies an account using the format Domain\User. .PARAMETER AdAccountOrGroupProtector Indicates that BitLocker uses an AD DS account as a protector for the volume encryption key. .PARAMETER AllowImmediateReboot Whether the computer can be immediately rebooted after enabling Bitlocker on an OS drive. Defaults to false. .PARAMETER AutoUnlock Whether volumes should be enabled for auto unlock using Enable-BitlockerAutoUnlock. .PARAMETER EncryptionMethod Indicates that BitLocker uses the TPM as a protector for the volume encryption key. .PARAMETER HardwareEncryption Indicates that the volume uses hardware encryption. .PARAMETER Password Specifies a secure string object that contains a password. .PARAMETER PasswordProtector Indicates that BitLocker uses a password as a protector for the volume encryption key. .PARAMETER Pin Specifies a secure string object that contains a PIN. .PARAMETER RecoveryKeyPath Specifies a path to a recovery key. .PARAMETER RecoveryKeyProtector Indicates that BitLocker uses a recovery key as a protector for the volume encryption key. .PARAMETER RecoveryPasswordProtector Indicates that BitLocker uses a recovery password as a protector for the volume encryption key. .PARAMETER Service Indicates that the system account for this computer unlocks the encrypted volume. .PARAMETER SkipHardwareTest Indicates that BitLocker does not perform a hardware test before it begins encryption. .PARAMETER StartupKeyPath Specifies a path to a startup key. .PARAMETER StartupKeyProtector Indicates that BitLocker uses a startup key as a protector for the volume encryption key. .PARAMETER TpmProtector Indicates that BitLocker uses the TPM as a protector for the volume encryption key. .PARAMETER UsedSpaceOnly Indicates that BitLocker does not encrypt disk space which contains unused data. .PARAMETER VerbosePreference Used to modify the default VerbosePreference for the function. #> function Enable-BitlockerInternal { # Suppressing this rule because $global:DSCMachineStatus is used to trigger a reboot. [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '')] <# Suppressing this rule because $global:DSCMachineStatus is only set, never used (by design of Desired State Configuration). #> [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $MountPoint, [Parameter(Mandatory = $true)] [ValidateSet('PasswordProtector', 'RecoveryPasswordProtector', 'StartupKeyProtector', 'TpmProtector')] [System.String] $PrimaryProtector, [Parameter()] [System.String] $AdAccountOrGroup, [Parameter()] [System.Boolean] $AdAccountOrGroupProtector, [Parameter()] [System.Boolean] $AllowImmediateReboot = $false, [Parameter()] [System.Boolean] $AutoUnlock = $false, [Parameter()] [ValidateSet('Aes128', 'Aes256')] [System.String] $EncryptionMethod, [Parameter()] [System.Boolean] $HardwareEncryption, [Parameter()] [System.Management.Automation.PSCredential] $Password, [Parameter()] [System.Boolean] $PasswordProtector, [Parameter()] [System.Management.Automation.PSCredential] $Pin, [Parameter()] [System.String] $RecoveryKeyPath, [Parameter()] [System.Boolean] $RecoveryKeyProtector, [Parameter()] [System.Boolean] $RecoveryPasswordProtector, [Parameter()] [System.Boolean] $Service, [Parameter()] [System.Boolean] $SkipHardwareTest, [Parameter()] [System.String] $StartupKeyPath, [Parameter()] [System.Boolean] $StartupKeyProtector, [Parameter()] [System.Boolean] $TpmProtector, [Parameter()] [System.Boolean] $UsedSpaceOnly, [Parameter()] $VerbosePreference ) Write-Verbose "Beginning processing of MountPoint: $($MountPoint)" $blv = Get-BitLockerVolume -MountPoint $MountPoint -ErrorAction SilentlyContinue if ($null -ne $blv) { if ($PSBoundParameters.ContainsKey('TpmProtector') -and $PrimaryProtector -ne 'TpmProtector') { throw 'If TpmProtector is used, it must be the PrimaryProtector.' } if ($PSBoundParameters.ContainsKey('Pin') -and !($PSBoundParameters.ContainsKey('TpmProtector'))) { throw 'A TpmProtector must be used if Pin is used.' } Add-MissingBitLockerKeyProtector @PSBoundParameters # Now enable Bitlocker with the primary key protector if ($blv.VolumeStatus -eq 'FullyDecrypted') { # First add non-key related parameters $params = @{} $params.Add('MountPoint', $MountPoint) if ($PSBoundParameters.ContainsKey('EncryptionMethod')) { $params.Add('EncryptionMethod', $EncryptionMethod) } if ($PSBoundParameters.ContainsKey('HardwareEncryption')) { $params.Add('HardwareEncryption', $HardwareEncryption) } if ($PSBoundParameters.ContainsKey('Service')) { $params.Add('Service', $Service) } if ($PSBoundParameters.ContainsKey('SkipHardwareTest')) { $params.Add('SkipHardwareTest', $SkipHardwareTest) } if ($PSBoundParameters.ContainsKey('UsedSpaceOnly')) { $params.Add('UsedSpaceOnly', $UsedSpaceOnly) } # Now add the primary protector $handledTpmAlready = $false # Deal with a couple one off cases if ($PSBoundParameters.ContainsKey('Pin')) { $handledTpmAlready = $true $params.Add('Pin', $Pin.Password) if ($PSBoundParameters.ContainsKey('StartupKeyProtector')) { $params.Add('TpmAndPinAndStartupKeyProtector', $true) $params.Add('StartupKeyPath', $StartupKeyPath) } else { $params.Add('TpmAndPinProtector', $true) } } if ($PSBoundParameters.ContainsKey('StartupKeyProtector') -and $PrimaryProtector -like 'TpmProtector' -and $handledTpmAlready -eq $false) { $handledTpmAlready = $true $params.Add('TpmAndStartupKeyProtector', $true) $params.Add('StartupKeyPath', $StartupKeyPath) } # Now deal with the standard primary protectors if ($PrimaryProtector -like 'PasswordProtector') { $params.Add('PasswordProtector', $true) $params.Add('Password', $Password.Password) } elseif ($PrimaryProtector -like 'RecoveryPasswordProtector') { $params.Add('RecoveryPasswordProtector', $true) } elseif ($PrimaryProtector -like 'StartupKeyProtector') { $params.Add('StartupKeyProtector', $true) $params.Add('StartupKeyPath', $StartupKeyPath) } elseif ($PrimaryProtector -like 'TpmProtector' -and $handledTpmAlready -eq $false) { $params.Add('TpmProtector', $true) } # Run Enable-Bitlocker Write-Verbose 'Running Enable-Bitlocker' $blv = Enable-Bitlocker @params # Check if the Enable succeeded if ($null -ne $blv) { # Only initiate reboot if this is an OS drive if ($blv.VolumeType -eq 'OperatingSystem') { $global:DSCMachineStatus = 1 if ($AllowImmediateReboot -eq $true) { Write-Verbose 'Forcing an immediate reboot of the computer in 30 seconds' Start-Sleep -Seconds 30 Restart-Computer -Force } } } else { throw "Failed to successfully enable Bitlocker on MountPoint $($MountPoint)" } } # Finally, enable AutoUnlock if requested if ($AutoUnlock -eq $true -and $blv.VolumeType -ne 'OperatingSystem' -and !$blv.AutoUnlockEnabled) { Enable-BitlockerAutoUnlock -MountPoint $MountPoint } } else { throw "Unable to find Bitlocker Volume associated with Mount Point '$($MountPoint)'" } } <# .SYNOPSIS Checks if any required secondary Key Protectors are missing, and adds them to the requested volume. .PARAMETER MountPoint The MountPoint name as reported in Get-BitLockerVolume. .PARAMETER PrimaryProtector The type of key protector that will be used as the primary key protector. .PARAMETER AdAccountOrGroup Specifies an account using the format Domain\User. .PARAMETER AdAccountOrGroupProtector Indicates that BitLocker uses an AD DS account as a protector for the volume encryption key. .PARAMETER AllowImmediateReboot Whether the computer can be immediately rebooted after enabling Bitlocker on an OS drive. Defaults to false. .PARAMETER AutoUnlock Whether volumes should be enabled for auto unlock using Enable-BitlockerAutoUnlock. .PARAMETER EncryptionMethod Indicates that BitLocker uses the TPM as a protector for the volume encryption key. .PARAMETER HardwareEncryption Indicates that the volume uses hardware encryption. .PARAMETER Password Specifies a secure string object that contains a password. .PARAMETER PasswordProtector Indicates that BitLocker uses a password as a protector for the volume encryption key. .PARAMETER Pin Specifies a secure string object that contains a PIN. .PARAMETER RecoveryKeyPath Specifies a path to a recovery key. .PARAMETER RecoveryKeyProtector Indicates that BitLocker uses a recovery key as a protector for the volume encryption key. .PARAMETER RecoveryPasswordProtector Indicates that BitLocker uses a recovery password as a protector for the volume encryption key. .PARAMETER Service Indicates that the system account for this computer unlocks the encrypted volume. .PARAMETER SkipHardwareTest Indicates that BitLocker does not perform a hardware test before it begins encryption. .PARAMETER StartupKeyPath Specifies a path to a startup key. .PARAMETER StartupKeyProtector Indicates that BitLocker uses a startup key as a protector for the volume encryption key. .PARAMETER TpmProtector Indicates that BitLocker uses the TPM as a protector for the volume encryption key. .PARAMETER UsedSpaceOnly Indicates that BitLocker does not encrypt disk space which contains unused data. .PARAMETER VerbosePreference Used to modify the default VerbosePreference for the function. #> function Add-MissingBitLockerKeyProtector { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $MountPoint, [Parameter(Mandatory = $true)] [ValidateSet('PasswordProtector', 'RecoveryPasswordProtector', 'StartupKeyProtector', 'TpmProtector')] [System.String] $PrimaryProtector, [Parameter()] [System.String] $AdAccountOrGroup, [Parameter()] [System.Boolean] $AdAccountOrGroupProtector, [Parameter()] [System.Boolean] $AllowImmediateReboot = $false, [Parameter()] [System.Boolean] $AutoUnlock = $false, [Parameter()] [ValidateSet('Aes128', 'Aes256')] [System.String] $EncryptionMethod, [Parameter()] [System.Boolean] $HardwareEncryption, [Parameter()] [System.Management.Automation.PSCredential] $Password, [Parameter()] [System.Boolean] $PasswordProtector, [Parameter()] [System.Management.Automation.PSCredential] $Pin, [Parameter()] [System.String] $RecoveryKeyPath, [Parameter()] [System.Boolean] $RecoveryKeyProtector, [Parameter()] [System.Boolean] $RecoveryPasswordProtector, [Parameter()] [System.Boolean] $Service, [Parameter()] [System.Boolean] $SkipHardwareTest, [Parameter()] [System.String] $StartupKeyPath, [Parameter()] [System.Boolean] $StartupKeyProtector, [Parameter()] [System.Boolean] $TpmProtector, [Parameter()] [System.Boolean] $UsedSpaceOnly, [Parameter()] $VerbosePreference ) if ($PSBoundParameters.ContainsKey('AdAccountOrGroupProtector') -and $PrimaryProtector -notlike 'AdAccountOrGroupProtector' -and !(Test-CollectionContainsKeyProtector -Type 'AdAccountOrGroup' -KeyProtectorCollection $blv.KeyProtector)) { Write-Verbose 'Adding AdAccountOrGroupProtector' Add-BitLockerKeyProtector -MountPoint $MountPoint -AdAccountOrGroupProtector -AdAccountOrGroup $AdAccountOrGroup } if ($PSBoundParameters.ContainsKey('PasswordProtector') -and $PrimaryProtector -notlike 'PasswordProtector' -and !(Test-CollectionContainsKeyProtector -Type 'Password' -KeyProtectorCollection $blv.KeyProtector)) { Write-Verbose 'Adding PasswordProtector' Add-BitLockerKeyProtector -MountPoint $MountPoint -PasswordProtector -Password $Password.Password } if ($PSBoundParameters.ContainsKey('RecoveryKeyProtector') -and $PrimaryProtector -notlike 'RecoveryKeyProtector' -and !(Test-CollectionContainsKeyProtector -Type 'ExternalKey' -KeyProtectorCollection $blv.KeyProtector)) { Write-Verbose 'Adding RecoveryKeyProtector' Add-BitLockerKeyProtector -MountPoint $MountPoint -RecoveryKeyProtector -RecoveryKeyPath $RecoveryKeyPath } if ($PSBoundParameters.ContainsKey('RecoveryPasswordProtector') -and $PrimaryProtector -notlike 'RecoveryPasswordProtector' -and !(Test-CollectionContainsKeyProtector -Type 'RecoveryPassword' -KeyProtectorCollection $blv.KeyProtector)) { Write-Verbose 'Adding RecoveryPasswordProtector' Add-BitLockerKeyProtector -MountPoint $MountPoint -RecoveryPasswordProtector } if ($PSBoundParameters.ContainsKey('StartupKeyProtector') -and $PrimaryProtector -notlike 'TpmProtector' -and $PrimaryProtector -notlike 'StartupKeyProtector' -and !(Test-CollectionContainsKeyProtector -Type 'ExternalKey' -KeyProtectorCollection $blv.KeyProtector)) { Write-Verbose 'Adding StartupKeyProtector' Add-BitLockerKeyProtector -MountPoint $MountPoint -StartupKeyProtector -StartupKeyPath $StartupKeyPath } } <# .SYNOPSIS Tests whether Bitlocker and the requested features have been enabled on the target disk. .PARAMETER MountPoint The MountPoint name as reported in Get-BitLockerVolume. .PARAMETER PrimaryProtector The type of key protector that will be used as the primary key protector. .PARAMETER AdAccountOrGroup Specifies an account using the format Domain\User. .PARAMETER AdAccountOrGroupProtector Indicates that BitLocker uses an AD DS account as a protector for the volume encryption key. .PARAMETER AllowImmediateReboot Whether the computer can be immediately rebooted after enabling Bitlocker on an OS drive. Defaults to false. .PARAMETER AutoUnlock Whether volumes should be enabled for auto unlock using Enable-BitlockerAutoUnlock. .PARAMETER EncryptionMethod Indicates that BitLocker uses the TPM as a protector for the volume encryption key. .PARAMETER HardwareEncryption Indicates that the volume uses hardware encryption. .PARAMETER Password Specifies a secure string object that contains a password. .PARAMETER PasswordProtector Indicates that BitLocker uses a password as a protector for the volume encryption key. .PARAMETER Pin Specifies a secure string object that contains a PIN. .PARAMETER RecoveryKeyPath Specifies a path to a recovery key. .PARAMETER RecoveryKeyProtector Indicates that BitLocker uses a recovery key as a protector for the volume encryption key. .PARAMETER RecoveryPasswordProtector Indicates that BitLocker uses a recovery password as a protector for the volume encryption key. .PARAMETER Service Indicates that the system account for this computer unlocks the encrypted volume. .PARAMETER SkipHardwareTest Indicates that BitLocker does not perform a hardware test before it begins encryption. .PARAMETER StartupKeyPath Specifies a path to a startup key. .PARAMETER StartupKeyProtector Indicates that BitLocker uses a startup key as a protector for the volume encryption key. .PARAMETER TpmProtector Indicates that BitLocker uses the TPM as a protector for the volume encryption key. .PARAMETER UsedSpaceOnly Indicates that BitLocker does not encrypt disk space which contains unused data. .PARAMETER VerbosePreference Used to modify the default VerbosePreference for the function. #> function Test-BitlockerEnabled { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [System.String] $MountPoint, [Parameter(Mandatory = $true)] [ValidateSet('PasswordProtector', 'RecoveryPasswordProtector', 'StartupKeyProtector', 'TpmProtector')] [System.String] $PrimaryProtector, [Parameter()] [System.String] $AdAccountOrGroup, [Parameter()] [System.Boolean] $AdAccountOrGroupProtector, [Parameter()] [System.Boolean] $AllowImmediateReboot = $false, [Parameter()] [System.Boolean] $AutoUnlock = $false, [Parameter()] [ValidateSet('Aes128', 'Aes256')] [System.String] $EncryptionMethod, [Parameter()] [System.Boolean] $HardwareEncryption, [Parameter()] [System.Management.Automation.PSCredential] $Password, [Parameter()] [System.Boolean] $PasswordProtector, [Parameter()] [System.Management.Automation.PSCredential] $Pin, [Parameter()] [System.String] $RecoveryKeyPath, [Parameter()] [System.Boolean] $RecoveryKeyProtector, [Parameter()] [System.Boolean] $RecoveryPasswordProtector, [Parameter()] [System.Boolean] $Service, [Parameter()] [System.Boolean] $SkipHardwareTest, [Parameter()] [System.String] $StartupKeyPath, [Parameter()] [System.Boolean] $StartupKeyProtector, [Parameter()] [System.Boolean] $TpmProtector, [Parameter()] [System.Boolean] $UsedSpaceOnly, [Parameter()] $VerbosePreference ) $blv = Get-BitLockerVolume -MountPoint $MountPoint -ErrorAction SilentlyContinue if ($null -eq $blv) { Write-Verbose "Unable to locate MountPoint: $($MountPoint)" return $false } elseif ($blv.VolumeStatus -eq 'FullyDecrypted') { Write-Verbose "MountPoint: $($MountPoint) Not Encrypted" return $false } elseif ($null -eq $blv.KeyProtector -or $blv.KeyProtector.Count -eq 0) { Write-Verbose "No key protectors on MountPoint: $($MountPoint)" return $false } elseif ($AutoUnlock -eq $true -and $blv.AutoUnlockEnabled -ne $true -and $blv.VolumeType -ne 'OperatingSystem') { Write-Verbose "AutoUnlock is not enabled for MountPoint: $($MountPoint)" return $false } else { if ($PSBoundParameters.ContainsKey('AdAccountOrGroupProtector') -and !(Test-CollectionContainsKeyProtector -Type 'AdAccountOrGroup' -KeyProtectorCollection $blv.KeyProtector)) { Write-Verbose "MountPoint '$($MountPoint) 'does not have AdAccountOrGroupProtector (AdAccountOrGroup)" return $false } if ($PSBoundParameters.ContainsKey('PasswordProtector') -and !(Test-CollectionContainsKeyProtector -Type 'Password' -KeyProtectorCollection $blv.KeyProtector)) { Write-Verbose "MountPoint '$($MountPoint) 'does not have PasswordProtector (Password)" return $false } if ($PSBoundParameters.ContainsKey('Pin') -and !(Test-CollectionContainsKeyProtector -Type 'TpmPin' -KeyProtectorCollection $blv.KeyProtector -StartsWith $true)) { Write-Verbose "MountPoint '$($MountPoint) 'does not have TpmPin assigned." return $false } if ($PSBoundParameters.ContainsKey('RecoveryKeyProtector') -and !(Test-CollectionContainsKeyProtector -Type 'ExternalKey' -KeyProtectorCollection $blv.KeyProtector)) { Write-Verbose "MountPoint '$($MountPoint) 'does not have RecoveryKeyProtector (ExternalKey)" return $false } if ($PSBoundParameters.ContainsKey('RecoveryPasswordProtector') -and !(Test-CollectionContainsKeyProtector -Type 'RecoveryPassword' -KeyProtectorCollection $blv.KeyProtector)) { Write-Verbose "MountPoint '$($MountPoint) 'does not have RecoveryPasswordProtector (RecoveryPassword)" return $false } if ($PSBoundParameters.ContainsKey('StartupKeyProtector')) { if ($PrimaryProtector -notlike 'TpmProtector') { if (!(Test-CollectionContainsKeyProtector -Type 'ExternalKey' -KeyProtectorCollection $blv.KeyProtector)) { Write-Verbose "MountPoint '$($MountPoint) 'does not have StartupKeyProtector (ExternalKey)" return $false } } else # TpmProtector is primary { if (!(Test-CollectionContainsKeyProtector -Type 'Tpm' -KeyProtectorCollection $blv.KeyProtector -StartsWith $true) -and !(Test-CollectionContainsKeyProtector -Type 'StartupKey' -KeyProtectorCollection $blv.KeyProtector -Contains $true)) { Write-Verbose "MountPoint '$($MountPoint) 'does not have TPM + StartupKey protector." return $false } } } if ($PSBoundParameters.ContainsKey('TpmProtector') -and !(Test-CollectionContainsKeyProtector -Type 'Tpm' -KeyProtectorCollection $blv.KeyProtector -StartsWith $true)) { Write-Verbose "MountPoint '$($MountPoint) 'does not have TpmProtector" return $false } } return $true } <# .SYNOPSIS Tests whether the requires prerequisite features for Bitlocker are installed, and throws an exception if they are not. #> function Assert-HasPrereqsForBitlocker { [CmdletBinding()] param () $hasAllPreReqs = $true $blFeature = Get-WindowsFeature BitLocker $blAdminToolsFeature = Get-WindowsFeature RSAT-Feature-Tools-BitLocker $blAdminToolsRemoteFeature = Get-WindowsFeature RSAT-Feature-Tools-BitLocker-RemoteAdminTool if ($blFeature.InstallState -ne 'Installed') { $hasAllPreReqs = $false Write-Error 'The Bitlocker feature needs to be installed before the xBitlocker module can be used' } if ($blAdminToolsFeature.InstallState -ne 'Installed') { $hasAllPreReqs = $false Write-Error 'The RSAT-Feature-Tools-BitLocker feature needs to be installed before the xBitlocker module can be used' } if ($blAdminToolsRemoteFeature.InstallState -ne 'Installed' -and (Get-OSEdition) -notmatch 'Core') { $hasAllPreReqs = $false Write-Error 'The RSAT-Feature-Tools-BitLocker-RemoteAdminTool feature needs to be installed before the xBitlocker module can be used' } if ($hasAllPreReqs -eq $false) { throw 'Required Bitlocker features need to be installed before xBitlocker can be used' } } <# .SYNOPSIS Tests whether the KeyProtectorCollection returned from Get-BitlockerVolume contains the specified KeyProtector type. .PARAMETER Type The KeyProtector type to look for in the KeyProtectorCollection. .PARAMETER KeyProtectorCollection The KeyProtectorCollection to look for the KeyProtector type within. .PARAMETER StartsWith Whether to look for a KeyProtector type that only StartsWith the input Type. .PARAMETER Contains Whether to look for a KeyProtector type that only Contains the input Type. #> function Test-CollectionContainsKeyProtector { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [System.String] $Type, [Parameter()] [System.Object[]] $KeyProtectorCollection, [Parameter()] [System.Boolean] $StartsWith = $false, [Parameter()] [System.Boolean] $Contains = $false ) if ($null -ne $KeyProtectorCollection) { foreach ($keyProtector in $KeyProtectorCollection) { if ($keyProtector.KeyProtectorType -eq $Type) { return $true } elseif ($StartsWith -eq $true -and $keyProtector.KeyProtectorType.ToString().StartsWith($Type)) { return $true } elseif ($Contains -eq $true -and $keyProtector.KeyProtectorType.ToString().Contains($Type)) { return $true } } } return $false } <# .SYNOPSIS Takes $PSBoundParameters from another function and adds in the keys and values from the given Hashtable. .PARAMETER PSBoundParametersIn The $PSBoundParameters Hashtable from the calling function. .PARAMETER ParamsToAdd A Hashtable containing new Key/Value pairs to add to the given PSBoundParametersIn Hashtable. #> function Add-ToPSBoundParametersFromHashtable { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.Object] $PSBoundParametersIn, [Parameter()] [System.Collections.Hashtable] $ParamsToAdd ) foreach ($key in $ParamsToAdd.Keys) { if (!($PSBoundParametersIn.ContainsKey($key))) # Key doesn't exist, so add it with value { $PSBoundParametersIn.Add($key, $ParamsToAdd[$key]) | Out-Null } else # Key already exists, so just replace the value { $PSBoundParametersIn[$key] = $ParamsToAdd[$key] } } } <# .SYNOPSIS Takes $PSBoundParameters from another function, and modifies it based on the contents of the ParamsToRemove or ParamsToKeep parameters. If ParamsToRemove is specified, it will remove each param. If ParamsToKeep is specified, everything but those params will be removed. .PARAMETER PSBoundParametersIn The $PSBoundParameters Hashtable from the calling function. .PARAMETER ParamsToKeep A String array containing the list of parameter names to keep in the given PSBoundParametersIn HashTable. .PARAMETER ParamsToRemove A String array containing the list of parameter names to remove in the given PSBoundParametersIn HashTable. #> function Remove-FromPSBoundParametersUsingHashtable { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.Object] $PSBoundParametersIn, [Parameter(Mandatory = $true, ParameterSetName = 'KeepParameters')] [System.String[]] $ParamsToKeep, [Parameter(Mandatory = $true, ParameterSetName = 'RemoveParameters')] [System.String[]] $ParamsToRemove ) if ($ParamsToKeep.Count -gt 0) { $ParamsToKeep = $ParamsToKeep.ToLower() foreach ($key in $PSBoundParametersIn.Keys) { if (!($ParamsToKeep.Contains($key.ToLower()))) { $ParamsToRemove += $key } } } if ($ParamsToRemove.Count -gt 0) { foreach ($param in $ParamsToRemove) { $null = $PSBoundParametersIn.Remove($param) } } } <# .SYNOPSIS Returns the OS edition we are currently running on #> function Get-OSEdition { [CmdletBinding()] [OutputType([System.String])] param () return (Get-ItemProperty -Path 'HKLM:/software/microsoft/windows nt/currentversion' -Name InstallationType).InstallationType } Export-ModuleMember -Function * |