[{"content":"Earlier this year, I wrote about how to manage Dell BIOS passwords using PowerShell. The method described in that post uses the DellBIOSProvider PowerShell module. This method works, but I was not completely satisfied with it, as the PowerShell module needs to be downloaded and installed on every system the script runs on.\nThankfully, Dell recently released a technical whitepaper documenting WMI classes that can be used to directly modify BIOS settings without needing an outside program or PowerShell module. This allowed me to create a new version of the Dell BIOS Settings Management script that does not require any additional content to function.\nOne caveat for this new method is the WMI classes are only supported on Dell hardware released to market after calendar year 2018. Because of this, older Dell hardware will still require the use of the DellBIOSProvider PowerShell module.\nThe script can be downloaded from my GitHub: https://github.com/ConfigJon/Firmware-Management/blob/master/Dell/Manage-DellBiosPasswords-WMI.ps1\nDell, WMI, and PowerShell Dell provides a WMI interface that can be used for querying and modifying BIOS settings on their hardware models (only applies to models released after calendar year 2018). This means that we can use PowerShell to directly view and edit BIOS settings without the need for a vendor specific program. This script uses 2 of the Dell provided WMI classes.\nThe first WMI class is PasswordObject. It is located in the root\\dcim\\sysman\\wmisecurity namespace. This class is used to return the current BIOS password status.\n#Connect to the PasswordObject WMI class $Password = Get-CimInstance -Namespace root\\dcim\\sysman\\wmisecurity -ClassName PasswordObject #Check the status of the admin password $Password | Where-Object NameId -EQ \u0026#34;Admin\u0026#34; | Select-Object -ExpandProperty IsPasswordSet #Check the status of the system password $Password | Where-Object NameId -EQ \u0026#34;System\u0026#34; | Select-Object -ExpandProperty IsPasswordSet The second WMI class is SecurityInterface. It is located in the root\\dcim\\sysman\\wmisecurity namespace. This class contains a method called SetNewPassword which is used to set and modify BIOS passwords.\n#Connect to the SecurityInterface WMI class $SecurityInterface = Get-WmiObject -Namespace root\\dcim\\sysman\\wmisecurity -Class SecurityInterface #Set the admin password when no password is currently set $SecurityInterface.SetNewPassword(0,0,0,\u0026#34;Admin\u0026#34;,\u0026#34;\u0026#34;,\u0026#34;NewPassword\u0026#34;) #Set the system password when no password is currently set $SecurityInterface.SetNewPassword(0,0,0,\u0026#34;System\u0026#34;,\u0026#34;\u0026#34;,\u0026#34;NewPassword\u0026#34;) #Change an existing admin password $SecurityInterface.SetNewPassword(1,$Bytes.Length,$Bytes,\u0026#34;Admin\u0026#34;,\u0026#34;CurrentPassword\u0026#34;,\u0026#34;NewPassword\u0026#34;) #Clear an existing admin password $SecurityInterface.SetNewPassword(1,$Bytes.Length,$Bytes,\u0026#34;Admin\u0026#34;,\u0026#34;CurrentPassword\u0026#34;,\u0026#34;\u0026#34;) BIOS Password Encoding The above information contains examples for modifying the BIOS with and without an existing BIOS password. When a BIOS password is set, it must first be encoded before it can be passed to a method.\n$Password = \u0026#34;ExamplePass\u0026#34; $Encoder = New-Object System.Text.UTF8Encoding $Bytes = $Encoder.GetBytes($Password) Each of the methods used to modify BIOS settings starts with 3 arguments. The 3 arguments are:\nThe type of text The length of the byte array The byte array containing the encoded password When no password is set, these arguments are set to 0,0,0. The type of text is 0 (None), the length of the byte array is 0, and the byte array itself is 0.\nWhen a password is set, these arguments are set to 1,$Bytes.Length,$Bytes. The type of text is 1 (plain text), the length of the byte array is set to $Bytes.Length, and the byte array is $Bytes.\nStatus Codes For reference, when calling the SetNewPassword method, the possible status codes are:\n0 - Success 1 - Failed 2 - Invalid Parameter 3 - Access Denied 4 - Not Supported 5 - Memory Error 6 - Protocol Error For more detailed information on the Dell WMI interface, refer to the official documentation. http://downloads.dell.com/manuals/common/dell-agentless-client-manageability.pdf\nManage-DellBiosPasswords-WMI.ps1 This script takes the basic commands we just looked at and adds logic to allow for a more automated password management process. The script accepts parameters that tell it which actions to perform.\nAdminSet – Set a new admin password or change an existing admin password AdminClear – Clear an existing admin password SystemSet – Set a new system password or change an existing system password SystemClear – Clear an existing system password There are also parameters that are used to specify the new and old BIOS passwords.\nAdminPassword – The current admin password or password to be set OldAdminPassword – The old admin password(s) to be changed. Multiple old passwords can be specified (separated by a comma). SystemPassword – The current system password or password to be set OldSystemPassword – The old system password(s) to be changed. Multiple old passwords can be specified (separated by a comma). By default, if the script fails to perform any of these actions, it will display a message box on the screen and exit with an error code. This can be useful in a task sequence scenario where you may not want a system to continue with the task sequence if the BIOS password is not set correctly. However, if you want the script to be completely silent, there are a few parameters that can be set.\nNoUserPrompt – Suppress all user prompts ContinueOnError – Ignore any errors caused by changing or clearing passwords When the script runs, it will write to a log file. By default, this log file will be named Manage-DellBiosPasswords-WMI.Log. If the script is being run during a task sequence, the log file will be located in the _SMSTSLogPath. Otherwise, the log file will be located in ProgramData\\ConfigJonScripts\\Dell. The log file name and path can be changed using the LogFile parameter. Note that the log file path will always be set to _SMSTSLogPath when run during a task sequence.\nExamples The script can be run as a standalone script in Windows, or as a part of a Configuration Manager task sequence. It can also be run in the full Windows OS or in WinPE.\nHere are a few examples of calling the script from a PowerShell prompt in Windows.\n#Set a new admin password Manage-DellBiosPasswords-WMI.ps1 -AdminSet -AdminPassword \u0026lt;String\u0026gt; #Set or change a admin password Manage-DellBiosPasswords-WMI.ps1 -AdminSet -AdminPassword \u0026lt;String\u0026gt; -OldAdminPassword \u0026lt;String1\u0026gt;,\u0026lt;String2\u0026gt;,\u0026lt;String3\u0026gt; #Set a new admin password and set a new system password Manage-DellBiosPasswords-WMI.ps1 -AdminSet -SystemSet -AdminPassword \u0026lt;String\u0026gt; -SystemPassword \u0026lt;String\u0026gt; #Clear an existing admin password Manage-DellBiosPasswords-WMI.ps1 -AdminClear -OldAdminPassword \u0026lt;String1\u0026gt;,\u0026lt;String2\u0026gt;,\u0026lt;String3\u0026gt; Here is a basic example of calling the script during a task sequence. This is likely one of the most common ways the script would be called in a task sequence. In this example the admin password will be set if it doesn’t exist, and it will be changed if it does already exist.\n-AdminSet -AdminPassword %NewPassword% -OldAdminPassword %OldPassword1%,%OldPassword2%,%OldPassword3% Password Lockout If you have read my posts on managing HP and Lenovo BIOS passwords, then you will know that those scripts have logic built-in to handle system reboots. This is because on HP and Lenovo systems, after a set number of failed password attempts, the system locks and needs to be rebooted before any additional password attempts can be made.\nIn my testing on Dell hardware, it seems that there is not a BIOS password lockout (or it is set to a very high number) when using the Dell PowerShell Provider. This means that there isn’t a need for multiple passes of the script when there are many potential old passwords to change. The OldAdminPassword and OldSystemPassword parameters could accept many values in a single pass of the script.\nHaving said that, I have only tested this on a limited number of Dell hardware models, so I am not sure if it is universal. Dell could also choose to add a lockout in the future. For these reasons, I have still included the reboot logic in the script, even if it isn’t needed right now.\nIf multiple passes of the script are required, it would function just like the HP and Lenovo scripts.\nFirst in the Set Password Values step, create variables for each password.\nThe First Pass folder has no conditions on it, as it should run for any Dell system. To set a new admin password or change an existing admin password, the AdminSet parameter is specified along with the AdminPassword and OldAdminPassword parameters.\nBecause the script will need to run multiple times, there is one additional parameter that needs to be specified. The SMSTSPasswordRetry parameter instructs the script to not display prompts to the screen until all attempts have completed. In this scenario, the script needs to be run 3 times, so SMSTSPasswordRetry parameter is specified on the first 2 passes of the script and not on the final pass. When the password(s) are successfully changed or cleared, the SMSTSPasswordRetry variable will be set to false. This means that if the first pass of the script is successful, the second and third passes of the script will be skipped.\n-AdminSet -AdminPassword %NewPassword% -OldAdminPassword %OldPassword1%,%OldPassword2% -SMSTSPasswordRetry When the script runs during a task sequence, it will create task sequence variables to track the success or failure of each different script action. If any one of the password actions fails, the associated task sequence variable will be set to Failed.\nDellSetAdmin DellClearAdmin DellSetSystem DellClearSystem As I mentioned before, the first run of the script in the task sequence does not have any conditions, but each successive run of the script should have these conditions.\nThe second pass of the script. Notice the SMSTSPasswordRetry parameter is specified because there is still another potential pass of the script yet to run.\n-AdminSet -AdminPassword %NewPassword% -OldAdminPassword %OldPassword3%,%OldPassword4% -SMSTSPasswordRetry The third pass of the script. Notice the SMSTSPasswordRetry parameter is not set because this is the final pass of the script.\n-AdminSet -AdminPassword %NewPassword% -OldAdminPassword %OldPassword5%,%OldPassword6% User Prompts If at the end of the script execution (whether that be one pass or multiple) any of the password management tasks are in a failed state, and the NoUserPrompt or ContinueOnError switches have not been specified, a prompt will be displayed on the screen informing the user of which tasks failed.\nThe end result of all of this is a script that can be used to change or clear Dell BIOS passwords. The script can be run in a task sequence and persist information across multiple reboots (if required). This allows for the user to be correctly prompted about any required manual actions even if there are many old passwords to test.\nNotes and Additional Reading A few notes about some restrictions Dell has placed on setting passwords.\nIf a system or hard drive password is currently set, an admin password cannot be set If an admin password is set and a system password is not set, the admin password is required to set the system password If an admin password and system password are both set and the admin password is cleared, the system password will also be automatically cleared When booting into WinPE, the Dell WMI classes take a couple of minutes to install or initialize. Because of this, if the script fails to connect to a WMI class, it will retry every 30 seconds for 3 minutes before failing. Some Dell systems have the ability to set hard drive password(s). This script currently does not support hard drive passwords. Only admin and system passwords can be managed. I may work on adding hard drive password support in the future.\nFor information on configuring Dell BIOS passwords using PowerShell and WMI, see my post Dell BIOS Settings Management - WMI. If you need to support older dell hardware that does not support the WMI classes, see my other Dell posts Dell BIOS Password Management - PSModule and Dell BIOS Settings Management - PSModule. If you’re looking for other options for managing Dell BIOS passwords, check out the Dell Command Configure utility.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/dell-bios-password-management-wmi/","summary":"\u003cp\u003eEarlier this year, I wrote about how to \u003cstrong\u003e\u003ca href=\"/dell-bios-settings-management/\"\u003emanage Dell BIOS password\u003c/a\u003e\u003c/strong\u003e\u003ca href=\"/dell-bios-settings-management/\"\u003e\u003cstrong\u003es\u003c/strong\u003e\u003c/a\u003e using PowerShell. The method described in that post uses the \u003ca href=\"/working-with-the-dell-command-powershell-provider/\"\u003e\u003cstrong\u003eDellBIOSProvider\u003c/strong\u003e\u003c/a\u003e PowerShell module. This method works, but I was not completely satisfied with it, as the PowerShell module needs to be downloaded and installed on every system the script runs on.\u003c/p\u003e\n\u003cp\u003eThankfully, Dell recently released a \u003ca href=\"https://downloads.dell.com/manuals/common/dell-agentless-client-manageability.pdf\"\u003e\u003cstrong\u003etechnical whitepaper\u003c/strong\u003e\u003c/a\u003e documenting WMI classes that can be used to directly modify BIOS settings without needing an outside program or PowerShell module. This allowed me to create a new version of the Dell BIOS Settings Management script that does not require any additional content to function.\u003c/p\u003e","title":"Dell BIOS Password Management - WMI"},{"content":"Earlier this year, I wrote about how to manage Dell BIOS settings using PowerShell. The method described in that post uses the DellBIOSProvider PowerShell module. This method works, but I was not completely satisfied with it, as the PowerShell module needs to be downloaded and installed on every system the script runs on.\nThankfully, Dell recently released a technical whitepaper documenting WMI classes that can be used to directly modify BIOS settings without needing an outside program or PowerShell module. This allowed me to create a new version of the Dell BIOS Settings Management script that does not require any additional content to function.\nOne caveat for this new method is the WMI classes are only supported on Dell hardware released to market after calendar year 2018. Because of this, older Dell hardware will still require the use of the DellBIOSProvider PowerShell module.\nThe script can be downloaded from my GitHub: https://github.com/ConfigJon/Firmware-Management/blob/master/Dell/Manage-DellBiosSettings-WMI.ps1\nDell, WMI, and PowerShell Dell provides a WMI interface that can be used for querying and modifying BIOS settings on their hardware models (only applies to models released after calendar year 2018). This means that we can use PowerShell to directly view and edit BIOS settings without the need for a vendor specific program. This script uses 7 of the Dell provided WMI classes.\nThe first WMI class is EnumerationAttribute. It is located in the root\\dcim\\sysman\\biosattributes namespace. This class is used to return a list of all BIOS settings with a set of predefined values. This list includes the majority of the configurable BIOS settings.\n#Connect to the EnumerationAttribute WMI class $Enumeration = Get-CimInstance -Namespace root\\dcim\\sysman\\biosattributes -ClassName EnumerationAttribute #Return a list of settings $Enumeration | Select-Object AttributeName,CurrentValue,PossibleValue #Return a specific setting and value $Enumeration | Where-Object AttributeName -eq \u0026#34;WakeOnLan\u0026#34; | Select-Object AttributeName,CurrentValue,PossibleValue The second WMI class is IntegerAttribute. It is located in the root\\dcim\\sysman\\biosattributes namespace. This class is used to return a list of all BIOS settings with an integer value. This list includes things like the power on hours and password length requirements.\n#Connect to the IntegerAttribute WMI class $Integer = Get-CimInstance -Namespace root\\dcim\\sysman\\biosattributes -ClassName IntegerAttribute #Return a list of settings $Integer | Select-Object AttributeName,CurrentValue,PossibleValue #Return a specific setting and value $Integer | Where-Object AttributeName -eq \u0026#34;AutoOnHr\u0026#34; | Select-Object AttributeName,CurrentValue,PossibleValue The third WMI class is StringAttribute. It is located in the root\\dcim\\sysman\\biosattributes namespace. This class is used to return a list of all BIOS settings with a string value. This list includes things like the service tag and asset tag.\n#Connect to the StringAttribute WMI class $String = Get-CimInstance -Namespace root\\dcim\\sysman\\biosattributes -ClassName StringAttribute #Return a list of settings $String | Select-Object AttributeName,CurrentValue,PossibleValue #Return a specific setting and value $String | Where-Object AttributeName -eq \u0026#34;SvcTag\u0026#34; | Select-Object AttributeName,CurrentValue,PossibleValue The fourth WMI class is BIOSAttributeInterface. It is located in the root\\dcim\\sysman\\biosattributes namespace. This class contains a method called SetAttribute which is used to modify BIOS settings. This class also contains a method called SetBIOSDefaults which can be used to set all BIOS settings to default values.\n#Connect to the BIOSAttributeInterface WMI class $AttributeInterface = Get-WmiObject -Namespace root\\dcim\\sysman\\biosattributes -Class BIOSAttributeInterface #Set a specific BIOS setting (BIOS password is not set) $AttributeInterface.SetAttribute(0,0,0,\u0026#34;SettingName\u0026#34;,\u0026#34;SettingValue\u0026#34;) #Set a specific BIOS setting (BIOS password is set) $AttributeInterface.SetAttribute(1,$Bytes.Length,$Bytes,\u0026#34;SettingName\u0026#34;,\u0026#34;SettingValue\u0026#34;) \u0026lt;# BIOS Defaults Value Reference 0 - BuiltInSafeDefaults 1 - LastKnownGood 2 - Factory 3 - UserConf1 4 - UserConf2 #\u0026gt; #Set all BIOS settings to factory defaults (BIOS password is not set) $AttributeInterface.SetBIOSDefaults(0,0,0,2) The fifth WMI class is BootOrder. It is located in the root\\dcim\\sysman\\biosattributes namespace. This class is used to return the boot order settings.\n#Connect to the BootOrder WMI class $BootOrder = Get-CimInstance -Namespace root\\dcim\\sysman\\biosattributes -ClassName BootOrder #Return the current boot order settings $BootOrder | Select-Object BootListType,BootOrder The sixth WMI class is BootOrderInterface. It is located in the root\\dcim\\sysman\\biosattributes namespace. This class contains a method called Set which is used to modify the boot order settings.\n#Connect to the BootOrderInterface WMI class $BootOrderInterface = Get-WmiObject -Namespace root\\dcim\\sysman\\biosattributes -Class BootOrderInterface #Save the new boot order to a variable $NewBootOrder = \u0026#34;Windows Boot Manager\u0026#34;,\u0026#34;Onboard NIC(IPV4)\u0026#34;,\u0026#34;Onboard NIC(IPV6)\u0026#34; #Set the UEFI boot order (BIOS password is not set) $BootOrderInterface.Set(0,0,0,\u0026#34;UEFI\u0026#34;,$NewBootOrder.Count,$NewBootOrder) #Set the UEFI boot order (BIOS password is set) $BootOrderInterface.Set(1,$Bytes.Length,$Bytes,\u0026#34;UEFI\u0026#34;,$NewBootOrder.Count,$NewBootOrder) The seventh WMI class is SecurityInterface. It is located in the root\\dcim\\sysman\\wmisecurity namespace. This class contains a method called SetNewPassword. In this script this method is used to test the existing BIOS password. For more information about this class, see this post Dell BIOS Password Management - WMI.\nBIOS Password Encoding The above information contains examples for modifying the BIOS with and without an existing BIOS password. When a BIOS password is set, it must first be encoded before it can be passed to a method.\n$Password = \u0026#34;ExamplePass\u0026#34; $Encoder = New-Object System.Text.UTF8Encoding $Bytes = $Encoder.GetBytes($Password) Each of the methods used to modify BIOS settings starts with 3 arguments. The 3 arguments are:\nThe type of text The length of the byte array The byte array containing the encoded password When no password is set, these arguments are set to 0,0,0. The type of text is 0 (None), the length of the byte array is 0, and the byte array itself is 0.\nWhen a password is set, these arguments are set to 1,$Bytes.Length,$Bytes. The type of text is 1 (plain text), the length of the byte array is set to $Bytes.Length, and the byte array is $Bytes.\nStatus Codes For reference, when calling the Set or SetAttribute or SetBIOSDefaults methods, the possible status codes are:\n0 - Success 1 - Failed 2 - Invalid Parameter 3 - Access Denied 4 - Not Supported 5 - Memory Error 6 - Protocol Error For more detailed information on the Dell WMI interface, refer to the official documentation. http://downloads.dell.com/manuals/common/dell-agentless-client-manageability.pdf\nManage-DellBiosSettings-WMI.ps1 This script takes the basic commands and adds logic to allow for a more automated settings management process. The script has 7 parameters.\nGetSettings - Use this parameter to instruct the script to generate a list of all current BIOS settings. The settings will be displayed on the screen by default. SetSettings - Use this parameter to instruct the script to set specific BIOS settings. Settings can be specified either in the body of the script or from a CSV file. CsvPath - Use this parameter to specify the location of a CSV file. If used with the GetSettings switch, this acts as the location where a list of current BIOS settings will be saved. If used with the SetSettings switch, this acts as the location where the script will read BIOS settings to be set from. Using this switch with the SetSettings switch will also cause the script to ignore any settings specified in the body of the script. AdminPassword - Used to specify the BIOS password. SetDefaults - Use this parameter to instruct the script to set all BIOS settings to default values. Acceptable values for this parameter are (BuiltInSafeDefaults, LastKnownGood, Factory, UserConf1, UserConf2) SetBootOrder - Used to specify the desired boot order to be set on the system. Values should be specified in a comma separated list. BootMode - Used to specify which boot mode the boot order should be applied to. Acceptable values for this parameter are (UEFI, Legacy) When using the script to set settings, the list of settings can either be specified in the script itself or in a CSV file. To specify settings in the script, look for the $Settings array near the top of the script. The settings should be in the format of “Setting Name,Setting Value”\n#List of settings to be configured ================================= #=================================================================== $Settings = ( \u0026#34;FingerprintReader,Enabled\u0026#34;, \u0026#34;FnLock,Enabled\u0026#34;, \u0026#34;IntegratedAudio,Enabled\u0026#34;, \u0026#34;NumLock,Enabled\u0026#34;, \u0026#34;SecureBoot,Enabled\u0026#34;, \u0026#34;TpmActivation,Enabled\u0026#34;, \u0026#34;TpmClear,Disabled\u0026#34;, \u0026#34;TpmPpiClearOverride,Disabled\u0026#34;, \u0026#34;TpmPpiDpo,Disabled\u0026#34;, \u0026#34;TpmPpiPo,Enabled\u0026#34;, \u0026#34;TpmSecurity,Enabled\u0026#34;, \u0026#34;UefiNwStack,Enabled\u0026#34;, \u0026#34;Virtualization,Enabled\u0026#34;, \u0026#34;VtForDirectIo,Enabled\u0026#34;, \u0026#34;WakeOnLan,Disabled\u0026#34; ) #=================================================================== #=================================================================== A full list of configurable settings can be exported from a device by calling the script with the GetSettings parameter. The CsvPath parameter can also be specified to output the list of settings to a CSV file.\nWhen the script runs, it will write to a log file. By default, this log file will be named Manage-DellBiosSettings-WMI.Log. If the script is being run during a task sequence, the log file will be located in the _SMSTSLogPath. Otherwise, the log file will be located in ProgramData\\ConfigJonScripts\\Dell. The log file name and path can be changed using the LogFile parameter. Note that the log file path will always be set to _SMSTSLogPath when run during a task sequence.\nThe script has logic built-in to detect if settings were already set correctly, were successfully set, failed to set, or were not found on the device. The script will output these counts to the screen at the end. More detailed information about the settings will be written to the log file.\nI have included a few example settings files in my GitHub. These settings files contain commonly configured Dell BIOS settings.\nSettings_CSV_SecureBoot.csv – Contains settings for enabling UEFI and SecureBoot Settings_CSV_TPM.csv – Contains settings for enabling and activating TPM Settings_CSV_General.csv – Contains other common settings Settings_In-Script_All.txt – Contains common settings formatted for use in the body of the script Examples The script can be run as a standalone script in Windows, or as part of a Configuration Manager task sequence. It can also be run in the full Windows OS or in WinPE.\nHere are a few examples of calling the script from a PowerShell prompt.\n#Set BIOS settings supplied in the script Manage-DellBiosSettings-WMI.ps1 -SetSettings -AdminPassword ExamplePassword #Set BIOS settings supplied in a CSV file Manage-DellBiosSettings-WMI.ps1 -SetSettings -CsvPath C:\\Temp\\Settings.csv -AdminPassword ExamplePassword #Set all BIOS settings to factory default values Manage-DellBiosSettings-WMI.ps1 -SetDefaults Factory -AdminPassword ExamplePassword #Set the UEFI boot order Manage-DellBiosSettings-WMI.ps1 -SetBootOrder \u0026#34;Windows Boot Manager\u0026#34;,\u0026#34;Onboard NIC(IPV4)\u0026#34;,\u0026#34;Onboard NIC(IPV6)\u0026#34; -BootMode UEFI -AdminPassword ExamplePassword #Set BIOS settings supplied in the script and set the UEFI boot order Manage-DellBiosSettings-WMI.ps1 -SetSettings -SetBootOrder \u0026#34;Windows Boot Manager\u0026#34;,\u0026#34;Onboard NIC(IPV4)\u0026#34;,\u0026#34;Onboard NIC(IPV6)\u0026#34; -BootMode UEFI -AdminPassword ExamplePassword #Output a list of current BIOS settings to the screen Manage-DellBiosSettings-WMI.ps1 -GetSettings #Output a list of current BIOS settings to a CSV file Manage-DellBiosSettings-WMI.ps1 -GetSettings -CsvPath C:\\Temp\\Settings.csv Here is an example of calling the script during a task sequence. In this example the settings are specified in the body of the script, so the script can be stored directly in the task sequence step. Also the admin password is set, so the AdminPassword parameter is specified.\nIn this second example, the script is being called from a package and the settings are being supplied from a CSV file.\nNotes and Additional Reading When booting into WinPE, the Dell WMI classes take a couple of minutes to install or initialize. Because of this, if the script fails to connect to a WMI class, it will retry every 30 seconds for 3 minutes before failing. The GetSettings parameter does not write the current Boot Order to the screen or to the CSV. This information is recorded in the log file. I\u0026rsquo;m hoping to improve this functionality in the future. For information on configuring Dell BIOS passwords using PowerShell and WMI, see my post Dell BIOS Password Management - WMI. If you need to support older dell hardware that does not support the WMI classes, see my other Dell posts Dell BIOS Password Management - PSModule and Dell BIOS Settings Management - PSModule. If you’re looking for other options for managing Dell BIOS settings, check out the Dell Command Configure utility.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/dell-bios-settings-management-wmi/","summary":"\u003cp\u003eEarlier this year, I wrote about how to \u003ca href=\"/dell-bios-settings-management/\"\u003e\u003cstrong\u003emanage Dell BIOS settings\u003c/strong\u003e\u003c/a\u003e using PowerShell. The method described in that post uses the \u003ca href=\"/working-with-the-dell-command-powershell-provider/\"\u003e\u003cstrong\u003eDellBIOSProvider\u003c/strong\u003e\u003c/a\u003e PowerShell module. This method works, but I was not completely satisfied with it, as the PowerShell module needs to be downloaded and installed on every system the script runs on.\u003c/p\u003e\n\u003cp\u003eThankfully, Dell recently released a \u003ca href=\"https://downloads.dell.com/manuals/common/dell-agentless-client-manageability.pdf\"\u003e\u003cstrong\u003etechnical whitepaper\u003c/strong\u003e\u003c/a\u003e documenting WMI classes that can be used to directly modify BIOS settings without needing an outside program or PowerShell module. This allowed me to create a new version of the Dell BIOS Settings Management script that does not require any additional content to function.\u003c/p\u003e","title":"Dell BIOS Settings Management - WMI"},{"content":"This post was updated on February 13th, 2021.\nThere are many issues that can happen while configuring and using an Always On VPN solution. In this post I\u0026rsquo;ll be covering the common errors I\u0026rsquo;ve encountered while setting up Always On VPN. In addition, I\u0026rsquo;ll share some useful commands and show to how monitor VPN connections. Also, make sure to check out the troubleshooting section of the official Microsoft Documentation.\nLinks to each individual post in this series can be found below.\nAlways On VPN - Basic Deployment Guide\nAlways On VPN - Certificates and Active Directory\nAlways On VPN - VPN and NPS Server Configuration\nAlways On VPN - User Tunnel\nAlways On VPN - Device Tunnel\nVPN Connection Error Codes The first thing I want to cover is the error codes you might encounter when attempting to establish a VPN connection. These errors can be found by looking in the Application event log on the client. The events will have a source of RasClient. A full list of RRAS error codes can be found here.\nError code: 691 This error can be caused by TLS 1.0 being disabled (Windows Server 2012 R2 and earlier) or by settings configured on the Dial-In tab of a user\u0026rsquo;s AD account. See this post and this post and this post for more information.\nError code: 800 This error is usually caused when a custom IKEv2 security policy is specified and the VPN connection type is set to automatic. See these links for more information. Microsoft, Richard Hicks\nError code: 809 This error is usually caused by the VPN client not being able to communicate with the VPN server. See these links for more information. Microsoft, Richard Hicks\nError code: 812 This is an error covered on the troubleshooting page of the Microsoft Documentation, but I wanted to add a few notes not mentioned there.\nIf attempting to connect a user tunnel, ensure the user account is a member of the AD group specified in the VPN policy on the NPS server Ensure the VPN server is able to communicate with the NPS server. If the NPS server is running on Windows Server 2019, there is a bug where the Windows Firewall rules may not work correctly. To fix this bug, run this command from an administrative command prompt on the NPS server. sc.exe sidtype IAS unrestricted For more information about this bug and the solution, see this post.\nError code: 858 This error is caused by the certificate on the NPS server being expired. See this post for more information.\nError code: 864 This error is caused by an invalid or missing certificate on the NPS server. See this post for more information.\nError code: 902 Error description\nThe specified protocol identifier is not known to the router. Possible cause\nThis error can occur when IPv6 has been disabled on the VPN server Possible solutions\nEnsure there is not a group policy object deployed to the VPN server that is disabling IPv6\nRe-enable IPv6\nIn the registry on the VPN server, navigate to HKLM\\SYSTEM\\CurrentControlSet\\Services\\Tcpip6\\Parameters and look for the value DisabledComponents If this value exists, it should be set to either 0 (IPv6 enabled) or 32 (IPv6 enabled but IPv4 is preferred). If this value is set to anything other than 0 or 32, the Routing and Remote Access service will not work. After changing this value, reboot the VPN server. For more information about this registry value, refer to this article. If the error persists after re-enabling IPv6\nIn the registry on the VPN server, navigate to HKLM\\SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\RouterManagers There should be a key under RouterManagers named ipv6. If this key does not exist, re-create it and then restart the Routing and Remote Access service Error code: 13801 This error is usually caused by a missing, expired, or incorrectly configured machine certificate on the client or VPN server. See this post for more information.\nError code: 13806 This error is usually caused when using a device tunnel connection and the machine certificate is missing on either the client or server side. See this post for more information.\nError code: 13868 Error description Policy match error Possible cause This error can occur when using the IKEv2 protocol and the IKEv2 security settings configured on the client don\u0026rsquo;t match the settings configured on the server. Possible solutions Ensure the IKEv2 security settings on the client and server match Check the server settings by running this PowerShell command Get-VpnServerIPsecConfiguration Check the client settings by running this PowerShell command Get-VpnConnection -Name \u0026ldquo;VPN Name\u0026rdquo; | Select-Object -ExpandProperty IPsecCustomPolicy If you\u0026rsquo;ve been following my guide and implemented the improved IKEv2 security settings on the server, then running this command on the client should resolve the issue. Set-VpnConnectionIPsecConfiguration -ConnectionName \u0026#34;VPN Name\u0026#34; -AuthenticationTransformConstants SHA256128 -CipherTransformConstants AES128 -DHGroup Group14 -EncryptionMethod AES128 -IntegrityCheckMethod SHA256 -PFSgroup PFS2048 -Force For more information about this error and my source for these commands, refer to this post.\nError code: 13899 Error description Error in assigning inner IP address to initiator in tunnel mode Possible cause This error can occur when the VPN server is unable to assign an IP address to the VPN tunnel Possible solutions If the VPN server is configured to assign IP addresses from a static pool, check if all available addresses have been allocated. If so, add additional IP address space to the pool. If the VPN server is configured to assign IP addresses using DHCP Ensure a DHCP server is reachable from the VPN server Ensure the DHCP scope has available IP addresses to allocate If the VPN server is running Windows Server 2019 and is configured to assign IP addresses using DHCP, there is a bug that can cause this issue. To resolve this issue, run the following command to create a new registry value, then reboot the VPN server For more information about this bug, refer to this TechNet post. reg add \u0026#34;HKLM\\SYSTEM\\CurrentControlSet\\Services\\Dhcp\u0026#34; /v RequiredPrivileges /d \u0026#34;SeChangeNotifyPrivilege\u0026#34;\\0\u0026#34;SeCreateGlobalPrivilege\u0026#34;\\0\u0026#34;SeImpersonatePrivilege\u0026#34;\\0 /t REG_MULTI_SZ /f Error code: 0x80070040 This error is caused by a missing or incorrectly configured certificate on the VPN server. See this post for more information.\nError code: 0x80092013 This error is caused when using SSTP and the CRL of the SSL certificate installed on the VPN server is not publicly available. See this post for more information.\nError code: 0x800B0109 This error is caused when the root CA certificate that issued the client certificate is not installed in the Trusted Root Certification Authorities store on the client computer. See this post for more information.\nVPN Connection Reliability (Sleep / Hibernate) Many users have experienced issues with Always On VPN connections not reliably re-connecting when a device comes out of a sleep or hibernate mode. There is a lengthy TechNet forum post on the topic. Richard Hicks also has a post on the subject.\nDevice Tunnel with Multiple Root Certificates It\u0026rsquo;s possible to have multiple copies of the same root certificate installed in the trusted root certificates store on the VPN server. This can cause issues with the authentication process for device tunnel connections. To resolve this issue, remove the duplicate certificates. Read more about this issue in this post by Richard Hicks.\nVPN Creation Errors These are errors you may encounter when using the New-AovpnDeviceTunnel.ps1 or New-AovpnUserTunnel.ps1 scripts to install a new VPN tunnel on a computer.\nBoth of these scripts write to a log file located in ProgramData\\AOVPN. Make sure to check this log file for more details about why one of the scripts may have failed.\nError Message - Unable to get user SID. User may be logged on over Remote Desktop: A constructor was not found. Cannot find an appropriate constructor for type System.Security.Principal.NTAccount This error is caused because the user tunnel cannot be created for a user that is logged in through a remote desktop session. The user must be locally logged into the computer or connected via a remote console session. Error Message - Unable to create VPN Name profile: A general error occurred that is not covered by a more specific error code This error is usually caused by invalid syntax in the XML file that was provided to the script. Review the XML file and correct any typos or incorrect formatting. Name Resolution Policy Table (NRPT) The Name Resolution Policy Table is used to specify DNS names or namespaces that require special handling during DNS lookups. In an AOVPN configuration, the NRPT is configured by specifying the element in the ProfileXML file. This can be a useful feature, however, there are a few things to be aware of when using the NRPT.\nTroubleshooting Tools When attempting to troubleshoot DNS with the NRPT enabled, be careful about using nslookup. Nslookup will bypass the NRPT and use the DNS servers configured on the network adapter. Instead of nslookup, use the Resolve-DNSName PowerShell cmdlet.\nThere are a few PowerShell cmdlets that can be used to view NRPT settings. (Get-DnsClientNrptPolicy, Get-DnsClientNrptGlobal, Get-DnsClientNrptRule)\n#View the currently applied NRPT settings Get-DnsClientNrptPolicy #View the NRPT settings for a specific namespace Get-DnsClientNrptPolicy -Effective -Namespace \u0026#34;example.corp.com\u0026#34; #View the global NRPT settings on a device Get-DnsClientNrptGlobal #View currently configured NRPT rules Get-DnsClientNrptRule DNS Registration Issue There is an issue when the NRPT is used and the ProfileXML has the element set to True. In this case, the client may register 2 DNS entries, one for the IP of the VPN, and one for the public IP of the system. Microsoft has released patches to resolve this issue, but even with the patches, a registry key may still need to be created to stop this issue from happening.\nNew-ItemProperty -Path \u0026#39;HKLM:SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters\\\u0026#39; -Name DisableNRPTForAdapterRegistration -PropertyType DWORD -Value 1 -Force For more information on this issue, refer to this post.\nNRPT and DirectAccess If you\u0026rsquo;re migrating from DirectAccess to Always On VPN, you may run into an issue where the NRPT rules seem to be ignored on the device. A symptom of this issue is when running the Get-DnsClientNrptPolicy cmdlet, no results are returned, but running the Get-DnsClientNrptRule cmdlet does show results. To resolve this issue, remove the registry key that is used to store DirectAccess NRPT entries.\nRemove-Item -Path \u0026#39;HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows NT\\DNSClient\\DnsPolicyConfig\u0026#39; -Recurse -Force Other Useful Commands This is a list of some commands I\u0026rsquo;ve found useful for troubleshooting Always On VPN connections.\n#Attempt to connect a VPN tunnel rasdial \u0026#34;Tunnel Name\u0026#34; #Attempt to disconnect a VPN tunnel rasdial \u0026#34;Tunnel Name\u0026#34; /d #List all user VPN connections Get-VpnConnection #List all device VPN connections Get-VpnConnection -AllUserConnection #Delete a user tunnel Get-VpnConnection | Where Name -eq \u0026#34;Tunnel Name\u0026#34; | Remove-VpnConnection #Delete a device tunnel Get-VpnConnection -AllUserConnection | Where Name -eq \u0026#34;Tunnel Name\u0026#34; | Remove-VpnConnection Monitor Active VPN Connections There are 3 main ways to monitor active VPN connections when using Windows Server as a VPN server.\nThe Remote Access Management console Open the Remote Access Management console and select Remote Client Status. This view gives the most information about the connected clients. The Routing and Remote Access console Open the Routing and Remote Access console and select Remote Access Clients. This view is like the first option, but less information is displayed. PowerShell Open PowerShell and run the Get-RemoteAccessConnectionStatistics cmdlet. ","permalink":"https://4c4806b4.configjon-blog.pages.dev/always-on-vpn-troubleshooting/","summary":"\u003cp\u003e\u003cstrong\u003eThis post was updated on February 13th, 2021.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThere are many issues that can happen while configuring and using an Always On VPN solution. In this post I\u0026rsquo;ll be covering the common errors I\u0026rsquo;ve encountered while setting up Always On VPN. In addition, I\u0026rsquo;ll share some useful commands and show to how monitor VPN connections. Also, make sure to check out the troubleshooting section of the official \u003cstrong\u003e\u003ca href=\"https://docs.microsoft.com/en-us/windows-server/remote/remote-access/vpn/always-on-vpn/deploy/always-on-vpn-deploy-troubleshooting\"\u003eMicrosoft Documentation\u003c/a\u003e\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eLinks to each individual post in this series can be found below.\u003c/p\u003e","title":"Always On VPN - Troubleshooting"},{"content":"Deployment Guide Always On VPN - Basic Deployment Guide\nAlways On VPN - Certificates and Active Directory\nAlways On VPN - VPN and NPS Server Configuration\nAlways On VPN - User Tunnel\nAlways On VPN - Device Tunnel\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/always-on-vpn/","summary":"\u003ch3 id=\"deployment-guide\"\u003eDeployment Guide\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003e\u003cstrong\u003e\u003ca href=\"/always-on-vpn-basic-deployment-guide/\"\u003eAlways On VPN - Basic Deployment Guide\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-certificates-and-active-directory/\"\u003eAlways On VPN - Certificates and Active Directory\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-vpn-and-nps-server-configuration/\"\u003eAlways On VPN - VPN and NPS Server Configuration\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-user-tunnel/\"\u003eAlways On VPN - User Tunnel\u003c/a\u003e\u003c/strong\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-device-tunnel/\"\u003eAlways On VPN - Device Tunnel\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e","title":"Always On VPN"},{"content":"With all the increased focus on working from home and remote access lately, I figured now would be a good time to share my notes on configuring Always On VPN. This first post will cover the basics of the Always On VPN technology. This guide will be split into multiple parts. Links to each individual post in this series can be found below.\nAlways On VPN - Certificates and Active Directory\nAlways On VPN - VPN and NPS Server Configuration\nAlways On VPN - User Tunnel\nAlways On VPN - Device Tunnel\nAlways On VPN - Troubleshooting\nI want to preface this series by saying that I am not an expert on this topic. These are my notes based on my experiences working with Always On VPN. I highly recommend reading through the official Microsoft Documentation. Additionally, throughout this series I reference a number of posts by Richard Hicks. If you\u0026rsquo;re going to be deploying any sort of remote access solution, I recommend bookmarking his website.\nHow Does Always On VPN Work? Always On VPN is a solution that allows a client to automatically establish a VPN connection without any user interaction. The technology that makes this possible is the VPNv2 CSP node, which is built into Windows 10. This CSP (configuration service provider) allows the built-in Windows 10 VPN client to be configured using an MDM solution (Intune), or PowerShell.\nThe server side of a typical Always On VPN deployment requires at least one VPN server and one authentication (RADIUS) server. Additionally, a certificate authority is required to issue certificates to the servers and clients. The certificates will be used to authenticate the VPN connection.\nThe Windows 10 VPN client can be configured to connect a user authenticated tunnel or a device authenticated tunnel. Both types of tunnels can be connected simultaneously if required.\nUser Tunnel The User Tunnel is established when a user logs into a computer. This type of tunnel is ideal for granting access to file shares or applications.\nHere is a high-level overview of the connection process for a Always On VPN user tunnel.\nThe VPN client sends a connection request to the external IP address of the VPN server The edge firewall passes the connection request to the external interface of the VPN server The VPN server passes the connection request to the RADIUS server. The connection request leaves via the internal interface of the VPN server and passes through the internal firewall The RADIUS server receives and authenticates the connection request The RADIUS server returns an accept or deny response to the VPN server The VPN server allows or denies the connection request based on the response from the RADIUS server Device Tunnel The Device Tunnel is established as soon as a computer is powered on and connected to the internet. A user does not need to be logged into a computer for a device tunnel to connect. This type of tunnel is ideal for granting access to Active Directory or other management servers like Configuration Manager.\nHere is a high-level overview of the connection process for a Always On VPN device tunnel.\nThe VPN client sends a connection request to the external IP address of the VPN server The edge firewall passes the connection request to the external interface of the VPN server The VPN server validates the computer authentication certificate of the client and allows or denies the connection request Notice that the device tunnel does not use RADIUS for authentication. The VPN server preforms the authentication. This prevents device tunnels from taking advantage of more advanced Always On VPN features like conditional access and multi-factor authentication. For more guidance on when to utilize device tunnels refer to this post.\nVPN Protocols Always On VPN utilizes familiar VPN infrastructure, which means that it can also utilize familiar VPN protocols. There are two main protocols that make the most sense to use when working with Always On VPN.\nIKEv2 Internet Key Exchange version 2 (IKEv2) has good security and good performance. Its ability to automatically re-connect after a short interruption gives it good reliability as well. The primary concern with using IKEv2 is that communication happens on UDP 500 and UDP 4500. This makes it more likely that the connection will be blocked by firewalls.\nNote that when using a Always On VPN device tunnel, IKEv2 is the only supported protocol.\nSSTP Secure Socket Tunneling Protocol (SSTP) also has good security, and good performance. The main benefit of using SSTP is that communication happens on TCP 443, so it is very unlikely that it will be blocked anywhere. The downsides to SSTP are that it is not quite as secure as IKEv2, and it does not handle connection interruptions as well.\nAbout this Guide The goal of this series is to cover the deployment of a basic Always On VPN environment. This guide will assume the reader has existing knowledge of Active Directory Domain Services, Active Directory Certificate Services, DNS, and basic enterprise networking concepts.\nThis example deployment of Always On VPN will include:\n1 VPN server running Windows Server 2019 with the Routing and Remote Access role. This server will be located in a perimeter network and will have 2 network adapters.\n1 NPS server running Windows Server 2019 with the Network Policy Server role. This server will be located on in the internal network.\n1 VPN client running Windows 10 Enterprise 1909. Both user and device tunnels will be configured.\nThis deployment will be configured to use IKEv2 for the User Tunnel and Device tunnel.\nThis guide also assumes Active Directory Domain Services, Active Directory Certificate Services, and Group Policy are installed and functional.\nAdditional Reading This guide is for a basic deployment of Always On VPN. There are more advanced features that can be configured but will not be covered here.\nConditional Access High Availability Multi-factor authentication Traffic Filtering Also, remember to check out the full Microsoft Documentation.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/always-on-vpn-basic-deployment-guide/","summary":"\u003cp\u003eWith all the increased focus on working from home and remote access lately, I figured now would be a good time to share my notes on configuring Always On VPN. This first post will cover the basics of the Always On VPN technology. This guide will be split into multiple parts. Links to each individual post in this series can be found below.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ca href=\"/always-on-vpn-certificates-and-active-directory/\"\u003eAlways On VPN - Certificates and Active Directory\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-vpn-and-nps-server-configuration/\"\u003eAlways On VPN - VPN and NPS Server Configuration\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003cstrong\u003e\u003ca href=\"/always-on-vpn-user-tunnel/\"\u003eAlways On VPN - User Tunnel\u003c/a\u003e\u003c/strong\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-device-tunnel/\"\u003eAlways On VPN - Device Tunnel\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-troubleshooting/\"\u003eAlways On VPN - Troubleshooting\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e","title":"Always On VPN - Basic Deployment Guide"},{"content":"This is the second post in my series on setting up a basic Always On VPN deployment. In this post I will be covering the requirements for the Always On VPN certificates. I will also talk about how Active Directory groups can be utilized. Links to each individual post in this series can be found below.\nAlways On VPN - Basic Deployment Guide\nAlways On VPN - VPN and NPS Server Configuration\nAlways On VPN - User Tunnel\nAlways On VPN - Device Tunnel\nAlways On VPN - Troubleshooting\nActive Directory Groups There are 4 Active Directory groups that can be created.\nAOVPN Users - This group will contain Active Directory user accounts and be used to control which users are allowed to connect via an Always On VPN user tunnel.\nAOVPN Computers - This group will contain Active Directory computer accounts and will be used to control which computers receive the Computer certificate.\nAOVPN NPS Servers - This group will contain the Active Directory computer objects of the NPS server(s). This group is not required, however it does make the certificate deployment and management process easier.\nAOVPN RAS Servers - This group will contain the Active Directory computer objects of the VPN server(s). If your VPN servers are not domain-joined, this group is not required. If your VPN servers are domain-joined this group will make certificate deployment and management easier.\nCertificates There are multiple certificates that can be used in a deployment of Always On VPN. In this example, the certificates will be issued by a Windows Server running Active Directory Certificate Services.\nVPN Server Certificate (IKEv2) This certificate should be issued if the VPN server will be accepting IKEv2 connections.\nOpen the Certification Authority MMC snap-in Right click on Certificate Templates and select Manage Right click on the RAS and IAS Server template and select Duplicate Template Compatibility tab Set Certification Authority to Windows Server 2012 R2 Click OK on the Resulting changes dialog box Set Certificate recipient to Windows 8.1 / Windows Server 2012 R2 Click OK on the Resulting changes dialog box General tab Enter a display name AOVPN RAS Authentication Optionally change the validity and renewal period Security tab Add the AOVPN RAS Servers group and grant it Read and Enroll permissions Remove the RAS and IAS Servers group Extensions tab Select Application Policies and click Edit Click Add, select IP security IKE intermediate, and click OK Subject Name tab Check Supply in the request Click OK on the Certificate Templates dialog box Click OK to save and close the properties window VPN Server Certificate (SSTP) This certificate should be issued if the VPN server will be accepting SSTP connections. The certificate revocation list (CRL) for this certificate needs to be available on the internet. If the CRL for the internal PKI is not publicly available, then this certificate should be issued through a third-party CA. An existing SSL wildcard certificate could be used here. For more information about the VPN server SSTP certificate, see this post.\nNPS Server Certificate Open the Certification Authority MMC snap-in Right click on Certificate Templates and select Manage Right click on the RAS and IAS Server template and select Duplicate Template Compatibility tab Set Certification Authority to Windows Server 2012 R2 Click OK on the Resulting changes dialog box Set Certificate recipient to Windows 8.1 / Windows Server 2012 R2 Click OK on the Resulting changes dialog box General tab Enter a display name AOVPN NPS Authentication Optionally change the validity and renewal period Security tab Add the AOVPN NPS Servers group and grant it Read, Enroll, and Autoenroll permissions Remove the RAS and IAS Servers group Click OK to save and close the properties window User Authentication Certificate Open the Certification Authority MMC snap-in Right click on Certificate Templates and select Manage Right click on the User template and select Duplicate Template Compatibility tab Set Certification Authority to Windows Server 2012 R2 Click OK on the Resulting changes dialog box Set Certificate recipient to Windows 8.1 / Windows Server 2012 R2 Click OK on the Resulting changes dialog box General tab Enter a display name AOVPN User Authentication Uncheck Publish certificate in Active Directory Optionally change the validity and renewal period Security tab Add the AOVPN Users group and grant it Read, Enroll, and Autoenroll permissions Remove the Domain Users group Request Handling tab Uncheck Allow private key to be exported Cryptography tab Change Provider Category to Key Storage Provider Check Requests must use one of the following providers In the Providers list Check Microsoft Platform Crypto Provider and Microsoft Software Key Storage Provider Use the up arrow button on to move Microsoft Platform Crypto Provider to the top of the list Set the Request hash to SHA256 Subject Name tab Uncheck Include e-mail name in the subject name and E-mail name Click OK to save and close the properties window Computer Authentication Certificate The only requirement for this certificate is that is has the Client Authentication property under Enhanced Key Usage. If a certificate with this property has already been issued to computers for other reasons (wireless, Configuration Manager, etc.) that certificate would work to authenticate the connection.\nOpen the Certification Authority MMC snap-in\nRight click on Certificate Templates and select Manage\nRight click on the Computer template and select Duplicate Template\nCompatibility tab\nSet Certification Authority to Windows Server 2012 R2 Click OK on the Resulting changes dialog box Set Certificate recipient to Windows 8.1 / Windows Server 2012 R2 Click OK on the Resulting changes dialog box General tab\nEnter a display name AOVPN Computer Authentication Optionally change the validity and renewal period Security tab\nAdd the AOVPN Computers group and grant it Read, Enroll, and Autoenroll permissions Remove the Domain Computers group Click OK to save and close the properties window\nIssue the Certificates After all of the certificate templates have been created, the need to be issued.\nOpen the Certification Authority MMC snap-in Right click on Certificate Templates, hover over New, and select Certificate Template to Issue Select the certificates that were just created and click OK Deploy the Certificates (User, Computer, and NPS Server) The User, Computer, and NPS Server certificates are all configured to allow auto-enrollment. This means the users and computers can be instructed to install the certificates automatically. This can be done using Group Policy.\nOpen the Group Policy Management MMC snap-in Create a new Group Policy Object named Enable Certificate Auto-enrollment Edit the newly created policy Navigate to Computer Configuration \u0026gt; Policies \u0026gt; Windows Settings \u0026gt; Security Settings \u0026gt; Public Key Policies Open the properties of Certificate Services Client - Auto-Enrollment Set Configuration Model to Enabled Check Renew expired certificates and Update certificates Navigate to User Configuration \u0026gt; Policies \u0026gt; Windows Settings \u0026gt; Security Settings \u0026gt; Public Key Policies Open the properties of Certificate Services Client - Auto-Enrollment Set Configuration Model to Enabled Check Renew expired certificates and Update certificates Close the Group Policy Management Editor Select the newly created Group Policy Object Use the Security Filtering feature to limit the policy to apply to AOVPN Users and AOVPN Computers Link the Group Policy Object to the organizational unit(s) containing computer and user objects After the Group Policy Object has been created and deployed, the user, computer, and NPS server certificates should automatically install. Note that you may need to reboot the computers and/or logoff the users before the certificates will appear.\nTo verify the user certificate is installed, run certmgr.msc and look in the Personal store.\nTo verify the computer certificate is installed, run certlm.msc and look in the Personal store.\nDeploy the VPN Server Certificate The VPN server certificate requires manual steps to complete the enrollment process. However, these steps are different depending on weather or not the server is Active Directory domain-joined.\nDomain-Joined Add the VPN server to the AOVPN VPN Servers Active Directory group Log into the VPN server and run certlm.msc Right click on the Personal store, hover over All Tasks, and select Request New Certificate Click Next at the Before You Begin page Select Active Directory Enrollment Policy and click Next Select the AOVPN VPN Authentication certificate and click the More Information is Required link Set the Subject Name type to Common Name Enter the external FQDN of the VPN server (aovpn.domain.com) and click Add Set the Alternative Name type to DNS Enter the external FQDN of the VPN server (aovpn.domain.com) and click Add Click OK to close the certificate properties window Click Enroll to complete the certificate enrollment Non-Domain-Joined Log into the VPN server Create a new text document and save it as VPNGateway.inf Copy this data into the newly created file Replace both instances of aovpn.domain.com with the external FQDN of the VPN server [Version] Signature=\u0026#34;$Windows NT$\u0026#34; [NewRequest] Subject = \u0026#34;CN=aovpn.domain.com\u0026#34; Exportable = FALSE KeyLength = 2048 KeySpec = 1 KeyUsage = 0xA0 MachineKeySet = True ProviderName = \u0026#34;Microsoft RSA SChannel Cryptographic Provider\u0026#34; RequestType = PKCS10 [Extensions] 2.5.29.17 = \u0026#34;{text}\u0026#34; _continue_ = \u0026#34;dns=aovpn.domain.com\u0026amp;\u0026#34; Open an administrative command prompt and run this command to create a new certificate request Certreq -new VPNGateway.inf VPNGateway.req This will create a new file named VPNGateway.req Copy VPNGateway.req to the certificate authority (CA) server On the CA server, open an administrative command prompt Run this command to generate a certificate from the request file Certreq -attrib \u0026#34;CertificateTemplate:AOVPNVPNAuthentication\u0026#34; -submit VPNGateway.req VPNGateway.cer This will create a new file named VPNGateway.cer Copy the VPNGateway.cer file back to the VPN server On the VPN server, open an administrative command prompt Run this command to complete the certificate request Certreq -accept VPNGateway.cer If the VPN server is non-domain-joined, it will also need to have the full certificate chain installed so the new cert is properly trusted. This involves exporting the root cert from each tier of the PKI down to the server that issued the VPN certificate. In my example, there is an offline root CA and a domain-joined issuing CA.\nLog into the Root CA and the Issuing CA and run this command from an administrative command prompt Replace NameOfServer with the name of the sever the certificate is being exported from Certutil -ca.cert NameOfServer.cer Copy the exported certificates to the VPN server Right click on the exported Root CA certificate and click Install Certificate Select Local Machine and click Next Select Place all certificates in the following store and click Browse Select Trusted Root Certification Authorities and click OK Click Next Click Finish to complete the import Right click on the exported Issuing CA certificate and click Install Certificate Select Local Machine and click Next Select Place all certificates in the following store and click Browse Select Intermediate Certification Authorities and click OK Click Next Click Finish to complete the import This completes the certificate configuration portion of the deployment. The next post in the series is Always On VPN - VPN and NPS Server Configuration.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/always-on-vpn-certificates-and-active-directory/","summary":"\u003cp\u003eThis is the second post in my series on setting up a basic Always On VPN deployment. In this post I will be covering the requirements for the Always On VPN certificates. I will also talk about how Active Directory groups can be utilized. Links to each individual post in this series can be found below.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ca href=\"/always-on-vpn-basic-deployment-guide/\"\u003eAlways On VPN - Basic Deployment Guide\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-vpn-and-nps-server-configuration/\"\u003eAlways On VPN - VPN and NPS Server Configuration\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003cstrong\u003e\u003ca href=\"/always-on-vpn-user-tunnel/\"\u003eAlways On VPN - User Tunnel\u003c/a\u003e\u003c/strong\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-device-tunnel/\"\u003eAlways On VPN - Device Tunnel\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-troubleshooting/\"\u003eAlways On VPN - Troubleshooting\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e","title":"Always On VPN - Certificates and Active Directory"},{"content":"This post was updated on August 17th, 2020.\nThis is the fifth post in my series on setting up a basic Always On VPN deployment. In this post I will be covering the configuration of the device tunnel. Links to each individual post in this series can be found below.\nAlways On VPN - Basic Deployment Guide\nAlways On VPN - Certificates and Active Directory\nAlways On VPN - VPN and NPS Server Configuration\nAlways On VPN - User Tunnel\nAlways On VPN - Troubleshooting\nDevice Tunnel Unlike the user tunnel, the device tunnel does not need to be manually created before being deployed. An XML file containing the configuration information for the device tunnel can be manually created and then directly deployed to devices.\nHere is an example of a basic device tunnel XML configuration file.\n\u0026lt;VPNProfile\u0026gt; \u0026lt;AlwaysOn\u0026gt;true\u0026lt;/AlwaysOn\u0026gt; \u0026lt;DeviceTunnel\u0026gt;true\u0026lt;/DeviceTunnel\u0026gt; \u0026lt;DnsSuffix\u0026gt;lab.configured.tech\u0026lt;/DnsSuffix\u0026gt; \u0026lt;RegisterDNS\u0026gt;true\u0026lt;/RegisterDNS\u0026gt; \u0026lt;TrustedNetworkDetection\u0026gt;lab.configured.tech\u0026lt;/TrustedNetworkDetection\u0026gt; \u0026lt;NativeProfile\u0026gt; \u0026lt;Servers\u0026gt;aovpn.configured.tech\u0026lt;/Servers\u0026gt; \u0026lt;RoutingPolicyType\u0026gt;SplitTunnel\u0026lt;/RoutingPolicyType\u0026gt; \u0026lt;NativeProtocolType\u0026gt;IKEv2\u0026lt;/NativeProtocolType\u0026gt; \u0026lt;Authentication\u0026gt; \u0026lt;MachineMethod\u0026gt;Certificate\u0026lt;/MachineMethod\u0026gt; \u0026lt;/Authentication\u0026gt; \u0026lt;DisableClassBasedDefaultRoute\u0026gt;true\u0026lt;/DisableClassBasedDefaultRoute\u0026gt; \u0026lt;/NativeProfile\u0026gt; \u0026lt;Route\u0026gt; \u0026lt;Address\u0026gt;192.168.1.200\u0026lt;/Address\u0026gt; \u0026lt;PrefixSize\u0026gt;32\u0026lt;/PrefixSize\u0026gt; \u0026lt;/Route\u0026gt; \u0026lt;Route\u0026gt; \u0026lt;Address\u0026gt;192.168.1.201\u0026lt;/Address\u0026gt; \u0026lt;PrefixSize\u0026gt;32\u0026lt;/PrefixSize\u0026gt; \u0026lt;/Route\u0026gt; \u0026lt;/VPNProfile\u0026gt; There are a few environment specific values in this XML that will need to be modified before it can be deployed.\nDnsSuffix (Line 4) - This value is used to assign a DNS suffix to the VPN interface. This should be the internal FQDN of the enterprise network. Multiple values can be specified in a comma separated list TrustedNetworkDetection (Line 6) - This value is used to determine when the VPN connection should be attempted. If the device is on a trusted network, the VPN will not attempt to connect. This should be the internal FQDN of the enterprise network. Multiple values can be specified in a comma separated list Servers (Line 8) - This value is used to specify the external DNS name and/or IP of the VPN server. Multiple values can be specified in a comma separated list Route (Lines 16 - 23) - These values are used to specify which network resources can be reached through the VPN tunnel. The device tunnel should be limited to access resources required for device management (Domain Controllers, PKI, DNS, Configuration Manager). Additional routes can be added by duplicating the tag After editing these values, save the XML file as DeviceProfile.xml.\nOptional - Advanced XML Configuration This example XML file will work for a basic deployment. However, more advanced deployments can require additional edits to the XML file. I am writing another post about more advanced XML configuration options. I\u0026rsquo;ll link to that post here once it is live.\nDeploy the XML Configuration File The Always On VPN profile(s) can be deployed using either PowerShell or Intune. In this post I will be using PowerShell and Configuration Manager. For information on using Intune to deploy Always On VPN, refer to these posts (Link1, Link2, Link3)\nThe PowerShell script to deploy the device tunnel can be found here (New-AovpnDeviceTunnel.ps1). This script will handle the creation of the VPN tunnel. For troubleshooting purposes, the script writes to a log file: C:\\ProgramData\\AOVPN\\Install-AOVPN-Device.log.\nDownload the script and optionally edit these lines:\nLine 33 - The default VPN connection name Line 37 - The registry key used for detection Line 38 - The registry value used for detection Line 39 - The version number to set the registry value to for detection Copy the New-AovpnDeviceTunnel.ps1 script and the DeviceProfile.xml file to the Configuration Manager content source location on the network.\nOpen the Configuration Manager console and navigate to Software Library \u0026gt; Application Management \u0026gt; Applications In the ribbon, click Create Application In the window that opens, select Manually specify the application information and click Next Enter a name for the application (Always On VPN Device Tunnel) and click Next Optionally enter information on the Software Center page and click Next On the Deployment Types page, click Add\u0026hellip; A new window opens In the Type menu, select Script Installer and click Next Enter a name for the deployment type \u0026ldquo;Always On VPN Device Tunnel\u0026rdquo; and click Next In the Content location box, browse to the network location where the PowerShell script and XML file are stored In the Installation program box, enter this command If needed, change the names of the PowerShell script and XML file to match your files PowerShell.exe -ExecutionPolicy Bypass -File \u0026#34;New-AovpnDeviceTunnel.ps1\u0026#34; -xmlFilePath DeviceProfile.xml After entering the installation command, click Next At the Detection Method page, click Add Clause\u0026hellip; In the Setting Type menu, select Registry In the Hive menu, select HKEY_LOCAL_MACHINE In the Key box, enter the registry key that matches the key specified on line 37 of the New-AovpnDeviceTunnel script In the Value box, enter the value from line 38 of the New-AovpnDeviceTunnel script In the Data Type menu, select Integer Select This registry setting must satisfy the following rule to indicate the presence of this application In the Operator menu, select Equals In the Value box, enter the version number that matches the version specified on line 39 of the New-AovpnDeviceTunnel script Click OK to close the Detection Rule window At the Detection Method page, click Next At the User Experience page, select these options Install for System Whether or not a user is logged on Hidden Change the Maximum allowed runtime to 15 minutes Click Next Click Summary to go to the summary screen Click Next to complete the creation of the detection method Click Close At the Deployment Types page, click Next Click Next to complete the creation of the application Click Close The application to deploy the Always On VPN Device Tunnel has been created. The next steps are to distribute content for the application and deploy the application.\nI have also created a script that can be used to remove Always On VPN Device Tunnels from computers. That script can be found here Remove-AovpnDeviceTunnel.ps1. This script could be added to the application as the uninstall program.\nThis completes the device tunnel configuration portion of the deployment. The next post in the series is Always On VPN - Troubleshooting.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/always-on-vpn-device-tunnel/","summary":"\u003cp\u003e\u003cstrong\u003eThis post was updated on August 17th, 2020.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThis is the fifth post in my series on setting up a basic Always On VPN deployment. In this post I will be covering the configuration of the device tunnel. Links to each individual post in this series can be found below.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ca href=\"/always-on-vpn-basic-deployment-guide/\"\u003eAlways On VPN - Basic Deployment Guide\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-certificates-and-active-directory/\"\u003eAlways On VPN - Certificates and Active Directory\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-vpn-and-nps-server-configuration/\"\u003eAlways On VPN - VPN and NPS Server Configuration\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-user-tunnel/\"\u003eAlways On VPN - User Tunnel\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-troubleshooting/\"\u003eAlways On VPN - Troubleshooting\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e","title":"Always On VPN - Device Tunnel"},{"content":"This post was updated on August 17th, 2020.\nThis is the fourth post in my series on setting up a basic Always On VPN deployment. In this post I will be covering the configuration of the user tunnel. Links to each individual post in this series can be found below.\nAlways On VPN - Basic Deployment Guide\nAlways On VPN - Certificates and Active Directory\nAlways On VPN - VPN and NPS Server Configuration\nAlways On VPN - Device Tunnel\nAlways On VPN - Troubleshooting\nUser Tunnel The user tunnel must first be manually created and connected. The configuration data from that connection will then be exported into an XML file. Finally that XML file will be deployed to other systems to automatically create the tunnel.\nManually Create the Connection Log into a Windows 10 1607 or newer computer with a user account that is a member of the AOVPN Users Active Directory group. The user account must also be a local administrator on the computer. Open certmgr.msc and ensure the user certificate has been successfully enrolled.\nOpen the Windows 10 Settings app Navigate to Network \u0026amp; Internet \u0026gt; VPN Click Add a VPN connection VPN provider - Windows (built-in) Connection name - Template Server name or address - The external FQDN of the VPN server (aovpn.corp.com) VPN type - IKEv2 Type of sign-in info - Certificate Click Save to close the configuration window Open the network connections window either by clicking Change adapter options or by running ncpa.cpl at the command line In the network connections window, right click on the Template VPN connection and select Properties Navigate to the Security tab\nEnsure Type of VPN is set to IKEv2\nChange Data encryption to Maximum strength encryption (disconnect if server declines)\nUnder the Use Extensible Authentication Protocol (EAP) option, select Microsoft: Protected EAP (PEAP) (encryption enabled)\nClick Properties\nThe Protected EAP Properties window is now open\nUnder Connect to these servers, type the FQDN of the NPS server\nUnder Trusted Root Certification Authorities, select the Root CA that issued the user authentication certificate\nUnder Notifications before connecting, select Don\u0026rsquo;t ask user to authorize new servers or trusted CAs\nUnder Select Authentication Method, select Smart Card or other certificate\nClick Configure\nThe Smart Card or other Certificate Properties window is now open Select User a certificate on this computer and click Advanced Check the Certificate Issuer box Select the Root CA from the list Click OK Under Connect to these servers, type the FQDN of the NPS server Under Trusted Root Certification Authorities, select the Root CA that issued the user authentication certificate Check the Don\u0026rsquo;t prompt user to authorize new servers or trusted certification authorities box Click OK 3 times to save and exit the VPN properties windows This next step is optional and only needs to be run if the IKEv2 security settings were modified during the setup of the VPN server.\nOpen an administrative PowerShell window Run this script to update the IPsec security parameters for IKEv2 $connection = \u0026#34;Template\u0026#34; Set-VpnConnectionIPsecConfiguration -ConnectionName $connection -AuthenticationTransformConstants SHA256128 -CipherTransformConstants AES128 -DHGroup Group14 -EncryptionMethod AES128 -IntegrityCheckMethod SHA256 -PFSgroup PFS2048 -Force For more information about configuring enhanced IKEv2 security settings, refer to this post.\nNow that the VPN adapter has been created, the next step is to establish a VPN tunnel connection. Connect the computer to a network that is outside of the corporate network, select the Template VPN adapter, and click Connect. If the connection is successful, then move on to the next section. If the connection was not successful, refer to the Troubleshooting section of this guide.\nCreate the XML Configuration File Once the manually created VPN connection has been successfully connected at least once, the next step is to create a XML file containing the connection settings that can be deployed to additional systems.\nThe easiest way to create the XML file is to use PowerShell to extract the settings from the manually created VPN connection. These settings can then be written to an XML file. The script to extract and format these settings can be found here (Get-VPNClientProfileXML.ps1)\nLog into the computer where the user tunnel was created Ensure the logged-in user has local administrator rights on the system Download the Get-VPNClientProfileXML.ps1 script Open an administrative PowerShell window and run the Get-VPNClientProfileXML.ps1 script Get-VPNClientProfileXML.ps1 -ConnectionName \u0026#34;Template\u0026#34; -xmlFilePath \u0026#34;C:\\Temp\\UserProfile.xml\u0026#34; This will generate a new XML file containing the configuration data from the Template VPN connection.\nOptional - Advanced XML Configuration This example XML file will work for a basic deployment. However, more advanced deployments can require additional edits to the XML file. I am writing another post about more advanced XML configuration options. I\u0026rsquo;ll link to that post here once it is live.\nDeploy the XML Configuration File The Always On VPN profile(s) can be deployed using either PowerShell or Intune. In this post I will be using PowerShell and Configuration Manager. For information on using Intune to deploy Always On VPN, refer to these posts (Link1, Link2, Link3)\nThe PowerShell script to deploy the user tunnel can be found here (New-AovpnUserTunnel.ps1). This script will handle the creation of the VPN tunnel. For troubleshooting purposes, the script writes to a log file: C:\\ProgramData\\AOVPN\\Install-AOVPN-User.log.\nDownload the script and optionally edit these lines:\nLine 33 - The default VPN connection name Line 37 - The registry key used for detection Line 38 - The registry value used for detection Line 39 - The version number to set the registry value to for detection Copy the New-AovpnUserTunnel.ps1 script and the UserProfile.xml file to the Configuration Manager content source location on the network.\nOpen the Configuration Manager console and navigate to Software Library \u0026gt; Application Management \u0026gt; Applications In the ribbon, click Create Application In the window that opens, select Manually specify the application information and click Next Enter a name for the application (Always On VPN User Tunnel) and click Next Optionally enter information on the Software Center page and click Next On the Deployment Types page, click Add\u0026hellip; A new window opens In the Type menu, select Script Installer and click Next Enter a name for the deployment type \u0026ldquo;Always On VPN User Tunnel\u0026rdquo; and click Next In the Content location box, browse to the network location where the PowerShell script and XML file are stored In the Installation program box, enter this command If needed, change the names of the PowerShell script and XML file to match your files PowerShell.exe -ExecutionPolicy Bypass -File \u0026#34;New-AovpnUserTunnel.ps1\u0026#34; -xmlFilePath UserProfile.xml After entering the installation command, click Next At the Detection Method page, select Use a custom script to detect the presence of this deployment type: and click Edit\u0026hellip; In the Script type menu, select PowerShell In the Script contents box, enter this script On line 1 of the script, modify the version number to match the version specified in New-AovpnUserTunnel.ps1 On line 2 of the script, modify the registry key to match the key specified in New-AovpnUserTunnel.ps1 On Line 3 of the script, modify the registry value to match the value specified in New-AovpnUserTunnel.ps1 $NewVersion = 1 $RegKey = \u0026#34;SOFTWARE\\ConfigJon\u0026#34; $RegValue = \u0026#34;AOVPNUserTunnelVersion\u0026#34; $Username = Get-WmiObject -Class Win32_ComputerSystem | Select-Object username $UserExists = [string]::IsNullOrEmpty($Username.Username) if(!($UserExists)) { $User = New-Object System.Security.Principal.NTAccount($Username.Username) $Sid = $User.Translate([System.Security.Principal.SecurityIdentifier]) $SidValue = $Sid.Value New-PSDrive -PSProvider registry -Root HKEY_USERS -Name HKU | Out-Null $Version = Get-ItemProperty \u0026#34;HKU:$($SidValue)\\$($RegKey)\u0026#34; -ErrorAction SilentlyContinue | Select-Object -ExpandProperty $RegValue if($Version -eq $NewVersion){Write-Output \u0026#34;Installed\u0026#34;} } After entering the detection script, click OK to close the Script Editor window At the Detection Method page, click Next At the User Experience page, select these options Install for System Only when a user is logged on Hidden Change the Maximum allowed runtime to 15 minutes Click Next Click Summary to go to the summary screen Click Next to complete the creation of the detection method Click Close At the Deployment Types page, click Next Click Next to complete the creation of the application Click Close The application to deploy the Always On VPN User Tunnel has been created. The next steps are to distribute content for the application and deploy the application.\nI have also created a script that can be used to remove Always On VPN User Tunnels from computers. That script can be found here Remove-AovpnUserTunnel.ps1. This script could be added to the application as the uninstall program.\nThis completes the user tunnel configuration portion of the deployment. The next post in the series is Always On VPN - Device Tunnel.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/always-on-vpn-user-tunnel/","summary":"\u003cp\u003e\u003cstrong\u003eThis post was updated on August 17th, 2020.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThis is the fourth post in my series on setting up a basic Always On VPN deployment. In this post I will be covering the configuration of the user tunnel. Links to each individual post in this series can be found below.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ca href=\"/always-on-vpn-basic-deployment-guide/\"\u003eAlways On VPN - Basic Deployment Guide\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-certificates-and-active-directory/\"\u003eAlways On VPN - Certificates and Active Directory\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-vpn-and-nps-server-configuration/\"\u003eAlways On VPN - VPN and NPS Server Configuration\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-device-tunnel/\"\u003eAlways On VPN - Device Tunnel\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-troubleshooting/\"\u003eAlways On VPN - Troubleshooting\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e","title":"Always On VPN - User Tunnel"},{"content":"This is the third post in my series on setting up a basic Always On VPN deployment. In this post I will be covering the configuration of the VPN server and the NPS server. I will also talk about the network and firewall configuration. Links to each individual post in this series can be found below.\nAlways On VPN - Basic Deployment Guide\nAlways On VPN - Certificates and Active Directory\nAlways On VPN - User Tunnel\nAlways On VPN - Device Tunnel\nAlways On VPN - Troubleshooting\nThe VPN Server In this deployment, the role of the VPN server will be filled by Windows Server 2019 running the Routing and Remote Access Server role. This post will provide instructions for both domain-joined and non-domain-joined VPN servers. For the best security, the recommendation is to not join the VPN server to the internal AD domain.\nNetwork Placement The server will be located in a perimeter network. If a perimeter network or DMZ is not available, the server could be placed on a separate VLAN where access to the rest of the corporate network is controlled by ACLs. The server could also be placed directly on the corporate network, but this is the least secure option.\nNetwork Configuration The server will have 2 network adapters, 1 internet facing adapter and 1 intranet facing adapter.\nExternal Adapter\nAssigned a static IP Address and Gateway IP\nOnly the IPv4 and IPv6 protocols should be enabled\nInternal Adapter\nAssigned a static IP Address Additional Notes\nThe IP addresses assigned to the adapters must be from different subnets The gateway IP should only be configured on the external adapter Access to internal resources should be configured using static routes #Create a new static route New-NetRoute -AddressFamily IPv4 -DestinationPrefix 10.0.0.0/8 -InterfaceAlias \u0026#39;Internal\u0026#39; -NextHop 192.168.1.254 #View existing static routes Get-NetRoute -InterfaceAlias \u0026#39;Internal\u0026#39; If the VPN server is domain-joined, the DNS servers should be specified on the internal adapter While this guide assumes a dual-interface configuration, it is possible to configure the VPN server with a single network interface. For more information about network interface configuration on the VPN server, refer to this post. Firewall Configuration Traffic allowed from the internet facing firewall to the external network adapter of the VPN server If using IKEv2 UDP 500 (IKE) UDP 4500 (IPSec NAT Traversal) If using SSTP TCP 443 (SSL) Traffic allowed to and from the internal network adapter of the VPN server to the internal network UDP 1812 (RADIUS Authentication) UDP 1813 (RADIUS Accounting) RADIUS traffic can also use UDP 1645 and UDP 1646, however, these are legacy ports and should not be needed when using modern clients and servers If the VPN server is domain-joined, the server will need to be able to communicate with a domain controller. If there is not a read-only domain controller in the perimeter network, then these ports will need to be opened to domain controller on the internal network. Note that this is a potential security risk.\nTCP and UDP 53 (DNS) TCP and UDP 88 (Kerberos) TCP 135 (RPC Endpoint Mapper) TCP and UDP 389 (LDAP) TCP 445 (SMB) TCP 636 (LDAPS) TCP 3268 (LDAP GC) TCP 3269 (LDAPS GC) Feature Installation and Configuration These steps will walk through the installation and configuration of the Routing and Remote Access Server role. These steps should be preformed on the VPN server.\nOpen an administrative PowerShell window and run this command to install the Routing and Remote Access Server role Install-WindowsFeature DirectAccess-VPN -IncludeManagementTools Open the Server Manager and click Open the Getting Started Wizard A refresh of the server manager may be required for the notification to appear In the Configure Remote Access window that opens, select Deploy VPN only The Routing and Remote Access console should now be open Right click on the VPN server and select Configure and Enable Routing and Remote Access The Routing and Remote Access Server Setup Wizard should open At the Welcome page, click Next Select Custom configuration and click Next Select VPN access and click Next Click Finish to complete the setup wizard When prompted to start the Routing and Remote Access service, click Start service If no prompt to start the service appears, right click on the VPN server, select All Tasks, and click Start Right click on the VPN server and select Properties Security tab Change the Authentication provider to RADIUS Authentication and click Configure In the window that opens, click Add Enter the FQDN of the NPS server Enter a shared secret This should be a long random string of characters. Save this password somewhere safe. It will be needed again during the NPS server configuration Optionally change the time-out or port settings and click OK twice Optionally change the Accounting provider IPv4 tab Choose to use DHCP or a static address pool for allocating IP addresses If using DHCP, ensure an IP Helper and firewall rules have been created to allow clients to find and communicate with the DHCP server. If using a static address pool, ensure the IP addresses have been excluded from being used by the DHCP server Set the adapter to the internal network interface Click OK to close the Properties window In the Routing and Remote Access console, right click on Ports and select Properties Select WAN Miniport (IKEv2) and click Configure Ensure Remote access connections (inbound only) is checked Ensure Demand-dial routing connections (inbound and outbound) is checked Optionally modify the maximum ports setting and click OK Configure the other unused RAS/Routing ports (L2TP, PPTP, SSTP) Uncheck both checkboxes This concludes the main setup of the Routing and Remote Access role. However, there are additional steps that can be done to improve security as well as add support for device tunnels.\nImprove IKEv2 Security The default security settings for an IKEv2 connection in the Routing and Remote Access configuration are not as good as they could be. The settings used for the IKEv2 connections can be set to a more secure level on the server. If these settings are set on the server, the same settings will need to be configured on the client side before the tunnel will connect.\nConnect to the VPN server and open an administrative PowerShell window Run this command to update the IPsec security parameters for IKEv2 Set-VpnServerConfiguration -CustomPolicy -AuthenticationTransformConstants SHA256128 -CipherTransformConstants AES128 -DHGroup Group14 -EncryptionMethod AES128 -IntegrityCheckMethod SHA256 -PFSgroup PFS2048 -SADataSizeForRenegotiationKilobytes 102400 Restart the Remote Access Management service to allow the changes to take effect This PowerShell command is sourced from this post.\nEnable IKEv2 Fragmentation It\u0026rsquo;s possible that the IKEv2 traffic can be split apart if the IP packets are too large. Windows 10 will support IKEv2 fragmentation by default, however this support needs to be manually enabled in Windows Server. Note that this feature only works in Windows Server 1803 and newer. To enable support for IKEv2 fragmentation, run this PowerShell command:\nNew-ItemProperty -Path \u0026#34;HKLM:\\SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\Ikev2\\\u0026#34; -Name EnableServerFragmentation -PropertyType DWORD -Value 1 -Force To read more about IKEv2 fragmentation, refer to this post.\nEnable Support for Device Tunnels The default configuration of the Routing and Remote Access server role does not allow machine certificate authentication. If device tunnels will be used, this needs to be enabled.\nConnect to the VPN server and open an administrative PowerShell window Run this script to enable machine certificate authentication Modify the first line of the script with the common name of the root CA before running the script $VPNRootCertAuthority = \u0026#34;Common Name of trusted root certification authority\u0026#34; $RootCACert = (Get-ChildItem -Path cert:LocalMachine\\root | Where-Object {$_.Subject -Like \u0026#34;*$VPNRootCertAuthority*\u0026#34; }) Set-VpnAuthProtocol -UserAuthProtocolAccepted Certificate, EAP -RootCertificateNameToAccept $RootCACert -PassThru This PowerShell script is sourced from this page.\nThe NPS Server In this deployment, the role of the NPS server will be filled by Windows Server 2019 running the Network Policy Server role. This server should be domain-joined.\nNetwork Placement and Configuration The server will be located behind the internal firewall on the internal network. The server should have a single network adapter with a static IP address or a DHCP reservation.\nFirewall Configuration The following ports should be allowed through the internal firewall and the Windows firewall between the VPN server and the NPS server.\nUDP 1812 (RADIUS Authentication) UDP 1813 (RADIUS Accounting) RADIUS traffic can also use UDP 1645 and UDP 1646, however, these are legacy ports and should not be needed when using modern clients and servers Windows Server 2019 has a bug where the Windows Firewall rules for the NPS role will appear as active but not actually be working. If communication on these ports does not seem to be making it through the Windows Firewall, open an administrative command prompt and run this command.\nsc.exe sidtype IAS unrestricted For more information about this bug and the solution, see this post.\nFeature Installation and Configuration These steps will walk through the installation and configuration of the Network Policy Server role. These steps should be preformed on the NPS server.\nOpen an administrative PowerShell window and run this command to install the Network Policy Server role Install-WindowsFeature NPAS -IncludeManagementTools Open the Network Policy Server console Right click on the NPS server and select Register server in Active Directory Click OK at the confirmation dialog and again at the success dialog In the Network Policy Server console, expand RADIUS Clients and Servers Right click on RADIUS Clients and select New Ensure Enable this RADIUS client is checked In the Friendly name box, enter the name of the VPN server In the Address (IP or DNS) box, enter the IP address of the internal network interface on the VPN server Shared Secret Ensure the Manual box is checked Enter the Shared Secret that was created during the VPN server setup Click OK to close the window Select the RADIUS server, ensure RADIUS server for Dial-Up or VPN Connections is selected, and click Configure VPN or Dial-Up In the window that appears, select Virtual Private Network (VPN) Connections and click Next Select the VPN server and click Next On the Authentication Methods page Uncheck Microsoft Encrypted Authentication version 2 (MS-CHAPv2) Check Extensible Authentication Protocol Set the Type to Microsoft: Protected EAP (PEAP) Click Configure Select Secured password (EAP-MSCHAP v2) and click Remove Click Add, select Smart Card or other certificate, and click OK Click Next At the User Groups page Click Add and select the AOVPN Users AD group Click Next At the IP Filters page, click Next At the Encryption Settings page, click Next At the Realm Name page, click Next Click Finish to complete the wizard This completes the VPN and NPS server configuration portion of the deployment. The next post in the series is Always On VPN - User Tunnel.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/always-on-vpn-vpn-and-nps-server-configuration/","summary":"\u003cp\u003eThis is the third post in my series on setting up a basic Always On VPN deployment. In this post I will be covering the configuration of the VPN server and the NPS server. I will also talk about the network and firewall configuration. Links to each individual post in this series can be found below.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ca href=\"/always-on-vpn-basic-deployment-guide/\"\u003eAlways On VPN - Basic Deployment Guide\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-certificates-and-active-directory/\"\u003eAlways On VPN - Certificates and Active Directory\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-user-tunnel/\"\u003eAlways On VPN - User Tunnel\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-device-tunnel/\"\u003eAlways On VPN - Device Tunnel\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/always-on-vpn-troubleshooting/\"\u003eAlways On VPN - Troubleshooting\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e","title":"Always On VPN - VPN and NPS Server Configuration"},{"content":"Task Sequence Downloads BIOS Management - Example Task Sequences\nDell Dell BIOS Password Management\nDell BIOS Settings Management\nWorking with the Dell Command | PowerShell Provider\nHP HP BIOS Password Management\nHP BIOS Settings Management\nInstalling the HP Client Management Script Library\nLenovo Lenovo BIOS Password Management\nLenovo BIOS Settings Management\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/bios-/-firmware-configuration/","summary":"\u003ch3 id=\"task-sequence-downloads\"\u003eTask Sequence Downloads\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ca href=\"/bios-management-example-task-sequences/\"\u003eBIOS Management - Example Task Sequences\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003ch3 id=\"dell\"\u003eDell\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ca href=\"/dell-bios-password-management/\"\u003eDell BIOS Password Management\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/dell-bios-settings-management/\"\u003eDell BIOS Settings Management\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/working-with-the-dell-command-powershell-provider/\"\u003eWorking with the Dell Command | PowerShell Provider\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003ch3 id=\"hp\"\u003eHP\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ca href=\"/hp-bios-password-management/\"\u003eHP BIOS Password Management\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/hp-bios-settings-management/\"\u003eHP BIOS Settings Management\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/installing-the-hp-client-management-script-library/\"\u003eInstalling the HP Client Management Script Library\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003ch3 id=\"lenovo\"\u003eLenovo\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ca href=\"/lenovo-bios-password-management/\"\u003eLenovo BIOS Password Management\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/lenovo-bios-settings-management/\"\u003eLenovo BIOS Settings Management\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e","title":"BIOS / Firmware Configuration"},{"content":"If you\u0026rsquo;ve been keeping up with my blog posts, you\u0026rsquo;ll know that HP natively provides a few WMI classes and methods to the WIndows OS. These WMI classes work great for managing BIOS settings, but what if I want to manage Firmware updates or work with HP Softpaqs? One answer is to use the HP Client Management Script Library. The HP CMSL is a bundle of PowerShell modules created by HP for the purpose of managing HP firmware and drivers from the command line.\nHP recently released the latest Client Management Script Library modules to the PowerShell gallery. I thought this provided a good opportunity to take a deeper look at what this tool offers. In this post I\u0026rsquo;ll be taking about the different ways to install the HP CSML.\nIf you\u0026rsquo;re just here for the script, you can find it on my GitHub: https://github.com/ConfigJon/Firmware-Management/blob/master/HP/Install-HPCMSL.ps1\nPrerequisites The only prerequisite for running the Client Management Script Library in full windows is PowerShell version 5.1 or newer. Before the CMSL can be run from WinPE, these components need to be added to the boot image.\nMicrosoft .NET (WinPE-NetFx) Scripting (WinPE-Scripting) Scripting (WinPE-WMI) Windows PowerShell (WinPE-PowerShell) The WinPE-Scripting and WinPE-WMI components are included in SCCM boot images by default. The WinPE-WMI and WinPE-PowerShell components need to be added in the Optional Components tab of the boot image Properties window.\nInstallation There are 3 main ways to install the HP Client Management Script Library.\nInstall using the executable installer provided by HP Install directly from the PowerShell gallery using Install-Module Copy the CMSL module files into the PowerShell modules directory Executable Install HP provides an installer than can be run in a full Windows OS. The installer can be downloaded from HERE. The executable is an InnoSetup installer and will take any of the standard InnoSetup switches. A basic silent install of the executable would look like this.\nhp-cmsl-latest.exe /VERYSILENT PowerShell Gallery Install HP has also made the Client Management Script Library modules available on the PowerShell gallery. This means that any computer with internet access can install the modules using the Install-Module PowerShell cmdlet.\n#Install the HPCMSL modules and prompt for install and license agreement Install-Module -Name HPCMSL #Install the HPCMSL modules and suppress the install and license agreement prompts Install-Module -Name HPCMSL -Force -AcceptLicense This seems like all that should be required for the install. However there are a couple pre-requisites when installing directly from the PowerShell Gallery.\nThe NuGet Package Provider needs to be updated The PowerShellGet module needs to be updated If you frequently install PowerShell modules on your system, these requirements may already be taken care of. However, on systems that haven\u0026rsquo;t installed modules from the PowerShell Gallery, both of these items will need updates.\nIf the current version of PowerShellGet is less than 2.0.1, there is a bug where after installing the latest version, a new PowerShell session needs to be opened to access the updated version.\nFile Copy Install Both the executable install and the PowerShell Gallery install result in some files and folders being copied into Program Files\\WindowsPowerShell\\Modules. So instead of using one of those automated install options, the files could just be manually copied.\nThese are the folders that need to be copied.\nThese folders can be obtained in multiple ways. The HP Client Management Script Library could be installed on a machine using either the executable or Install-Module cmdlet. Then the files could be copied from Program Files\\WindowsPowerShell\\Modules. Alternatively, the files could be downloaded directly from the PowerShell Gallery.\nHP.ClientManagement HP.Firmware HP.Private HP.Repo HP.Sinks HP.Softpaq HP.Utility HPCMSL Note that in order for the modules to be detected by PowerShell, they need to be correctly named. The folder name needs to be the same as the name of the module it contains.\nThis is the method that would need to be used when installing the HP Client Management Script Library in WinPE. This is because WinPE doesn\u0026rsquo;t support installing Modules directly from PowerShell Gallery and also does not allow for installing from an executable.\nInstall-HPCMSL.ps1 I decided to create a PowerShell script to automate the PowerShell Gallery and file copy install methods for the HP Client Management Script Library. The script can be run either in online mode or offline mode.\nWhen running the script in online mode, it will reach out to the PowerShell Gallery and compare the version of the HPCMSL module against the locally installed version. If the PowerShell Gallery version is newer, it will be automatically downloaded and installed. The script also has logic to automatically install and update the NuGet Package Provider and the PowerShellGet module. Running the script in online mode requires a full Windows OS with internet access.\nWhen running the script in offline mode, it will look for the HPCMSL modules in a local folder. The script will compare the versions of the modules in the folder against the currently installed versions. If the modules need to be updated, the new files will be copied.\nThe script has one optional parameter.\nModulePath – This parameter is used to specify the location of the HPCMSL module source files. If the parameter is specified the script will work in offline mode. Otherwise the script will run in online mode. This parameter should be specified when the script is running in WinPE or when the system does not have internet access.\nExamples Run the script in online mode\nInstall-HPCMSL.ps1 Run the script in offline mode\nInstall-HPCMSL.ps1 -ModulePath HPCMSL IMPORTANT: When the script is running in offline mode, it is looking for a specific folder structure. Each of the HP Client Management Script Library modules need to be placed in the root of the folder specified in the ModulePath parameter. These folders need to be named exactly how they are named by HP.\nHP.ClientManagement HP.Firmware HP.Private HP.Repo HP.Sinks HP.Softpaq HP.Utility HPCMSL Each one of these module folders should have a single first-level sub-folder. The name of this sub-folder should be the version of the included module. If the module files are obtained from a previous installation using either the executable or Install-Module, the folder structure will already be correct. If the module files are obtained directly from the PowerShell Gallery, this folder structure will need to be created.\nIn the above example, the script is called with the ModulePath parameter referencing a folder named HPCMSL. This folder is located in the same directory as the Install-HPCMSL.ps1 file. The HPCMSL folder then contains all of the properly named module folders, and each module folder contains a version sub-folder which then contains the actual module files.\nThis script can be run as part of a Configuration Manager task sequence to install the modules either in WinPE or the full Windows OS. The task sequence step would look like this:\nLogging The script will create a log file named Install-HPCMSL.log. When running outside of a task sequence, the log file will be located in ProgramData\\BiosScripts\\HP. When running inside of a task sequence, the log file will be located in the _SMSTSLogPath.\nAdditional Reading I\u0026rsquo;m planning some future blog posts to cover the functionality of the HP Client Management Script Library. I\u0026rsquo;ll link to those posts here as they happen. For now, you can read more about using the HP Client Management Script Library in HP\u0026rsquo;s official documentation.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/installing-the-hp-client-management-script-library/","summary":"\u003cp\u003eIf you\u0026rsquo;ve been keeping up with my blog posts, you\u0026rsquo;ll know that HP natively provides a few WMI classes and methods to the WIndows OS. These WMI classes work great for managing BIOS settings, but what if I want to manage Firmware updates or work with HP Softpaqs? One answer is to use the \u003cstrong\u003e\u003ca href=\"https://ftp.hp.com/pub/caps-softpaq/cmit/hp-cmsl.html\"\u003eHP Client Management Script Library\u003c/a\u003e\u003c/strong\u003e. The HP CMSL is a bundle of PowerShell modules created by HP for the purpose of managing HP firmware and drivers from the command line.\u003c/p\u003e","title":"Installing the HP Client Management Script Library"},{"content":"UPDATE September 16th, 2020 - The scripts included in these downloads are currently outdated. I plan to update this post soon with the latest script versions.\nNow that I have working BIOS management scripts for Dell, HP, and Lenovo, I figured I would put them all together in a few example task sequences. This post will also act as a hub for my BIOS management posts.\nCurrent BIOS Management Posts Dell BIOS Password Management\nDell BIOS Settings Management\nHP BIOS Password Management\nHP BIOS Settings Management\nLenovo BIOS Password Management\nLenovo BIOS Settings Management\nExample Task Sequences My original goal with these scripts was to manage BIOS settings and passwords in a task sequence without needing to download any content. However, after using the scripts for awhile, I\u0026rsquo;ve seen where it can still make sense to have the scripts in a package. So I\u0026rsquo;ve decided to make two different example task sequences available. Both task sequences run the same steps, the only difference is the amount of content required.\nBIOS Management TS (Minimal Content)Download\nThe minimal content task sequence makes use of the option to embed a PowerShell script directly into the Run PowerShell Script step. The only outside content required in this task sequence is the files needed to install the Dell BIOS Provider PowerShell module.\nBIOS Management TS (Full Content)Download\nThe full content task sequence runs the PowerShell scripts from a package. The scripts also point to CSV files located in the same package.\nEach of the example task sequence downloads contains 3 separate task sequences.\nNested - BIOS - Set Password Variables - This task sequence is used to set variables that will be supplied to the BIOS management scripts. Nested - BIOS - Manage Passwords - This task sequence is used to set, change, or clear the BIOS password on devices. Nested - BIOS - Manage Settings - This task sequence is used to set BIOS settings on devices. These task sequences are meant to be run as nested task sequences in a parent deploy task sequence.\nAdditional Notes In the Manage Passwords task sequence, I have the steps attempting to set the BIOS password and check it against 6 old passwords. If that many old passwords are not required, simply remove the variables and disable any of the extra steps. For HP and Lenovo, ensure that the SMSTSPasswordRetry switch is not set if the script will not be run again.\nAt the top of the BIOS settings task sequence, there is a \u0026ldquo;Collect System Information\u0026rdquo; step. I put this step here, as some of the settings groups depend on variables set by it. Normally this step would be run near the top of the parent task sequence, so feel free to move it. As long as it runs before the BIOS settings task sequence, it should be fine.\nThese task sequences are just examples and have not been extensively tested. I\u0026rsquo;m sure there are changes and optimizations that could be made. If you have suggestions or questions, feel free to send me a message on Twitter @ConfigJon.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/bios-management-example-task-sequences/","summary":"\u003cp\u003e\u003cstrong\u003eUPDATE September 16th, 2020 - The scripts included in these downloads are currently outdated. I plan to update this post soon with the latest script versions.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eNow that I have working BIOS management scripts for Dell, HP, and Lenovo, I figured I would put them all together in a few example task sequences. This post will also act as a hub for my BIOS management posts.\u003c/p\u003e\n\u003ch3 id=\"current-bios-management-posts\"\u003eCurrent BIOS Management Posts\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ca href=\"/dell-bios-password-management/\"\u003eDell BIOS Password Management\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/dell-bios-settings-management/\"\u003eDell BIOS Settings Management\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/hp-bios-password-management/\"\u003eHP BIOS Password Management\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/hp-bios-settings-management/\"\u003eHP BIOS Settings Management\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/lenovo-bios-password-management/\"\u003eLenovo BIOS Password Management\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003e\u003ca href=\"/lenovo-bios-settings-management/\"\u003eLenovo BIOS Settings Management\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e","title":"BIOS Management - Example Task Sequences"},{"content":"This post was updated on September 11th, 2020.\nUpdate: Dell does now provide native WMI classes to manage BIOS settings on newer models. For more information, see this post: Dell BIOS Settings Management - WMI. For information on using the Dell PowerShell module to configure settings on older models, continue reading this post.\nThis post is one of 3 posts in my series on managing BIOS settings using PowerShell. I\u0026rsquo;ve also written about HP and Lenovo. In this post I\u0026rsquo;ll be talking about using PowerShell to manage Dell BIOS settings.\nThe script can be downloaded from my GitHub: https://github.com/ConfigJon/Firmware-Management/blob/master/Dell/Manage-DellBiosSettings-PSModule.ps1\nDell and PowerShell Unlike HP and Lenovo, Dell does not provide command line access to their BIOS settings by default. Instead, Dell provides a PowerShell module called Dell Command | PowerShell Provider. This PowerShell module allows Dell BIOS passwords and settings to be directly viewed and modified from a PowerShell prompt or script. This PowerShell module needs to be installed before running the Dell password management script. For more information, see my recent blog post, Working with the Dell Command | PowerShell Provider.\nOnce the Dell PowerShell Provider module has been installed, open an administrative PowerShell prompt and import the module.\nImport-Module DellBIOSProvider The DellBIOSProvider module creates a new PSDrive called DellSmbios. Settings can be queried or modified by using the Get-Item and Set-Item cmdlets on objects in the DellSmbios:\\ location.\n#Get the current value of a single BIOS setting Get-Item -Path DellSmbios:\\Category\\Setting | Select-Object -ExpandProperty CurrentValue #Get the current value and possible values of all BIOS settings $DellSmbios = Get-ChildItem -Path DellSmbios:\\ $Categories = $DellSmbios.Category $SettingList = @() foreach($Category in $Categories){ $SettingList += Get-ChildItem -Path \u0026#34;DellSmbios:\\$($Category)\u0026#34; | Select-Object Attribute,CurrentValue,PossibleValues } Write-Output $SettingList #Set the value of a single BIOS setting Set-Item -Path DellSmbios:\\Category\\Setting -Value Enabled The DellBIOSProvider module also allows for working with systems that have a BIOS password set. In this case, the password parameter needs to be used when setting a new value.\n#Set the value of a single BIOS setting when a BIOS password is set Set-Item -Path DellSmbios:\\Category\\Setting -Value Enabled -Password ExamplePassword For more information on using the Dell PowerShell Provider, refer to the official documentation: Reference Guide, User Guide\nManage-DellBiosSettings.ps1 This script takes the basic commands and adds logic to allow for a more automated settings management process. The script has four parameters.\nGetSettings - Use this parameter to instruct the script to generate a list of all current BIOS settings. The settings will be displayed to the screen by default. SetSettings - Use this parameter to instruct the script to set specific BIOS settings. Settings can be specified either in the body of the script or from a CSV file. CsvPath - Use this parameter to specify the location of a CSV file. If used with the GetSettings switch, this acts as the location where a list of current BIOS settings will be saved. If used with the SetSettings switch, this acts as the location where the script will read BIOS settings to be set from. Using this switch with the SetSettings switch will also cause the script to ignore any settings specified in the body of the script. AdminPassword - Used to specify the BIOS password When using the script to set settings, the list of settings can either be specified in the script itself or in a CSV file. To specify settings in the script, look for the $Settings array near the top of the script. The settings should be in the format of \u0026ldquo;Setting Name,Setting Value\u0026rdquo;\n#List of settings to be configured ================================= #=================================================================== $Settings = ( \u0026#34;FingerprintReader,Enabled\u0026#34;, \u0026#34;FnLock,Enabled\u0026#34;, \u0026#34;IntegratedAudio,Enabled\u0026#34;, \u0026#34;NumLock,Enabled\u0026#34;, \u0026#34;SecureBoot,Enabled\u0026#34;, \u0026#34;TpmActivation,Enabled\u0026#34;, \u0026#34;TpmClear,Disabled\u0026#34;, \u0026#34;TpmPpiClearOverride,Disabled\u0026#34;, \u0026#34;TpmPpiDpo,Disabled\u0026#34;, \u0026#34;TpmPpiPo,Enabled\u0026#34;, \u0026#34;TpmSecurity,Enabled\u0026#34;, \u0026#34;UefiNwStack,Enabled\u0026#34;, \u0026#34;Virtualization,Enabled\u0026#34;, \u0026#34;VtForDirectIo,Enabled\u0026#34;, \u0026#34;WakeOnLan,Disabled\u0026#34; ) #=================================================================== #=================================================================== A full list of configurable settings can be exported from a device by calling the script with the GetSettings parameter. The CsvPath parameter can also be specified to output the list of settings to a CSV file.\nYou can then sort through the exported settings and either save them as a CSV file or add them to the $Settings array in the body of the script.\nWhen the script runs, it will write to a log file. By default, this log file will be named Manage-DellBiosSettings-PSModule.Log. If the script is being run during a task sequence, the log file will be located in the _SMSTSLogPath. Otherwise, the log file will be located in ProgramData\\ConfigJonScripts\\Dell. The log file name and path can be changed using the LogFile parameter. Note that the log file path will always be set to _SMSTSLogPath when run during a task sequence.\nThe script has logic built-in to detect if settings were already set correctly, were successfully set, failed to set, or were not found on the device. The script will output these counts to the screen at the end. More detailed information about the settings will be written to the log file.\nI have included a few example settings files in my GitHub. These settings files contain commonly configured Dell BIOS settings.\nSettings_CSV_SecureBoot.csv - Contains settings for enabling UEFI and SecureBoot Settings_CSV_TPM.csv - Contains settings for enabling and activating TPM Settings_CSV_General.csv - Contains other common settings Settings_In-Script_All.txt - Contains common settings formatted for use in the body of the script Examples The script can be run as a standalone script in Windows, or as part of a Configuration Manager task sequence. It can also be run in the full Windows OS or in WinPE.\nHere are a few examples of calling the script from a PowerShell prompt.\n#Set BIOS settings supplied in the script Manage-DellBiosSettings-PSModule.ps1 -SetSettings -AdminPassword ExamplePassword #Set BIOS settings supplied in a CSV file Manage-DellBiosSettings-PSModule.ps1 -SetSettings -CsvPath C:\\Temp\\Settings.csv -AdminPassword ExamplePassword #Output a list of current BIOS settings to the screen Manage-DellBiosSettings-PSModule.ps1 -GetSettings #Output a list of current BIOS settings to a CSV file Manage-DellBiosSettings-PSModule.ps1 -GetSettings -CsvPath C:\\Temp\\Settings.csv Here is an example of calling the script during a task sequence. In this example the settings are specified in the body of the script, so the script can be stored directly in the task sequence step. Also the admin password is set, so the AdminPassword parameter is specified.\nIn this second example, the script is being called from a package and the settings are being supplied from a CSV file.\nAdditional Reading If you\u0026rsquo;re looking for other options for managing Dell BIOS settings, check out the Dell Command Configure utility. For information on configuring Dell BIOS passwords using PowerShell, see my post Dell BIOS Password Management.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/dell-bios-settings-management-psmodule/","summary":"\u003cp\u003e\u003cstrong\u003eThis post was updated on September 11th, 2020.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eUpdate: Dell does now provide native WMI classes to manage BIOS settings on newer models. For more information, see this post: \u003cstrong\u003e\u003ca href=\"/dell-bios-settings-management-wmi/\"\u003eDell BIOS Settings Management - WMI\u003c/a\u003e\u003c/strong\u003e. For information on using the Dell PowerShell module to configure settings on older models, continue reading this post.\u003c/p\u003e\n\u003cp\u003eThis post is one of 3 posts in my series on managing BIOS settings using PowerShell. I\u0026rsquo;ve also written about \u003cstrong\u003e\u003ca href=\"/hp-bios-settings-management/\"\u003eHP\u003c/a\u003e\u003c/strong\u003e and \u003cstrong\u003e\u003ca href=\"/lenovo-bios-settings-management/\"\u003eLenovo\u003c/a\u003e\u003c/strong\u003e. In this post I\u0026rsquo;ll be talking about using PowerShell to manage Dell BIOS settings.\u003c/p\u003e","title":"Dell BIOS Settings Management - PSModule"},{"content":"I just finished updating the script I\u0026rsquo;ve been using to bulk create collections in Configuration Manager. I know there are already many different examples of this same type of script out there, but I figured I\u0026rsquo;d share my take on it.\nThe script can be downloaded from my GitHub: https://github.com/ConfigJon/ConfigMgr-Scripts/tree/master/Create-Collections\nCreate_Collections.ps1 This script can be used to dynamically create user collections, device collections, and folder structure based on information in a CSV file. The script should be run as a user account with rights to connect to and create collections in Configuration Manager. The script should be run on a computer with the Configuration Manager Admin Console installed. The script will automatically search for the ConfigurationManager.psd1 file, attempt to import it, and connect to the specific site.\nThe script has 3 parameters:\nSiteCode - The site code of the Configuration Manager site SiteServer - The name of the primary site server, or sms provider CsvPath - The path to the CSV file containing the collection information The CSV file has 12 columns:\nCollectionName - (Required) - The display name of the collection. CollectionType - (Required) - The type of collection to create (valid values: User or Device) LimitingCollectionName - (Required) - The name of the collection to be used as the limiting collection FolderPath - (Optional) - The folder path where the collection is to be created. If the folder path does not exist, it will be created. If the folder path is left blank, the collection will be placed at the root of Device Collections or User Collections. (Example folder path: Applications\\Required) Comment - (Optional) - A comment ScheduleInterval - (Required) - The interval to be used for collection evaluation. (Example values: Days or Hours) IntervalCount - (Required) - The number of intervals between collection evaluation. IncrementalUpdate - (Optional) - Used to enable incremental updates (Valid values: Yes or No) IncludeCollection - (Optional) - Used to specify collections to include. Specify the name of the collection(s). If specifying multiple collections, separate the names with a semi-colon ExcludeCollection - (Optional) - Used to specify collections to exclude. Specify the name of the collection(s). If specifying multiple collections, separate the names with a semi-colon. QueryName - (Optional) - Name of the query rule to create QueryRule - (Optional) - The query language An example CSV file can be found along with the script on my GitHub page.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/configuration-manager-collection-creation-script/","summary":"\u003cp\u003eI just finished updating the script I\u0026rsquo;ve been using to bulk create collections in Configuration Manager. I know there are already many different examples of this same type of script out there, but I figured I\u0026rsquo;d share my take on it.\u003c/p\u003e\n\u003cp\u003eThe script can be downloaded from my GitHub: \u003ca href=\"https://github.com/ConfigJon/ConfigMgr-Scripts/tree/master/Create-Collections\"\u003e\u003cstrong\u003ehttps://github.com/ConfigJon/ConfigMgr-Scripts/tree/master/Create-Collections\u003c/strong\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch3 id=\"create_collectionsps1\"\u003eCreate_Collections.ps1\u003c/h3\u003e\n\u003cp\u003eThis script can be used to dynamically create user collections, device collections, and folder structure based on information in a CSV file. The script should be run as a user account with rights to connect to and create collections in Configuration Manager. The script should be run on a computer with the Configuration Manager Admin Console installed. The script will automatically search for the ConfigurationManager.psd1 file, attempt to import it, and connect to the specific site.\u003c/p\u003e","title":"Configuration Manager Collection Creation Script"},{"content":"I\u0026rsquo;ve recently been working on a lot of app packaging, and I decided to take the opportunity to update my scripts. In this post I\u0026rsquo;ll cover 3 PowerShell functions that I found to be the most useful. The functions can be found on my GitHub.\nInvoke-MsiExec This function works with msiexec.exe. The function allows for installing or uninstalling a .msi based application.\nThe function has a number of parameters:\nFilePath - The path to the .msi or .msp file Guid - The GUID of the MSI-based application to be uninstalled Install - Indicates that the /i switch should be used when calling msiexec.exe Uninstall - Indicates that the /x switch should be used when calling msiexec.exe Patch - Indicates that the /p switch should be used when calling msiexec.exe Arguments - A comma separated list of arguments to pass to msiexec.exe ExitCodes - A comma separated list of non-standard exit codes Some notes about the parameters:\nThe Install, Uninstall, and Patch parameters are mutually exclusive. Only specify 1 of these switches. The function will tell you if you accidentally specify more than 1. The list of arguments must be contained within single quotes and each argument must be separated by a comma. Double quotes can be passed in the arguments list. PowerShell variables can also be passed in the arguments list. The variables will be expanded inside the function. By default the function will only interpret exit codes 0 and 3010 as success. If the application in question has other successful exit codes, they must be specified with the ExitCodes parameter. The list of exit codes must be contained within single quotes and each exit code must be separated by a comma. Some examples of using the function:\n#Install a .msi file Invoke-MsiExec -Install -FilePath \u0026#34;$PSScriptRoot\\Setup.msi\u0026#34; -Arguments \u0026#39;/qn,/norestart\u0026#39; #Install a .msi file with arguments containing double quotes, variables, and non-standard exit codes Invoke-MsiExec -Install -FilePath \u0026#34;$PSScriptRoot\\Setup.msi\u0026#34; -Arguments \u0026#39;/qn,/norestart,TRANSFORMS=\u0026#34;$PSScriptRoot\\Settings.mst\u0026#34;\u0026#39; -ExitCodes \u0026#39;4,8,10\u0026#39; #Install a .msp file Invoke-Msiexec -Patch -FilePath \u0026#34;$PSScriptRoot\\Patch.msp\u0026#34; -Arguments \u0026#39;/qn,/norestart\u0026#39; #Uninstall a application Invoke-MsiExec -Uninstall -Guid \u0026#34;{00000000-0000-0000-0000-000000000000}\u0026#34; -Arguments \u0026#39;/qn,/norestart\u0026#39; Invoke-Executable This function works with .exe files. The function allows for running an exe with arguments.\nThe function has a few parameters. The same notes above about the Arguments and ExitCodes parameters also apply here.\nFilePath - The path to the .exe file Arguments - A comma separated list of arguments to pass to the executable ExitCodes - A comma separated list of non-standard exit codes Some examples of using the function:\n#Run a .exe file Invoke-Executable -FilePath \u0026#34;$PSScriptRoot\\Setup.exe\u0026#34; -Arguments \u0026#39;/S\u0026#39; #Run a .exe file with arguments containing double quotes, and non-standard exit codes Invoke-Executable -FilePath \u0026#34;$PSScriptRoot\\Setup.exe\u0026#34; -Arguments \u0026#39;/S,/v\u0026#34;/qn REBOOT=reallysuppress\u0026#34;\u0026#39; -ExitCodes \u0026#39;4,8,10\u0026#39; New-RegistryValue This function allows for the creation and/or modification of registry values.\nThe function has a few parameters:\nRegKey - The path to the target registry key Name - The name of the registry value to create of modify PropertyType - The type of registry value to create or modify Value - The data to write to the registry value Some notes about this function:\nIf the specified registry key does not yet exist, the function will create it before creating the value. To modify the default value of a registry key, specify \u0026rsquo;(Default)\u0026rsquo; in the name parameter Valid values for the PropertyType parameter are - ( \u0026lsquo;String\u0026rsquo; \u0026lsquo;ExpandString\u0026rsquo; \u0026lsquo;Binary\u0026rsquo; \u0026lsquo;DWord\u0026rsquo; \u0026lsquo;MultiString\u0026rsquo; \u0026lsquo;Qword\u0026rsquo; \u0026lsquo;Unknown\u0026rsquo; ) By default only the HKLM and HKCU registry hives are loaded. Use New-PSDrive to load other registry hives. ( New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT ) Some examples of using the function:\n#Create a new Dword registry value New-RegistryValue -RegKey \u0026#34;HKLM:\\SOFTWARE\\Example\u0026#34; -Name \u0026#34;ExampleValue\u0026#34; -PropertyType Dword -Value 2 #Modify the default value of a registry key New-RegistryValue -RegKey \u0026#34;HKLM:\\SOFTWARE\\Example\u0026#34; -Name \u0026#39;(Default)\u0026#39; -PropertyType String -Value \u0026#34;abcd\u0026#34; ","permalink":"https://4c4806b4.configjon-blog.pages.dev/app-packaging-powershell-functions/","summary":"\u003cp\u003eI\u0026rsquo;ve recently been working on a lot of app packaging, and I decided to take the opportunity to update my scripts. In this post I\u0026rsquo;ll cover 3 PowerShell functions that I found to be the most useful. The functions can be found on my \u003cstrong\u003e\u003ca href=\"https://github.com/ConfigJon/Miscellaneous-Scripts/tree/master/App%20Packaging\"\u003eGitHub\u003c/a\u003e\u003c/strong\u003e.\u003c/p\u003e\n\u003ch3 id=\"invoke-msiexec\"\u003eInvoke-MsiExec\u003c/h3\u003e\n\u003cp\u003eThis function works with msiexec.exe. The function allows for installing or uninstalling a .msi based application.\u003c/p\u003e\n\u003cp\u003eThe function has a number of parameters:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eFilePath\u003c/strong\u003e - The path to the .msi or .msp file\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGuid\u003c/strong\u003e - The GUID of the MSI-based application to be uninstalled\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eInstall\u003c/strong\u003e - Indicates that the /i switch should be used when calling msiexec.exe\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUninstall\u003c/strong\u003e - Indicates that the /x switch should be used when calling msiexec.exe\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePatch\u003c/strong\u003e - Indicates that the /p switch should be used when calling msiexec.exe\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eArguments\u003c/strong\u003e - A comma separated list of arguments to pass to msiexec.exe\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eExitCodes\u003c/strong\u003e - A comma separated list of non-standard exit codes\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eSome notes about the parameters:\u003c/p\u003e","title":"App Packaging PowerShell Functions"},{"content":"This post was updated on September 11th, 2020.\nUpdate: Dell does now provide native WMI classes to manage BIOS passwords on newer models. For more information, see this post: Dell BIOS Password Management - WMI. For information on using the Dell PowerShell module to configure passwords on older models, continue reading this post.\nThis is the third post in my series on how to manage BIOS / Firmware passwords with PowerShell. Previously, I\u0026rsquo;ve discussed Lenovo BIOS Password Management and HP BIOS Password Management.\nThis script is similar to the previous scripts in that the goal was to have a script that could automatically set, change, or clear BIOS passwords while providing logging and optional user prompts. However, there are a few differences. In this post, I\u0026rsquo;ll cover the basics of how the script works.\nThe script can be downloaded from my GitHub: https://github.com/ConfigJon/Firmware-Management/blob/master/Dell/Manage-DellBiosPasswords-PSModule.ps1\nDell and PowerShell Unlike HP and Lenovo, Dell does not provide command line access to their BIOS settings by default. Instead, Dell provides a PowerShell module called Dell Command | PowerShell Provider. This PowerShell module allows Dell BIOS passwords and settings to be directly viewed and modified from a PowerShell prompt or script. This PowerShell module needs to be installed before running the Dell password management script. For more information, see my recent blog post, Working with the Dell Command | PowerShell Provider.\nOnce the Dell PowerShell Provider module has been installed, open an administrative PowerShell prompt and import the module.\nImport-Module DellBIOSProvider Now that the module is imported, the first thing that needs to be done is to determine what passwords are currently configured. This information can be obtained using the Get-Item PowerShell cmdlet against the DellSmbios: PSDrive.\n#Check the status of the admin password Get-Item -Path DellSmbios:\\Security\\IsAdminPasswordSet | Select-Object -ExpandProperty CurrentValue #Check the status of the system password Get-Item -Path DellSmbios:\\Security\\IsSystemPasswordSet | Select-Object -ExpandProperty CurrentValue Checking the status of the passwords with return either True or False.\nThe next step is to action on this data and set, change, or clear the password(s). This can be accomplished by using the Set-Item PowerShell cmdlet against the DellSmbios: PSDrive.\n#Set a new admin password Set-Item -Path DellSmbios:\\Security\\AdminPassword NewPassword #Change an existing admin password Set-Item -Path DellSmbios:\\Security\\AdminPassword NewPassword -Password OldPassword #Clear an existing admin password Set-Item -Path DellSmbios:\\Security\\AdminPassword \u0026#34;\u0026#34; -Password OldPassword For more information on using the Dell PowerShell Provider, refer to the official documentation: Reference Guide, User Guide\nManage-DellBiosPasswords.ps1 This script takes the basic commands we just looked at and adds logic to allow for a more automated password management process. The script accepts parameters that tell it which actions to perform.\nAdminSet - Set a new admin password or change an existing admin password AdminClear - Clear an existing admin password SystemSet - Set a new system password or change an existing system password SystemClear - Clear an existing system password There are also parameters that are used to specify the new and old BIOS passwords.\nAdminPassword - The current admin password or password to be set OldAdminPassword - The old admin password(s) to be changed. Multiple old passwords can be specified (separated by a comma). SystemPassword - The current system password or password to be set OldSystemPassword - The old system password(s) to be changed. Multiple old passwords can be specified (separated by a comma). By default, if the script fails to perform any of these actions, it will display a message box on the screen and exit with an error code. This can be useful in a task sequence scenario where you may not want a system to continue with the task sequence if the BIOS password is not set correctly. However, if you want the script to be completely silent, there are a few parameters that can be set.\nNoUserPrompt - Suppress all user prompts ContinueOnError - Ignore any errors caused by changing or clearing passwords When the script runs, it will write to a log file. By default, this log file will be named Manage-DellBiosPasswords-PSModule.Log. If the script is being run during a task sequence, the log file will be located in the _SMSTSLogPath. Otherwise, the log file will be located in ProgramData\\ConfigJonScripts\\Dell. The log file name and path can be changed using the LogFile parameter. Note that the log file path will always be set to _SMSTSLogPath when run during a task sequence.\nExamples The script can be run as a standalone script in Windows, or as a part of a Configuration Manager task sequence. It can also be run in the full Windows OS or in WinPE.\nHere are a few examples of calling the script from a PowerShell prompt in Windows.\nSet a new admin password Manage-DellBiosPasswords-PSModule.ps1 -AdminSet -AdminPassword \u0026lt;String\u0026gt; Set or change a admin password Manage-DellBiosPasswords-PSModule.ps1 -AdminSet -AdminPassword \u0026lt;String\u0026gt; -OldAdminPassword \u0026lt;String1\u0026gt;,\u0026lt;String2\u0026gt;,\u0026lt;String3\u0026gt; Set a new admin password and set a new system password Manage-DellBiosPasswords-PSModule.ps1 -AdminSet -SystemSet -AdminPassword \u0026lt;String\u0026gt; -SystemPassword \u0026lt;String\u0026gt; Clear an existing admin password Manage-DellBiosPasswords-PSModule.ps1 -AdminClear -OldAdminPassword \u0026lt;String1\u0026gt;,\u0026lt;String2\u0026gt;,\u0026lt;String3\u0026gt; Here is a basic example of calling the script during a task sequence. This is likely one of the most common ways the script would be called in a task sequence. In this example the admin password will be set if it doesn\u0026rsquo;t exist, and it will be changed if it does already exist.\n-AdminSet -AdminPassword %NewPassword% -OldAdminPassword %OldPassword1%,%OldPassword2%,%OldPassword3% Note that before running the Dell password management script, the DellBIOSProvider PowerShell module must be installed. See my recent post Working with the Dell Command | PowerShell Provider for information on installing the module during a task sequence.\nPassword Lockout If you have read my posts on managing HP and Lenovo BIOS passwords, then you will know that those scripts have logic built-in to handle system reboots. This is because on HP and Lenovo systems, after a set number of failed password attempts, the system locks and needs to be rebooted before any additional password attempts can be made.\nIn my testing on Dell hardware, it seems that there is not a BIOS password lockout (or it is set to a very high number) when using the Dell PowerShell Provider. This means that there isn\u0026rsquo;t a need for multiple passes of the script when there are many potential old passwords to change. The OldAdminPassword and OldSystemPassword parameters could accept many values in a single pass of the script.\nHaving said that, I have only tested this on a limited number of Dell hardware models, so I am not sure if it is universal. Dell could also choose to add a lockout in the future. For these reasons, I have still included the reboot logic in the script, even if it isn\u0026rsquo;t needed right now.\nIf multiple passes of the script are required, it would function just like the HP and Lenovo scripts.\nFirst in the Set Password Values step, create variables for each password.\nThe First Pass folder has no conditions on it, as it should run for any Dell system. To set a new admin password or change an existing admin password, the AdminSet parameter is specified along with the AdminPassword and OldAdminPassword parameters.\nBecause the script will need to run multiple times, there is one additional parameter that needs to be specified. The SMSTSPasswordRetry parameter instructs the script to not display prompts to the screen until all attempts have completed. In this scenario, the script needs to be run 3 times, so SMSTSPasswordRetry parameter is specified on the first 2 passes of the script and not on the final pass. When the password(s) are successfully changed or cleared, the SMSTSPasswordRetry variable will be set to false. This means that if the first pass of the script is successful, the second and third passes of the script will be skipped.\n-AdminSet -AdminPassword %NewPassword% -OldAdminPassword %OldPassword1%,%OldPassword2% -SMSTSPasswordRetry When the script runs during a task sequence, it will create task sequence variables to track the success or failure of each different script action. If any one of the password actions fails, the associated task sequence variable will be set to Failed.\nDellSetAdmin DellClearAdmin DellSetSystem DellClearSystem As I mentioned before, the first run of the script in the task sequence does not have any conditions, but each successive run of the script should have these conditions.\nThe second pass of the script. Notice the SMSTSPasswordRetry parameter is specified because there is still another potential pass of the script yet to run.\n-AdminSet -AdminPassword %NewPassword% -OldAdminPassword %OldPassword3%,%OldPassword4% -SMSTSPasswordRetry The third pass of the script. Notice the SMSTSPasswordRetry parameter is not set because this is the final pass of the script.\n-AdminSet -AdminPassword %NewPassword% -OldAdminPassword %OldPassword5%,%OldPassword6% User Prompts If at the end of the script execution (whether that be one pass or multiple) any of the password management tasks are in a failed state, and the NoUserPrompt or ContinueOnError switches have not been specified, a prompt will be displayed on the screen informing the user of which tasks failed.\nThe end result of all of this is a script that can be used to change or clear Dell BIOS passwords. The script can be run in a task sequence and persist information across multiple reboots (if required). This allows for the user to be correctly prompted about any required manual actions even if there are many old passwords to test.\nNotes and Additional Reading A few notes about some restrictions Dell has placed on setting passwords.\nIf a system or hard drive password is currently set, an admin password cannot be set If an admin password is set and a system password is not set, the admin password is required to set the system password If an admin password and system password are both set and the admin password is cleared, the system password will also be automatically cleared Some Dell systems have the ability to set hard drive password(s). This script currently does not support hard drive passwords. Only admin and system passwords can be managed. I may work on adding hard drive password support in the future.\nIf you\u0026rsquo;re looking to configure Dell BIOS settings other than just the passwords, check out these links. Dell Command Configure, Dell PowerShell Provider User Guide, Dell PowerShell Provider Reference Guide. Also, look for a future blog post from me on configuring Dell BIOS settings with PowerShell.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/dell-bios-password-management-psmodule/","summary":"\u003cp\u003e\u003cstrong\u003e\u003cstrong\u003eThis post was updated on September 11th, 2020.\u003c/strong\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eUpdate: Dell does now provide native WMI classes to manage BIOS passwords on newer models. For more information, see this post: \u003cstrong\u003e\u003ca href=\"/dell-bios-password-management-wmi/\"\u003eDell BIOS Password Management - WMI\u003c/a\u003e\u003c/strong\u003e. For information on using the Dell PowerShell module to configure passwords on older models, continue reading this post.\u003c/p\u003e\n\u003cp\u003eThis is the third post in my series on how to manage BIOS / Firmware passwords with PowerShell. Previously, I\u0026rsquo;ve discussed \u003cstrong\u003e\u003ca href=\"/lenovo-bios-password-management/\"\u003eLenovo BIOS Password Management\u003c/a\u003e\u003c/strong\u003e and \u003cstrong\u003e\u003ca href=\"/hp-bios-password-management/\"\u003eHP BIOS Password Management\u003c/a\u003e\u003c/strong\u003e.\u003c/p\u003e","title":"Dell BIOS Password Management - PSModule"},{"content":"This post was updated on February 20th, 2022.\nI\u0026rsquo;ve recently been writing a series of blog posts on how to manage BIOS and Firmware settings using PowerShell. When working with HP and Lenovo hardware I was able to modify the settings by connecting to the WMI classes that are surfaced on the hardware by default. With Dell this was not as straightforward.\nIn order to access the Dell WMI classes that can be used to query and modify BIOS settings, the Dell Command | Monitor software needs to be installed. This posed another problem, as I wanted to be able to modify BIOS settings while in WinPE, and Dell Command | Monitor only installs in a full Windows OS. The solution to this issue was the Dell Command | PowerShell Provider.\nThe Dell Command | PowerShell Provider is a PowerShell module that allows for the querying and modification of BIOS settings in both WinPE and the full Windows OS. In this post I will talk about the requirements for using the Dell PowerShell Provider as well as the PowerShell script I wrote for installing and updating it.\nUpdate 2022-02-20 - With the latest release of the Dell Command PowerShell Provider, Dell has changed the .dll files that are required to run the module. I have updated this post and the Install-DellBiosProvider.ps1 script to work with version 2.6.0 and newer. The legacy versions of the script that work with module version 2.4.0 and 2.3.1 can still be found on my GitHub.\nThe script can be found on my GitHub: https://github.com/ConfigJon/Firmware-Management/blob/master/Dell/Install-DellBiosProvider.ps1\nPrerequisites Before the Dell PowerShell Provider can be installed and run, there are a few prerequisites that need to be in place.\nWindows Management Framework 3.0 and PowerShell 3.0 or newer Microsoft Visual C++ Redistributable 2010 Microsoft Visual C++ Redistributable 2015 Microsoft Visual C++ Redistributable 2019 Dell SMBIOS Version 2.4 or newer Additionally, before installing the Dell PowerShell Provider in WinPE, these components need to be added to the boot image.\nMicrosoft .NET (WinPE-NetFx) Scripting (WinPE-Scripting) Scripting (WinPE-WMI) Windows PowerShell (WinPE-PowerShell) Some notes about the prerequisites:\nThe WMF 3.0 and PowerShell 3.0 requirements will be met by default on any version of Windows 10 or WinPE 10. If the target system SMBIOS version is lower than 2.4, apply the latest BIOS / Firmware update available from Dell. The Visual C++ Redistributables can be installed in full Windows. Alternatively, these .dll files can be copied into the Windows\\System32 folder Dell Command PowerShell Provider 2.6.0 and later msvcp100.dll msvcr100.dll msvcp140.dll vcruntime140.dll vcruntime140_1.dll Dell Command PowerShell Provider 2.4.0 msvcp140.dll vcruntime140.dll vcruntime140_1.dll Dell Command PowerShell Provider 2.3.1 and earlier msvcp100.dll msvcr100.dll msvcp140.dll vccorlib140.dll vcruntime140.dll The WinPE-Scripting and WinPE-WMI components are included in SCCM boot images by default. The WinPE-WMI and WinPE-PowerShell components need to be added in the Optional Components tab of the boot image Properties window. The script has logic to check for the SMBIOS version, PowerShell version, and Visual C++ .dll files. If any of these prerequisites are not met, the script will exit. Installation The Dell Command | PowerShell Provider is really just a PowerShell module called DellBIOSProvider. This module can be found on the PowerShell Gallery. I have created a PowerShell script that is able to verify the prerequisites are met and install the module.\nThe script has two optional parameters.\nModulePath - This parameter is used to specify the location of the DellBIOSProvider module source files. This parameter should be specified when the script is running in WinPE or when the system does not have internet access.\nDllPath - This parameter is used to specify the location of the .dll files required to run the DellBIOSProvider module. This parameter should be specified when the script is running in WinPE or when the system does not have the required Visual C++ Redistributables installed. If you do not specify a folder using the DllPath parameter and the .dll files are missing on the system, the script will look for the .dll files in the script root directory.\nInstall from the internet The script is able to connect directly to the PowerShell Gallery to download and install the module. In order for this to work, the script needs to be running in a full Windows OS and the system needs to have internet access. To have the script install the module from the internet, run the script without specifying the ModulePath parameter.\nInstall from local source files If the script is being run from WinPE or if the system does not have internet access, the DellBIOSProvider source files can be manually downloaded from the PowerShell Gallery. The module will download as a .nupkg file. Extract the contents of this file and place them in a folder. Specify that folder in the ModulePath parameter.\nExamples Running in a full Windows OS with internet access and with the Visual C++ Redistributables installed.\nInstall-DellBiosProvider.ps1 Running in a full Windows OS with internet access but without the Visual C++ Redistributables installed. The required .dll files are in a folder named DllFiles. The folder is located in the same directory as the script file.\nInstall-DellBiosProvider.ps1 -DllPath DllFiles Running in a WinPE OS. The DellBIOSProvider module source files are in a folder named DellBIOSProvider. The required .dll files are in a folder named DllFiles. Both folders are located in the same directory as the script file.\nInstall-DellBiosProvider.ps1 -ModulePath DellBIOSProvider -DllPath DllFiles Running in a WinPE OS. The DellBIOSProvider module source files are in a folder named DellBIOSProivder. The DellBIOSProvider folder and the required .dll files are located in the same directory as the script file.\nInstall-DellBiosProvider.ps1 -ModulePath DellBIOSProvider The task sequence step would look like this:\nIn this example, the package source files would look like this. The DellBIOSProvider module is in the DellBIOSProvider module folder and the required .dll files are in the folder root.\nLogging When the script runs, it will write to a log file. By default, this log file will be named Install-DellBiosProvider.log. If the script is being run during a task sequence, the log file will be located in the _SMSTSLogPath. Otherwise, the log file will be located in ProgramData\\ConfigJonScripts\\Dell. The log file name and path can be changed using the LogFile parameter. Note that the log file path will always be set to _SMSTSLogPath when run during a task sequence.\nView and Modify BIOS Settings Once the DellBIOSProvider module has been installed, it needs to be imported before being used.\nImport-Module DellBIOSProvider The DellBIOSProvider module makes settings available by creating a new PSDrive called DellSmbios:. This drive contains a list of all of the available settings on the system. These settings can be read by using Get-Item or Get-ChildItem and can be modified by using Set-Item. Here are a few examples of listing and modifying settings.\n#Check the status of the admin password Get-Item -Path DellSmbios:\\Security\\IsAdminPasswordSet | Select-Object -ExpandProperty CurrentValue #Set a new admin password Set-Item -Path DellSmbios:\\Security\\AdminPassword NewPassword #Check the status of the NumLock setting Get-Item -Path DellSmbios:\\POSTBehavior\\NumLock | Select-Object -ExpandProperty CurrentValue #Check the possible values for the NumLock setting Get-Item -Path DellSmbios:\\POSTBehavior\\NumLock | Select-Object -ExpandProperty PossibleValues #Modify the NumLock setting when a BIOS password is not set Set-Item -Path DellSmbios:\\POSTBehavior\\NumLock Disabled #Modify the NumLock setting when a BIOS password is set Set-Item -Path DellSmbios:\\POSTBehavior\\NumLock Disabled -Password MyPassword #List all available BIOS Settings $DellSettings = Get-ChildItem -Path DellSmbios:\\ ForEach ($Setting in $DellSettings) { Get-ChildItem -Path \u0026#34;DellSmbios:\\$($Setting.Category)\u0026#34; -WarningAction SilentlyContinue | Select-Object PSChildName,Attribute,CurrentValue,PossibleValues } For more information on using the Dell PowerShell Provider, refer to the official documentation: Reference Guide, User Guide. Also, look for a future blog post from me that goes into more depth on Dell BIOS Settings management with PowerShell.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/working-with-the-dell-command-powershell-provider/","summary":"\u003cp\u003e\u003cstrong\u003eThis post was updated on February 20th, 2022.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eI\u0026rsquo;ve recently been writing a series of blog posts on how to manage BIOS and Firmware settings using PowerShell. When working with HP and Lenovo hardware I was able to modify the settings by connecting to the WMI classes that are surfaced on the hardware by default. With Dell this was not as straightforward.\u003c/p\u003e\n\u003cp\u003eIn order to access the Dell WMI classes that can be used to query and modify BIOS settings, the \u003cstrong\u003e\u003ca href=\"https://www.dell.com/support/article/us/en/04/sln311855/dell-command-monitor?lang=en\"\u003eDell Command | Monitor\u003c/a\u003e\u003c/strong\u003e software needs to be installed. This posed another problem, as I wanted to be able to modify BIOS settings while in WinPE, and Dell Command | Monitor only installs in a full Windows OS. The solution to this issue was the \u003cstrong\u003e\u003ca href=\"https://www.dell.com/support/article/us/en/04/sln311262/dell-command-powershell-provider?lang=en\"\u003eDell Command | PowerShell Provider\u003c/a\u003e\u003c/strong\u003e.\u003c/p\u003e","title":"Working with the Dell Command | PowerShell Provider"},{"content":"This post was updated on October 18th, 2020.\nThis post is one of 3 posts in my series on managing BIOS settings using PowerShell. I’ve also written about Dell and HP. In this post I’ll be talking about using PowerShell to manage Lenovo BIOS settings.\nThe script can be downloaded from my GitHub: https://github.com/ConfigJon/Firmware-Management/tree/master/Lenovo\nLenovo, WMI, and PowerShell Lenovo provides a WMI interface that can be used for querying and modifying BIOS settings on their hardware models. This means that we can use PowerShell to directly view and edit BIOS settings without the need for a vendor specific program. This script uses 6 of the Lenovo provided WMI classes.\nThe first WMI class is Lenovo_BiosSetting. This class is used to return a list of the configurable BIOS settings as well as their current values.\n#Connect to the Lenovo_BiosSetting WMI class $SettingList = Get-WmiObject -Namespace root\\wmi -Class Lenovo_BiosSetting #Return a list of all configurable settings $SettingList | Select-Object CurrentSetting #Return a specific setting and value $SettingList | Where-Object CurrentSetting -Like \u0026#34;SettingName*\u0026#34; | Select-Object -ExpandProperty CurrentSetting The second WMI class is Lenovo_SetBiosSetting. This class contains a method called SetBiosSetting which is used to modify bios setting values.\n#Connect to the Lenovo_SetBiosSetting WMI class $Interface = Get-WmiObject -Namespace root\\wmi -Class Lenovo_SetBiosSetting #Set a specific BIOS setting when a BIOS password is not set $Interface.SetBiosSetting(\u0026#34;SettingName,SettingValue\u0026#34;) #Set a specific BIOS setting when a BIOS password is set $Interface.SetBiosSetting(\u0026#34;SettingName,SettingValue,Password,ascii,us\u0026#34;) The third WMI class is Lenovo_SaveBiosSetting. This class contains a method called SaveBiosSettings which is used to commit any changes made to BIOS setting values.\n#Connect to the Lenovo_SaveBiosSetting WMI class $SaveSettings = Get-WmiObject -Namespace root\\wmi -Class Lenovo_SaveBiosSettings #Save any outstanding BIOS configuration changes (no password set) $SaveSettings.SaveBiosSettings() #Save any outstanding BIOS configuration changes (password set) $SaveSettings.SaveBiosSettings(\u0026#34;Password,ascii,us\u0026#34;) The fourth WMI class is Lenovo_BiosPasswordSettings. This class is used to query the current status of the BIOS passwords.\n#Connect to the Lenovo_BiosPasswordSettings WMI class $PasswordSettings = Get-WmiObject -Namespace root\\wmi -Class Lenovo_BiosPasswordSettings #Check the current password configuration state $PasswordSettings.PasswordState The fifth WMI class is Lenovo_LoadDefaultSettings. This class contains a method called LoadDefaultSettings which is used the set all BIOS settings to factory default values.\n#Connect to the Lenovo_LoadDefaultSettings WMI class $DefaultSettings = Get-WmiObject -Namespace root\\wmi -Class Lenovo_LoadDefaultSettings #Load default settings (no password set) $DefaultSettings.LoadDefaultSettings() #Load default settings (password set) $DefaultSettings.LoadDefaultSettings(\u0026#34;Password,ascii,us\u0026#34;) The sixth WMI class is Lenovo_SetBiosPassword. This class contains a method called SetBiosPassword which is used to set or change a BIOS password. In this script, it\u0026rsquo;s used to check if the currently configured password matches the password passed to the script in the SupervisorPassword or SystemManagementPassword parameters.\n#Connect to the Lenovo_SetBiosPassword WMI class $PasswordSet = Get-WmiObject -Namespace root\\wmi -Class Lenovo_SetBiosPassword #Set a BIOS password $PasswordSet.SetBiosPassword(\u0026#34;pap,OldPassword,NewPassword,ascii,us\u0026#34;) For reference, when calling the SetBiosSetting, SaveBiosSetting, LoadDefaultSettings or SetBiosPassword methods, the possible return values are:\nSuccess Not Supported Invalid Parameter Access Denied - BIOS password not supplied or not correct System Busy - There are pending setting changes. Reboot and try again For more detailed information on the Lenovo WMI interface, as well as a list of supported hardware models, refer to the official documentation. https://support.lenovo.com/us/en/solutions/ht100612\nManage-LenovoBiosSettings.ps1 This script takes the basic commands and adds logic to allow for a more automated settings management process. The script has four parameters.\nGetSettings – Use this parameter to instruct the script to generate a list of all current BIOS settings. The settings will be displayed to the screen by default. SetSettings – Use this parameter to instruct the script to set specific BIOS settings. Settings can be specified either in the body of the script or from a CSV file. SetDefaults - Use this parameter to instruct the script to set all BIOS settings to factory default values. CsvPath – Use this parameter to specify the location of a CSV file. If used with the GetSettings switch, this acts as the location where a list of current BIOS settings will be saved. If used with the SetSettings switch, this acts as the location where the script will read BIOS settings to be set from. Using this switch with the SetSettings switch will also cause the script to ignore any settings specified in the body of the script. SupervisorPassword - Used to specify the supervisor password SystemManagementPassword - Used to specify the system management password When using the script to set settings, the list of settings can either be specified in the script itself or in a CSV file. To specify settings in the script, look for the $Settings array near the top of the script. The settings should be in the format of “Setting Name,Setting Value”\n#List of settings to be configured ================================= #=================================================================== $Settings = ( \u0026#34;PXE IPV4 Network Stack,Enabled\u0026#34;, \u0026#34;IPv4NetworkStack,Enable\u0026#34;, \u0026#34;PXE IPV6 Network Stack,Enabled\u0026#34;, \u0026#34;IPv6NetworkStack,Enable\u0026#34;, \u0026#34;Intel(R) Virtualization Technology,Enabled\u0026#34;, \u0026#34;VirtualizationTechnology,Enable\u0026#34;, \u0026#34;VT-d,Enabled\u0026#34;, \u0026#34;VTdFeature,Enable\u0026#34;, \u0026#34;Enhanced Power Saving Mode,Disabled\u0026#34;, \u0026#34;Wake on LAN,Primary\u0026#34;, \u0026#34;Require Admin. Pass. For F12 Boot,Yes\u0026#34;, \u0026#34;Physical Presence for Provisioning,Disabled\u0026#34;, \u0026#34;PhysicalPresenceForTpmProvision,Disable\u0026#34;, \u0026#34;Physical Presnce for Clear,Disabled\u0026#34;, \u0026#34;PhysicalPresenceForTpmClear,Disable\u0026#34;, \u0026#34;Boot Up Num-Lock Status,Off\u0026#34; ) #=================================================================== #=================================================================== A full list of configurable settings can be exported from a device by calling the script with the GetSettings parameter. The CsvPath parameter can also be specified to output the list of settings to a CSV file.\nYou can then sort through the exported settings and either save them as a CSV file or add them to the $Settings array in the body of the script.\nWhen the script runs, it will write to a log file. By default, this log file will be named Manage-LenovoBiosSettings.Log. If the script is being run during a task sequence, the log file will be located in the _SMSTSLogPath. Otherwise, the log file will be located in ProgramData\\ConfigJonScripts\\Lenovo. The log file name and path can be changed using the LogFile parameter. Note that the log file path will always be set to _SMSTSLogPath when run during a task sequence.\nThe script has logic built-in to detect if settings were already set correctly, were successfully set, failed to set, or were not found on the device. The script will output these counts to the screen at the end. More detailed information about the settings will be written to the log file.\nLenovo BIOS setting names differ between hardware models. Specifically, laptops and desktops seem to have different setting names. This means that there can be multiple different ways to specify the same setting across multiple hardware models. I have included a few example settings files in my GitHub. These settings files contain commonly configured Lenovo BIOS settings that cover multiple Lenovo hardware models.\nSettings_CSV_UEFI_SecureBoot.csv - Contains settings for enabling UEFI and Secure Boot Settings_CSV_TPM.csv - Contains settings for enabling and activating TPM Settings_General.csv - Contains other common settings Settings_In-Script_All.txt - Contains common settings formatted for use in the body of the script One current limitation of the script has to do with the password check functionality. The script has logic built-in to detect if the BIOS password specified in the SupervsiorPassword or SystemManagementPassword parameter matches the currently set BIOS password. Running this password check only works one time per reboot, this means that if you need to run the script multiple times, you will need to have a reboot between each run of the script, or you will need to disable the password check portion of the script.\nExamples The script can be run as a standalone script in Windows, or as a part of a Configuration Manager task sequence. It can also be run in the full Windows OS or in WinPE.\nHere are a few examples of calling the script from a PowerShell prompt.\n#Set BIOS settings supplied in the script (no password set) Manage-LenovoBiosSettings.ps1 -SetSettings #Set BIOS settings supplied in the script (supervisor password set) Manage-LenovoBiosSettings.ps1 -SetSettings -SupervisorPassword ExamplePassword #Set BIOS settings supplied in the script (system management password set) Manage-LenovoBiosSettings.ps1 -SetSettings -SystemManagementPassword ExamplePassword #Set BIOS settings supplied in a CSV file (supervisor password set) Manage-LenovoBiosSettings.ps1 -SetSettings -CsvPath C:\\Temp\\Settings.csv -SupervisorPassword ExamplePassword #Set all BIOS settings to factory default values (supervisor password set) Manage-LenovoBiosSettings.ps1 -SetDefaults -SupervisorPassword ExamplePassword #Output a list of current BIOS settings to the screen Manage-LenovoBiosSettings.ps1 -GetSettings #Output a list of current BIOS settings to a CSV file Manage-LenovoBiosSettings.ps1 -GetSettings -CsvPath C:\\Temp\\Settings.csv Here is an example of calling the script during a task sequence. In this example the settings are specified in the body of the script, so the script can be stored directly in the task sequence step. Also the setup password is set, so the SupervisorPassword parameter is specified.\nIn this second example, the script is being called from a package and the settings are being supplied from a CSV file.\nNotes and Additional Reading If a password is set, the script attempts to verify the supplied password matches the currently set password. There seems to be a bug that can cause this check to not work.\nThe supervisor and system management passwords are both set Attempt to change the supervisor password and supply the system management password as the existing password The SetBiosPassword method reports success, but the password is not changed The script then continues and attempts to change settings, but the password is incorrect, so the settings fail to change. I don\u0026rsquo;t currently have a work around for this issue, so if a supervisor password is set, ensure that password is specified.\nIf you’re looking for other methods to configure Lenovo BIOS settings, check out these links. The Think BIOS Config Tool is an official tool released by Lenovo that allows for changing BIOS settings through a GUI interface or at the command line. The Lenovo BIOS Configurator is a script written by Martin Bengtsson. It’s an alternate example of using PowerShell to configure Lenovo BIOS settings. For information on configuring Lenovo BIOS passwords using PowerShell, see my post Lenovo BIOS Password Management.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/lenovo-bios-settings-management/","summary":"\u003cp\u003e\u003cstrong\u003eThis post was updated on October 18th, 2020.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThis post is one of 3 posts in my series on managing BIOS settings using PowerShell. I’ve also written about \u003cstrong\u003e\u003ca href=\"/dell-bios-settings-management/\"\u003eDell\u003c/a\u003e\u003c/strong\u003e and \u003cstrong\u003e\u003ca href=\"/hp-bios-settings-management/\"\u003eHP\u003c/a\u003e\u003c/strong\u003e. In this post I’ll be talking about using PowerShell to manage Lenovo BIOS settings.\u003c/p\u003e\n\u003cp\u003eThe script can be downloaded from my GitHub: \u003cstrong\u003e\u003ca href=\"https://github.com/ConfigJon/Firmware-Management/tree/master/Lenovo\"\u003ehttps://github.com/ConfigJon/Firmware-Management/tree/master/Lenovo\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003ch3 id=\"lenovo-wmi-and-powershell\"\u003eLenovo, WMI, and PowerShell\u003c/h3\u003e\n\u003cp\u003eLenovo provides a WMI interface that can be used for querying and modifying BIOS settings on their hardware models. This means that we can use PowerShell to directly view and edit BIOS settings without the need for a vendor specific program. This script uses 6 of the Lenovo provided WMI classes.\u003c/p\u003e","title":"Lenovo BIOS Settings Management"},{"content":"This post was updated on September 18th, 2020.\nThis post is one of 3 posts in my series on managing BIOS settings using PowerShell. I\u0026rsquo;ve also written about Dell and Lenovo. In this post I\u0026rsquo;ll be talking about using PowerShell to manage HP BIOS settings.\nThe script can be downloaded from my GitHub: https://github.com/ConfigJon/Firmware-Management/tree/master/HP\nHP, WMI, and PowerShell HP provides a WMI interface that can be used for querying and modifying BIOS settings on their hardware models. This means that we can use PowerShell to directly view and edit BIOS settings without the need for a vendor specific program. This script uses 3 of the HP provided WMI classes.\nThe first WMI class is HP_BIOSEnumeration. It is located in the root\\HP\\InstrumentedBIOS namespace. This class is used to return a list of the commonly configurable BIOS settings on a device. This list would include things like power settings, TPM settings, and Secure Boot settings to name a few examples.\n#Connect to the HP_BIOSEnumeration WMI class $SettingList = Get-WmiObject -Namespace root\\HP\\InstrumentedBIOS -Class HP_BIOSEnumeration #Return a list of all configurable settings $SettingList | Select-Object Name,Value #Return the current and available values for a specific setting ($SettingList | Where-Object Name -eq \u0026#34;Deep Sleep\u0026#34;).Value The second WMI class is HP_BIOSSetting. It is located in the root\\HP\\InstrumentedBIOS namespace. This class is used to return a list of all BIOS settings on a device. This class contains all of the same things as the HP_BIOSEnumeration class, but it also contains extra information like the serial number, UUID, and MAC address. The reason this class is used, is for querying the BIOS password status. The HP_BIOSEnumeration class does not contain the password settings.\n#Connect to the HP_BIOSSetting WMI class $HPBiosSettings = Get-WmiObject -Namespace root\\HP\\InstrumentedBIOS -Class HP_BIOSSetting #Return a list of all settings $HPBiosSettings | Select-Object Name,Value #Check the status of the setup password ($HPBiosSetting | Where-Object Name -eq \u0026#34;Setup Password\u0026#34;).IsSet The third WMI class is HP_BIOSSettingInterface. It is located in the root\\HP\\InstrumentedBIOS namespace. This class is used to set or change BIOS settings.\n#Connect to the HP_BIOSSettingInterface WMI class $Interface = Get-WmiObject -Namespace root\\HP\\InstrumentedBIOS -Class HP_BIOSSettingInterface #Set a specific value for a specific setting when a BIOS password is not set $Interface.SetBIOSSetting(\u0026#34;Deep Sleep\u0026#34;,\u0026#34;On\u0026#34;) #Set a specific value for a specific setting when a BIOS password is set $Interface.SetBIOSSetting(\u0026#34;Deep Sleep\u0026#34;,\u0026#34;On\u0026#34;,\u0026#34;\u0026lt;utf-16/\u0026gt;\u0026#34; + \u0026#34;Password\u0026#34;) The HP_BIOSSettingInterface WMI class contains a method called SetBIOSSetting. This method allows for changing HP BIOS settings.\nFor reference, these are the possible return codes for the SetBIOSSetting method:\n0 – Success 1 – Not Supported 2 – Unspecified Error 3 – Timeout 4 – Failed (Usually caused by a typo in the setting value) 5 – Invalid Parameter 6 – Access Denied (Usually caused by an incorrect BIOS password) For more detailed information on the HP WMI interface, refer to the official documentation: http://h20331.www2.hp.com/Hpsub/downloads/cmi_whitepaper.pdf\nManage-HPBiosSettings.ps1 This script takes the basic commands and adds logic to allow for a more automated settings management process. The script has four parameters.\nGetSettings - Use this parameter to instruct the script to generate a list of all current BIOS settings. The settings will be displayed to the screen by default. SetSettings - Use this parameter to instruct the script to set specific BIOS settings. Settings can be specified either in the body of the script or from a CSV file. CsvPath - Use this parameter to specify the location of a CSV file. If used with the GetSettings switch, this acts as the location where a list of current BIOS settings will be saved. If used with the SetSettings switch, this acts as the location where the script will read BIOS settings to be set from. Using this switch with the SetSettings switch will also cause the script to ignore any settings specified in the body of the script. SetupPassword - Used to specify the BIOS password When using the script to set settings, the list of settings can either be specified in the script itself or in a CSV file. To specify settings in the script, look for the $Settings array near the top of the script. The settings should be in the format of \u0026ldquo;Setting Name,Setting Value\u0026rdquo;\n#List of settings to be configured ================================= #=================================================================== $Settings = ( \u0026#34;Deep S3,Off\u0026#34;, \u0026#34;Deep Sleep,Off\u0026#34;, \u0026#34;S4/S5 Max Power Savings,Disable\u0026#34;, \u0026#34;S5 Maximum Power Savings,Disable\u0026#34;, \u0026#34;Fingerprint Device,Disable\u0026#34;, \u0026#34;Num Lock State at Power-On,Off\u0026#34;, \u0026#34;NumLock on at boot,Disable\u0026#34;, \u0026#34;Numlock state at boot,Off\u0026#34;, \u0026#34;Prompt for Admin password on F9 (Boot Menu),Enable\u0026#34;, \u0026#34;Prompt for Admin password on F11 (System Recovery),Enable\u0026#34;, \u0026#34;Prompt for Admin password on F12 (Network Boot),Enable\u0026#34;, \u0026#34;PXE Internal IPV4 NIC boot,Enable\u0026#34;, \u0026#34;PXE Internal IPV6 NIC boot,Enable\u0026#34;, \u0026#34;PXE Internal NIC boot,Enable\u0026#34;, \u0026#34;Wake On LAN,Boot to Hard Drive\u0026#34;, \u0026#34;Swap Fn and Ctrl (Keys),Disable\u0026#34; ) #=================================================================== #=================================================================== A full list of configurable settings can be exported from a device by calling the script with the GetSettings parameter. The CsvPath parameter can also be specified to output the list of settings to a CSV file.\nYou can then sort through the exported settings and either save them as a CSV file or add them to the $Settings array in the body of the script.\nWhen the script runs, it will write to a log file. By default, this log file will be named Manage-HPBiosSettings.Log. If the script is being run during a task sequence, the log file will be located in the _SMSTSLogPath. Otherwise, the log file will be located in ProgramData\\ConfigJonScripts\\HP. The log file name and path can be changed using the LogFile parameter. Note that the log file path will always be set to _SMSTSLogPath when run during a task sequence.\nThe script has logic built-in to detect if settings were already set correctly, were successfully set, failed to set, or were not found on the device. The script will output these counts to the screen at the end. More detailed information about the settings will be written to the log file.\nI\u0026rsquo;ve noticed that over the years, HP BIOS setting names have not remained consistent. Because of this, there can be multiple different ways to specify the same setting across different HP models. I have included a few example settings files in my GitHub. These settings files contain commonly configured HP BIOS settings that cover a wide range of HP hardware models.\nSettings_CSV_SecureBoot,csv - Contains settings for enabling UEFI and Secure Boot Settings_CSV_TPM,csv - Contains settings for enabling and activating TPM Settings_CSV_General.csv - Contains other common settings Settings_In-Script_All.txt - Contains common settings formatted for use in the body of the script Examples The script can be run as a standalone script in Windows, or as a part of a Configuration Manager task sequence. It can also be run in the full Windows OS or in WinPE.\nHere are a few examples of calling the script from a PowerShell prompt.\n#Set BIOS settings supplied in the script Manage-HPBiosSettings.ps1 -SetSettings -SetupPassword ExamplePassword #Set BIOS settings supplied in a CSV file Manage-HPBiosSettings.ps1 -SetSettings -CsvPath C:\\Temp\\Settings.csv -SetupPassword ExamplePassword #Output a list of current BIOS settings to the screen Manage-HPBiosSettings.ps1 -GetSettings #Output a list of current BIOS settings to a CSV file Manage-HPBiosSettings.ps1 -GetSettings -CsvPath C:\\Temp\\Settings.csv Here is an example of calling the script during a task sequence. In this example the settings are specified in the body of the script, so the script can be stored directly in the task sequence step. Also the setup password is set, so the SetupPassword parameter is specified.\nIn this second example, the script is being called from a package and the settings are being supplied from a CSV file.\nAdditional Reading If you\u0026rsquo;re looking for other options for managing HP BIOS settings, check out these links. The HP BIOS Configuration Utility is a tool provided by HP, it\u0026rsquo;s been around for years, and works well. The HP Client Management Script Library contains PowerShell scripts written by HP to manage BIOS settings. This is a good place to start if you want to write your own HP PowerShell solution. For information on configuring HP BIOS passwords using PowerShell, see my post HP BIOS Password Management.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/hp-bios-settings-management/","summary":"\u003cp\u003e\u003cstrong\u003eThis post was updated on September 18th, 2020.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThis post is one of 3 posts in my series on managing BIOS settings using PowerShell. I\u0026rsquo;ve also written about \u003cstrong\u003e\u003ca href=\"/dell-bios-settings-management/\"\u003eDell\u003c/a\u003e\u003c/strong\u003e and \u003cstrong\u003e\u003ca href=\"/lenovo-bios-settings-management/\"\u003eLenovo\u003c/a\u003e\u003c/strong\u003e. In this post I\u0026rsquo;ll be talking about using PowerShell to manage HP BIOS settings.\u003c/p\u003e\n\u003cp\u003eThe script can be downloaded from my GitHub: \u003cstrong\u003e\u003ca href=\"https://github.com/ConfigJon/Firmware-Management/tree/master/HP\"\u003ehttps://github.com/ConfigJon/Firmware-Management/tree/master/HP\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003ch3 id=\"hp-wmi-and-powershell\"\u003eHP, WMI, and PowerShell\u003c/h3\u003e\n\u003cp\u003eHP provides a WMI interface that can be used for querying and modifying BIOS settings on their hardware models. This means that we can use PowerShell to directly view and edit BIOS settings without the need for a vendor specific program. This script uses 3 of the HP provided WMI classes.\u003c/p\u003e","title":"HP BIOS Settings Management"},{"content":"This post was updated on September 18th, 2020.\nIn my last blog post, (Lenovo BIOS Password Management), I talked about managing Lenovo BIOS passwords with PowerShell. I liked how that process worked, so I decided to create a similar process to handle HP BIOS passwords. Once again, the goal was to have a script that could automatically set, change, or clear BIOS passwords while providing logging and optional user prompts. In this post, I’ll cover the basics of how the script works and some limitations of the script.\nThe script can be downloaded from my GitHub. https://github.com/ConfigJon/Firmware-Management/tree/master/HP\nHP, WMI, and PowerShell HP provides a WMI interface that can be used for querying and modifying BIOS settings on their hardware models. This means that we can use PowerShell to directly view and edit BIOS settings without the need for a vendor specific program. This script deals specifically with HP BIOS passwords, so in this post, I will only be discussing the classes related to password management.\nThe first thing that needs to be done is to determine what passwords are currently configured. This information can be obtained from the HP_BIOSSetting WMI class under the root/hp/InstrumentedBIOS WMI namespace.\n#Connect to the HP_BIOSSetting WMI class $HPBiosSettings = Get-WmiObject -Namespace root/hp/InstrumentedBIOS -Class HP_BIOSSetting #Check the status of the setup password ($HPBiosSetting | Where-Object Name -eq \u0026#34;Setup Password\u0026#34;).IsSet #Check the status of the power-On password ($HPBiosSetting | Where-Object Name -eq \u0026#34;Power-On Password\u0026#34;).IsSet Checking the status of the passwords will return either a 0 or a 1.\n0 - No password set 1 - Password set The next step is to action on this data and set, change, or clear the BIOS password. To accomplish this, we need to connect to the HP_BIOSSettingInterface WMI class under the root/hp/InstrumentedBIOS WMI namespace.\n#Connect to the HP_BIOSSettingInterface WMI class $Interface = Get-WmiObject -Namespace root/hp/InstrumentedBIOS -Class HP_BIOSSettingInterface #Set a new setup password $Interface.SetBIOSSetting(\u0026#34;Setup Password\u0026#34;,\u0026#34;\u0026lt;utf-16/\u0026gt;\u0026#34; + \u0026#34;NewPassword\u0026#34;,\u0026#34;\u0026lt;utf-16/\u0026gt;\u0026#34;) #Change an existing setup password $Interface.SetBIOSSetting(\u0026#34;Setup Password\u0026#34;,\u0026#34;\u0026lt;utf-16/\u0026gt;\u0026#34; + \u0026#34;NewPassword\u0026#34;,\u0026#34;\u0026lt;utf-16/\u0026gt;\u0026#34; + \u0026#34;OldPassword\u0026#34;) #Clear an existing setup password $Interface.SetBIOSSetting(\u0026#34;Setup Password\u0026#34;,\u0026#34;\u0026lt;utf-16/\u0026gt;\u0026#34;,\u0026#34;\u0026lt;utf-16/\u0026gt;\u0026#34; + \u0026#34;OldPassword\u0026#34;) The HP_BIOSSettingInterface WMI class contains a method called SetBIOSSetting. This method allows for changing HP BIOS settings. In this case, we are changing the \u0026ldquo;Setup Password\u0026rdquo; setting. The format for changing a password is (Password Type, NewPassword, OldPassword). Additionally, when specifying the password values, the encoding of the passwords must also be specified. This is done by adding \u0026ldquo;\u0026rdquo; in front of the password. This encoding must be specified even when the password value is blank (look at the password set or password clear examples).\nFor reference, these are the possible return codes for the SetBIOSSetting method:\n0 - Success 1 - Not Supported 2 - Unspecified Error 3 - Timeout 4 - Failed (Usually caused by a typo in the setting value) 5 - Invalid Parameter 6 - Access Denied (Usually caused by an incorrect BIOS password) For more detailed information on the HP WMI interface, refer to the official documentation: http://h20331.www2.hp.com/Hpsub/downloads/cmi_whitepaper.pdf\nManage-HPBiosPasswords.ps1 This script takes the basic commands we just looked at and adds logic to allow for a more automated password management process. The script accepts parameters that tell it which actions to perform.\nSetupSet - Set a new setup password or change an existing setup password SetupClear – Clear an existing setup password PowerOnSet - Set a new power on password or change an existing power on password PowerOnClear – Clear an existing power on password There are also parameters that are used to specify the new and old BIOS passwords.\nSetupPassword – The current setup password or password to be set OldSetupPassword – The old setup password(s) to be changed. Multiple old passwords can be specified (separated by a comma). See the Limitations section of this post for more information. PowerOnPassword – The current power on password or password to be set OldPowerOnPassword – The old power on password(s) to be changed. Multiple old passwords can be specified (separated by a comma). See the Limitations section of this post for more information. By default, if the script fails to perform any of these actions, it will display a message box on the screen and exit with an error code. This can be useful in a task sequence scenario where you may not want a system to continue with the task sequence if the BIOS password is not set correctly. However, if you want the script to be completely silent, there are a few parameters that can be set.\nNoUserPrompt – Suppress all user prompts ContinueOnError – Ignore any errors caused by changing or clearing passwords When the script runs, it will write to a log file. By default, this log file will be named Manage-HPBiosPasswords.Log. If the script is being run during a task sequence, the log file will be located in the _SMSTSLogPath. Otherwise, the log file will be located in ProgramData\\ConfigJonScripts\\HP. The log file name and path can be changed using the LogFile parameter. Note that the log file path will always be set to _SMSTSLogPath when run during a task sequence.\nLimitations Password Lockout\nThis limitation is imposed by HP for security reasons. If enough wrong password attempts are made, the system will lock and require a reboot to continue attempting passwords. I\u0026rsquo;ve tested a few different HP models, and they all seem to lock after 3 failed password attempts.\nEven though the lockout number is 3, the way this script is written, you can only specify 2 old passwords in the old password parameters. This is because the script first tests if the password is already set to the value passed in the new password parameters, which eats up 1 of those lockout attempts if incorrect.\nFor example, if the script is instructed to change a setup password, the first thing it does, is test the current password against the value passed in the SetupPassword parameter. If it does not match, this counts as 1 failed attempt. The script then attempts to change the password to the values passed in the OldSetupPassword parameter. However, since we are already at 1 failed attempt after the first test, we can only try 2 more passwords before needing a reboot.\nIf this script is being run during a task sequence, and there are 4 different potential old passwords, and the device locks after 3 failed attempts, the script would need to be called with Password1 and Password2 specified as old passwords. Then a reboot would need to happen. Then the script would need to be run a second time with Password3 and Password4 specified as old passwords.\nThere is a check in the parameter validation section of the script that will throw an error if 2 or more old passwords are specified. If you need to increase this limit, either comment out or modify those lines.\nExamples The script can be run as a standalone script in Windows, or as a part of a Configuration Manager task sequence. It can also be run in the full Windows OS or in WinPE.\nHere are a few examples of calling the script from a PowerShell prompt in Windows.\nSet a new setup password Manage-HPBiosPasswords.ps1 -SetupSet -SetupPassword \u0026lt;String\u0026gt; Set a new setup password or change an existing setup password Manage-HPBiosPasswords.ps1 -SetupSet -SetupPassword \u0026lt;String\u0026gt; -OldSetupPassword \u0026lt;String1\u0026gt;,\u0026lt;String2\u0026gt; Change an existing Setup password and clear a power on password Manage-HPBiosPasswords.ps1 -SetupSet -SetupPassword \u0026lt;String\u0026gt; -OldSetupPassword \u0026lt;String1\u0026gt;,\u0026lt;String2\u0026gt; -PowerOnClear -OldPowerOnPassword \u0026lt;String1\u0026gt;,\u0026lt;String2\u0026gt; Here is a basic example of calling the script during a task sequence. This is likely one of the most common ways the script would be called in a task sequence. In this example the setup password will be set if it doesn\u0026rsquo;t exist, and it will be changed if it does already exist.\n-SetupSet -SetupPassword %NewPassword% -OldSetupPassword %OldPassword1% Here is a second example of calling the script during a task sequence. In this example, the setup password is being set or changed and there are 6 possible old setup passwords. The hardware the script is being run against will lock after 3 failed attempts, so only 2 old passwords can be specified before a reboot is required. The means that the script will need to be run 3 times.\nFirst in the Set Password Values step, create variables for each password.\nThe First Pass folder has no conditions on it, as we want it to run for any HP system. To set a new setup password or change an existing setup password, the SetupSet parameter is specified along with the SetupPassword and OldSetupPassword parameters.\nBecause the script will need to run multiple times, there is one additional parameter that needs to be specified. The SMSTSPasswordRetry parameter instructs the script to not display prompts to the screen until all attempts have completed. In this scenario, the script needs to be run 3 times, so SMSTSPasswordRetry parameter is specified on the first 2 passes of the script and not on the final pass. When the password(s) are successfully changed or cleared, the SMSTSPasswordRetry variable will be set to false. This means that if the first pass of the script is successful, the second and third passes of the script will be skipped.\n-SetupSet -SetupPassword %NewPassword% -OldSetupPassword %OldPassword1%,%OldPassword2% -SMSTSPasswordRetry When the script runs during a task sequence, it will create task sequence variables to track the success or failure of each different script action. If any one of the password actions fails, the associated task sequence variable will be set to Failed.\nHPSetSetup HPClearSetup HPSetPowerOn HPClearPowerOn As I mentioned before, the first run of the script in the task sequence does not have any conditions, but each successive run of the script should have these conditions.\nThe second pass of the script. Notice the SMSTSPasswordRetry parameter is specified because there is still another potential pass of the script yet to run.\n-SetupSet -SetupPassword %NewPassword% -OldSetupPassword %OldPassword3%,%OldPassword4% -SMSTSPasswordRetry The third pass of the script. Notice the SMSTSPasswordRetry parameter is not set because this is the final pass of the script.\n-SetupSet -SetupPassword %NewPassword% -OldSetupPassword %OldPassword5%,%OldPassword6% If at the end of the 3 passes of the script, the password was still not successfully changed, a message would then be prompted on the screen informing the imaging technician.\nThe end result of all of this is a script that can be used to change or clear HP BIOS passwords. The script can be run in a task sequence and persist information across multiple reboots. This allows for the user to be correctly prompted about any required manual actions even if there are many old passwords to test.\nAdditional Reading If you’re looking to configure HP BIOS settings other than just the passwords, check out these links. HP BIOS Settings Management, HP BIOS Configuration Utility, and HP Client Management Script Library.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/hp-bios-password-management/","summary":"\u003cp\u003e\u003cstrong\u003eThis post was updated on September 18th, 2020.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eIn my last blog post, (\u003cstrong\u003e\u003ca href=\"/lenovo-bios-password-management/\"\u003eLenovo BIOS Password Management\u003c/a\u003e\u003c/strong\u003e), I talked about managing Lenovo BIOS passwords with PowerShell. I liked how that process worked, so I decided to create a similar process to handle HP BIOS passwords. Once again, the goal was to have a script that could automatically set, change, or clear BIOS passwords while providing logging and optional user prompts. In this post, I’ll cover the basics of how the script works and some limitations of the script.\u003c/p\u003e","title":"HP BIOS Password Management"},{"content":"This post was updated on October 18th, 2020.\nThis post discusses how to manage Lenovo BIOS passwords using WMI. My goal was to have a script that could change or clear existing passwords and could display a prompt to the screen when manual intervention was required. In this post, I\u0026rsquo;ll cover the basics of how the script works. I\u0026rsquo;ll also talk about some limitations of the script and some areas it could be improved in the future\nThe script can be downloaded from my GitHub. https://github.com/ConfigJon/Firmware-Management/tree/master/Lenovo\nLenovo, WMI, and PowerShell Lenovo provides a WMI interface that can be used for querying and modifying BIOS settings on their hardware models. This means that we can use PowerShell to directly view and edit BIOS settings without the need for a vendor specific program. This script deals specifically with Lenovo BIOS passwords, so in this post, I will only be discussing the classes related to password management.\nThe first thing that needs to be done is to determine what passwords are currently configured. This information can be obtained from the Lenovo_BiosPasswordSettings class.\n$PasswordSettings = Get-WmiObject -Namespace root\\wmi -Class Lenovo_BiosPasswordSettings $PasswordSettings.PasswordState These two lines will return a number that tells us what passwords are currently set. For reference, this is what each value means:\n0 - No passwords set 1 - Power on password set 2 - Supervisor password set 3 - Power on and supervisor passwords set 4 - Hard drive password(s) set 5 - Power on and hard drive passwords set 6 - Supervisor and hard drive passwords set 7 - Supervisor, power on, and hard drive passwords set 64 - System management password set 65 - System management and power on passwords set 66 - System management and supervisor passwords set 67 - System management, supervisor, and power on passwords set 68 - System management and hard drive passwords set 69 - System management, power on, and hard drive passwords set 70 - System management, supervisor, and hard drive passwords set 71 - System management, supervisor, power on, and hard drive passwords set The next step is to action on this data and either change or clear the BIOS password. This can be done using the Lenovo_SetBiosPassword class.\n$PasswordSet = Get-WmiObject -Namespace root\\wmi -Class Lenovo_SetBiosPassword $PasswordSet.SetBiosPassword(\u0026#34;pap,OldPassword,NewPassword,ascii,us\u0026#34;) These two lines will attempt to change the supervisor password from OldPassword to NewPassword. The type of password being modified is determined by the first value inside the double quotes, in this case pap, which is the supervisor password. For reference, here are the values for the other password types:\npap - Supervisor password pop - Power on password smp - System management password uhdp1 - User hard drive password mhdp1 - Master hard drive password Here are some additional examples.\n#Change the supervisor password $PasswordSet.SetBiosPassword(\u0026#34;pap,OldPassword,NewPassword,ascii,us\u0026#34;) #Change the power on password $PasswordSet.SetBiosPassword(\u0026#34;pop,OldPassword,NewPassword,ascii,us\u0026#34;) #Change the system management password $PasswordSet.SetBiosPassword(\u0026#34;smp,OldPassword,NewPassword,ascii,us\u0026#34;) #Clear the supervisor password $PasswordSet.SetBiosPassword(\u0026#34;pap,OldPassword,,ascii,us\u0026#34;) #Clear the power on password $PasswordSet.SetBiosPassword(\u0026#34;pop,OldPassword,,ascii,us\u0026#34;) #Clear the system management password $PasswordSet.SetBiosPassword(\u0026#34;smp,OldPassword,,ascii,us\u0026#34;) For more detailed information on the Lenovo WMI interface, as well as a list of supported hardware models, refer to the official documentation. https://support.lenovo.com/us/en/solutions/ht100612\nManage-LenovoBiosPasswords.ps1 This script takes the basic commands we just looked at and adds logic to allow for a more automated password management process. The script accepts parameters that tell it which actions to perform.\nSupervisorSet - Change an existing supervisor password SupervisorClear - Clear an existing supervisor password PowerOnSet - Change an existing power on password PowerOnClear - Clear an existing power on password SystemManagementSet - Change an existing system management password SystemManagementClear - Clear an existing system management password HDDPasswordClear - Clear an existing user and/or master hard drive password There are also parameters that are used to specify the new and old BIOS passwords.\nSupervisorPassword - The current supervisor password or password to be set OldSupervisorPassword - The old supervisor password(s) to be changed. Multiple old passwords can be specified (separated by a comma). See the Limitations section of this post for more information. PowerOnPassword - The current power on password or password to be set OldPowerOnPassword - The old power on password(s) to be changed. Multiple old passwords can be specified (separated by a comma). See the Limitations section of this post for more information. SystemManagementPassword - The current system management password or password to be set OldSystemManagementPassword - The old system management password(s) to be changed. Multiple old passwords can be specified (separated by a comma). See the Limitations section of this post for more information. HDDUserPassword - The current user hard drive password to be cleared HDDMasterPassword - The current master hard drive password to be cleared By default, if the script fails to perform any of these actions, it will display a message box on the screen and exit with an error code. This can be useful in a task sequence scenario where you may not want a system to continue with the task sequence if the BIOS password is not set correctly. However, if you want the script to be completely silent, there are a few parameters that can be set.\nNoUserPrompt - Suppress all user prompts ContinueOnError - Ignore any errors caused by changing or clearing passwords. (Will not ignore parameter validation errors) When the script runs, it will write to a log file. By default, this log file will be named Manage-LenovoBiosPasswords.Log. If the script is being run during a task sequence, the log file will be located in the _SMSTSLogPath. Otherwise, the log file will be located in ProgramData\\ConfigJonScripts\\Lenovo. The log file name and path can be changed using the LogFile parameter. Note that the log file path will always be set to _SMSTSLogPath when run during a task sequence.\nLimitations and Known Issues Blank Passwords\nThe first limitation is actually imposed by Lenovo for security reasons. The first time a BIOS password is set, it must be set manually. It is not possible to programmatically set a BIOS password when one does not already exist. The script does have logic to detect for this scenario, and will throw an error and prompt the user if that is the case.\nLenovo has recently added a System Deployment Boot Mode to newer hardware models that allows setting a password. I will look into this more in the future to see if it can be incorporated into the script.\nPassword Lockout\nThe second limitation is also imposed by Lenovo for security reasons. If enough wrong password attempts are made, the system will lock and require a reboot to continue attempting passwords. In my testing with Lenovo hardware, I\u0026rsquo;ve found some models lock after 3 failed password attempts, and some lock after 6 failed password attempts.\nEven though the lockout number is 3 or 6, depending on hardware model, the way this script is written, you can only specify either 2 or 5 old passwords in the old password parameters. This is because the script first tests if the password is already set to the value passed in the new password parameters, which eats up 1 of those lockout attempts if incorrect.\nFor example, if the script is instructed to change a supervisor password, the first thing it does, is test the current password against the value passed in the SupervisorPassword parameter. If it does not match, this counts as 1 failed attempt. The script then attempts to change the password to the values passed in the OldSupervisorPassword parameter. However, since we are already at 1 failed attempt after the first test, we can only try 2 more passwords before needing a reboot.\nIf this script is being run during a task sequence, and there are 4 different potential old passwords, and the device locks after 3 failed attempts, the script would need to be called with Password1 and Password2 specified as old passwords. Then a reboot would need to happen. Then the script would need to be run a second time with Password3 and Password4 specified as old passwords.\nThere are 2 checks in the parameter validation section of the script that will throw an error if 2 or more old passwords are specified. If you need to increase this limit, either comment out or modify those lines. Additionally, if too many failed password attempts are made and the BIOS setting Password Count Exceeded Error is set to Enabled, on the next reboot a message will be displayed on screen and require a user input.\nMultiple Configured Passwords\nWhen multiple types of passwords are set on a system, there are different requirements for which passwords must be specified to complete some actions.\nIf the supervisor and power on passwords are set The supervisor password is required to change or clear the power on password If the supervisor and system management passwords are set The supervisor password is required to change or clear the system management password If the system management and power on passwords are set The system management password is required to change or clear the power on password Power On Password Issue\nIn my testing I\u0026rsquo;ve run into an issue where the SetBiosPassword WMI method will always report success (even in a failure situation) when attempting to change or clear the power on password. When attempting to change a password, my script will first check to see if the supplied password is already set correctly. If it is not, the SetBiosPassword method should return a failure, but when this issue occurs, the SetBiosPassword always returns success. This causes the script to think the power on password has been changed, when in reality, it has not.\nAnother symptom of this issue is after a failed (reported success) attempt to change or clear the power on password, an error message will be displayed on the screen during the next system reboot. The message is: 0191: System Security - Invalid remote change requested.\nHard Drive Passwords\nCurrently the script only has logic to clear existing hard drive passwords. In my testing, I found that when attempting to change or clear a hard drive password, the command always returns Success even if it failed. This makes it difficult to determine if the command actually worked or not. If you are planning to use the hard drive password parameters, ensure that the passwords being used are correct. I\u0026rsquo;d love to hear from you if you have tips on better dealing with Lenovo hard drive passwords. This is definitely an area of the script that could use improvement.\nExamples The script can be run as a standalone script in Windows, or as a part of a Configuration Manager task sequence. It can also be run in the full Windows OS or in WinPE.\nHere are a few examples of calling the script from a PowerShell prompt in Windows.\n#Change an existing supervisor password Manage-LenovoBiosPasswords.ps1 -SupervisorSet -SupervisorPassword Password1 -OldSupervisorPassword Password2 #Clear an existing supervisor password Manage-LenovoBiosPasswords.ps1 -SupervisorClear -OldSupervisorPassword Password1 #Change an existing system management password when the supervisor password is also set Manage-LenovoBiosPasswords.ps1 -SystemManagementSet -SystemManagementPassword Password1 -SupervisorPassword Password2 #Change an existing supervisor password and clear a power on password Manage-LenovoBiosPasswords.ps1 -SupervisorSet -SupervisorPassword Password1 -OldSupervisorPassword Password2 -PowerOnClear #Clear an existing power on password when only the power on password is set, suppress any user prompts, and continue on error Manage-LenovoBiosPasswords.ps1 -PowerOnClear -OldPowerOnPassword Password1,Password2 -NoUserPrompt -ContinueOnError Here is a basic example of calling the script during a task sequence. In this example the supervisor password is being changed and there is only 1 possible old supervisor password.\n-SupervisorSet -SupervisorPassword %NewPassword% -OldSupervisorPassword %OldPassword% Here is a second example of calling the script during a task sequence. In this example, the supervisor password is being changed and there are 6 possible old supervisor passwords. The hardware the script is being run against will lock after 3 failed attempts, so only 2 old passwords can be specified before a reboot is required. The means that the script will need to be run 3 times.\nFirst in the Set Password Values step, create variables for each password.\nThe First Pass folder has no conditions on it, as we want it to run for any Lenovo system. To change a supervisor password, the SupervisorSet parameter is specified along with the SupervisorPassword and OldSupervisorPassword parameters.\nBecause the script will need to run multiple times, there is one additional parameter that needs to be specified. The SMSTSPasswordRetry parameter instructs the script to not display prompts to the screen until all attempts have completed. In this scenario, the script needs to be run 3 times, so SMSTSPasswordRetry parameter is specified on the first 2 passes of the script and not on the final pass. When the password(s) are successfully changed or cleared, the SMSTSPasswordRetry variable will be set to false. This means that if the first pass of the script is successful, the second and third passes of the script will be skipped.\n-SupervisorSet -SupervisorPassword %NewPassword% -OldSupervisorPassword %OldPassword1%,%OldPassword2% -SMSTSPasswordRetry When the script runs during a task sequence, it will create task sequence variables to track the success or failure of each different script action. If any one of the password actions fails, the associated task sequence variable will be set to Failed.\nLenovoSetSupervisor LenovoClearSupervisor LenovoSetPowerOn LenovoClearPowerOn LenovoSetSystemManagement LenovoClearSystemManagement As I mentioned before, the first run of the script in the task sequence does not have any conditions, but each successive run of the script should have these conditions.\nThe second pass of the script. Notice the SMSTSPasswordRetry parameter is specified because there is still another potential pass of the script yet to run.\n-SupervisorSet -SupervisorPassword %NewPassword% -OldSupervisorPassword %OldPassword3%,%OldPassword4% -SMSTSPasswordRetry The third pass of the script. Notice the SMSTSPasswordRetry parameter is not set because this is the final pass of the script.\n-SupervisorSet -SupervisorPassword %NewPassword% -OldSupervisorPassword %OldPassword5%,%OldPassword6% If at the end of the 3 passes of the script, the password was still not successfully changed, a message would then be prompted on the screen informing the imaging technician.\nThis script ended up being a lot longer and more complicated than I expected when I started, but the end result of all of this is a script that can be used to change or clear Lenovo BIOS passwords. The script can be run in a task sequence and persist information across multiple reboots. This allows for the user to be correctly prompted about any required manual actions even if there are many old passwords to test.\nAdditional Reading If you\u0026rsquo;re looking to configure Lenovo BIOS settings other than just the passwords, check out these links. Lenovo BIOS Settings Management is my own script. The Think BIOS Config Tool is an official tool released by Lenovo that allows for changing BIOS settings through a GUI interface or at the command line. The Lenovo BIOS Configurator is a script written by Martin Bengtsson. It\u0026rsquo;s a great example of using PowerShell to configure BIOS settings.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/lenovo-bios-password-management/","summary":"\u003cp\u003e\u003cstrong\u003eThis post was updated on October 18th, 2020.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThis post discusses how to manage Lenovo BIOS passwords using WMI. My goal was to have a script that could change or clear existing passwords and could display a prompt to the screen when manual intervention was required. In this post, I\u0026rsquo;ll cover the basics of how the script works. I\u0026rsquo;ll also talk about some limitations of the script and some areas it could be improved in the future\u003c/p\u003e","title":"Lenovo BIOS Password Management"},{"content":"The out of the box Windows 10 experience has improved over the years, but I still find most clients I work with want to make various tweaks and modifications to the default settings. In the past I would add these customizations to a Configuration Manager task sequence as individual steps. But I\u0026rsquo;m lazy, and I didn\u0026rsquo;t want to have to continually add each individual step over and over. Plus I like to keep task sequences shorter when I can. The solution was to create a PowerShell script that allows the admin to select which of the common Windows customizations to run in their environment.\nThere are two parts to the solution. The Parameters.ini file is where the admin makes their customization selections. The Customize_Windows.ps1 file imports data from the Parameters.ini file and then actions on that data.\nHere is a snippet from the Parameters.ini file.\n#Edge desktop shortcut. (1 = Remove shortcut) / (Not Configured (DEFAULT SETTING)) EdgeDesktopShortcut=1 # #Default file explorer view. (1 = This PC) (2 = Quick Access) / (Not Configured (DEFAULT SETTING)) #FileExplorerView=1 # #\u0026#34;Run as different user\u0026#34; in the Start menu. (1 = Show \u0026#34;Run As\u0026#34; in Start) / (Not Configured (DEFAULT SETTING)) RunAsUserStart=1 # Any line in the parameters file that starts with a # will be ignored by the main script. Any lines without a # at the beginning will be imported by the main script. A variable will be created with a name matching the string on the left side of the = sign. The value for that variable will be set to the string on the right side of the = sign.\nIn this example, a variable named EdgeDesktopShortcut will be created and set to a value of 1. Another variable named RunAsUserStart will be created and set to a value of 1. The FileExplorerView line will be ignored, as it begins with a #. The result of running the script will be the Edge desktop shortcut being deleted and the \u0026ldquo;Run as different user\u0026rdquo; option being accessible in the Start menu.\nHere is a snippet from the PowerShell script showing the customizations being run if the variable is created.\nif ($NULL -ne $EdgeDesktopShortcut) { New-RegistryValue -Customization \u0026#34;Edge Desktop Shortcut\u0026#34; -RegKey \u0026#34;HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\u0026#34; -Name \u0026#34;DisableEdgeDesktopShortcutCreation\u0026#34; -PropertyType DWord -Value $EdgeDesktopShortcut } if ($NULL -ne $FileExplorerView) { New-RegistryValue -Customization \u0026#34;File Explorer View\u0026#34; -RegKey \u0026#34;HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\u0026#34; -Name \u0026#34;LaunchTo\u0026#34; -PropertyType DWord -Value $FileExplorerView } if ($NULL -ne $RunAsUserStart) { New-RegistryValue -Customization \u0026#34;Run As User Start Menu\u0026#34; -RegKey \u0026#34;HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows\\Explorer\u0026#34; -Name \u0026#34;ShowRunasDifferentuserinStart\u0026#34; -PropertyType DWord -Value $RunAsUserStart } The majority of the customizations are registry modifications. However, there are a couple of options that warrant a quick explanation. The StartLayout and DefaultApps options in the Parameters.ini file require a .xml file name as input. The script will attempt to locate the specified files in the root directory of the PowerShell script. If using these options ensure all files are saved in the same directory. For more information on how to generate these files, see these links: Start Layout, Default Apps.\nThe PowerShell script has 1 parameter, -File, which is used to point to the Parameters.ini file. The script can be called during a Configuration Manager task sequence using a Run PowerShell Script step.\nThe full PowerShell script and a Parameters.ini file can be downloaded from my GitHub. https://github.com/ConfigJon/Windows-Customizations/tree/master/Customization-Script\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/windows-customizations-with-powershell/","summary":"\u003cp\u003eThe out of the box Windows 10 experience has improved over the years, but I still find most clients I work with want to make various tweaks and modifications to the default settings. In the past I would add these customizations to a Configuration Manager task sequence as individual steps. But I\u0026rsquo;m lazy, and I didn\u0026rsquo;t want to have to continually add each individual step over and over. Plus I like to keep task sequences shorter when I can. The solution was to create a PowerShell script that allows the admin to select which of the common Windows customizations to run in their environment.\u003c/p\u003e","title":"Windows Customizations with PowerShell"},{"content":"I was working with a client that had a requirement where each computer that was deployed needed to be paired with a physical document that had information about the computer. The solution I used to automate this process was to use a PowerShell script to take information from a running task sequence, then write and print a Word document.\nHere is a high level outline of the process.\nInformation about the computer and deployment is collected by a PowerShell script during the task sequence The same PowerShell script then copies that information to a network share as a CSV file A separate computer or server has a Windows Scheduled Task set to run a second PowerShell script on a schedule The second PowerShell script takes any CSV files in the network location as input. It uses the data from the CSV files to build a Word document and then sends that document to a printer. This is the script that runs during the task sequence to collect information and write it to a CSV file on a network share. This example script is collecting the Serial Number, Asset Tag, and Computer Model.\nA network share needs to be specified as the destination for the CSV file. Credentials for a user account with write access to the network share also need to be specified.\n#Set account credentials to connect to network share $pass=\u0026#34;Password\u0026#34;|ConvertTo-SecureString -AsPlainText -Force $Cred = New-Object System.Management.Automation.PsCredential(\u0026#39;user@domain.local\u0026#39;,$pass) #Set network share used for CSV storage $netpath = \u0026#39;\\\\server.domain.local\\csv\u0026#39; #Connect to network drive New-PSDrive -name R -Root $netpath -Credential $cred -PSProvider filesystem -ErrorAction SilentlyContinue #Set variables $sn = Get-WmiObject Win32_ComputerSystemProduct | Select-Object -ExpandProperty IdentifyingNumber $asset = Get-WmiObject Win32_SystemEnclosure | Select-Object -ExpandProperty SmbiosAssetTag $model = Get-WmiObject Win32_ComputerSystem | Select-Object -ExpandProperty Model #Write data to the CSV and export to a file $data = @( [pscustomobject]@{ sn = $sn asset = $asset model = $model } ) $data | Export-Csv -Path \u0026#34;$netpath\\$sn.csv\u0026#34; -NoTypeInformation #Remove quotes from the CSV (Get-Content \u0026#34;$netpath\\$sn.csv\u0026#34;) | ForEach-Object {$_ -Replace \u0026#39;\u0026#34;\u0026#39;, \u0026#34;\u0026#34;} | Out-File \u0026#34;$netpath\\$sn.csv\u0026#34; -Force -Encoding ascii This is the script that takes the CSV files as input, creates a Word document, and then prints the document. I had this script running as a scheduled task on the server every 10 mintues. This example shows some examples of basic formatting (making a list, injecting an image file, changing font size, etc.)\nThe location of the CSV files to take as input needs to be specified.\n#Script to create a word document based on variables from a computer running the deploy task sequence. #Set the path where the CSV files are stored $csvpath = \u0026#39;C:\\CSV\u0026#39; #Get CSV files in the specified path $csvs = Get-ChildItem \u0026#34;$csvpath\\*.csv\u0026#34; #Run a loop to import CSV files and data ForEach ($csv in $csvs) { $csvdata = Import-Csv \u0026#34;$csv\u0026#34; ForEach ($data in $csvdata) { $SN = $data.sn $Asset = $data.asset $Model = $data.model } #----------------------------------------------- #----------------------------------------------- #Create a new Word document $word = New-Object -ComObject Word.Application $Document = $Word.Documents.Add() $Selection = $Word.Selection #Uncomment to make the Word Document visible #$Word.Visible = $True #----------------------------------------------- #----------------------------------------------- #Format the Word document #Set margins $Selection.PageSetup.LeftMargin = 36 $Selection.PageSetup.RightMargin = 36 $Selection.PageSetup.TopMargin = 36 $Selection.PageSetup.BottomMargin = 36 #Title $Selection.Style = \u0026#39;Title\u0026#39; $Selection.ParagraphFormat.Alignment = 1 $Selection.Borders.OutsideLineStyle = 1 $Selection.TypeText(\u0026#34;New Computer Information\u0026#34;) $Selection.TypeParagraph() $Selection.TypeParagraph() #Numbered List $Selection.Style = \u0026#39;List Number\u0026#39; $Selection.Font.Size = 12 $Selection.TypeText(\u0026#34;The computer model is: \u0026#34;) $Selection.Font.Bold = 1 $Selection.TypeText(\u0026#34;$model\u0026#34;) $Selection.Font.Bold = 0 $Selection.TypeParagraph() $Selection.TypeText(\u0026#34;The computer serial number is: \u0026#34;) $Selection.Font.Bold = 1 $Selection.TypeText(\u0026#34;$SN\u0026#34;) $Selection.Font.Bold = 0 $Selection.TypeParagraph() $Selection.TypeText(\u0026#34;The computer asset tag is: \u0026#34;) $Selection.Font.Bold = 1 $Selection.TypeText(\u0026#34;$asset\u0026#34;) $Selection.Font.Bold = 0 $Selection.TypeParagraph() $Selection.Style = \u0026#39;No Spacing\u0026#39; #Insert and center image $Selection.ParagraphFormat.Alignment = 1 $Selection.InlineShapes.AddPicture(\u0026#34;C:\\CSV\\Images\\Image.png\u0026#34;) $Selection.TypeParagraph() $Selection.TypeParagraph() #Inser date imaged and add a line for the technician to sign $Selection.Font.Size = 12 $Selection.ParagraphFormat.Alignment = 0 $date = Get-Date -UFormat \u0026#34;%m / %d / %Y\u0026#34; $Selection.TypeText(\u0026#34;Imaged Date: $date - \u0026#34;) $Selection.TypeText(\u0026#34;Imaging Technician:_________________\u0026#34;) $Selection.TypeParagraph() #----------------------------------------------- #----------------------------------------------- #Save the Word document $SaveLoc = \u0026#34;$csvpath\\$SN.docx\u0026#34; $Document.SaveAs([ref]$SaveLoc,[ref]$SaveFormat::wdFormatDocument) $word.Quit() #----------------------------------------------- #----------------------------------------------- #Print the Word document Start-Process -Filepath \u0026#34;$csvpath\\$SN.docx\u0026#34; -verb print Start-Sleep -Seconds 10 #----------------------------------------------- #----------------------------------------------- #Move the Word document and delete the CSV file Move-Item -Path \u0026#34;$csvpath\\$SN.docx\u0026#34; -Destination \u0026#34;$csvpath\\Completed Documents\\$SN.docx\u0026#34; -Force Remove-Item \u0026#34;$csv\u0026#34; #----------------------------------------------- #----------------------------------------------- } #Cleanup the Word COM Object $null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$word) [gc]::Collect() [gc]::WaitForPendingFinalizers() Remove-Variable word This script uses the the Microsoft Word COM object to write the document line by line. More detailed information on all the available objects can be found Here.\nThis script example creates the Word document silently in the background. If you want the document to be visiable (useful for initially building the document and troubleshooting) uncomment this line in the script.\n$Word.Visible = $True I have made these scripts available for download on my GitHub page.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/create-and-print-a-word-document-with-powershell/","summary":"\u003cp\u003eI was working with a client that had a requirement where each computer that was deployed needed to be paired with a physical document that had information about the computer. The solution I used to automate this process was to use a PowerShell script to take information from a running task sequence, then write and print a Word document.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eHere is a high level outline of the process.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eInformation about the computer and deployment is collected by a PowerShell script during the task sequence\u003c/li\u003e\n\u003cli\u003eThe same PowerShell script then copies that information to a network share as a CSV file\u003c/li\u003e\n\u003cli\u003eA separate computer or server has a Windows Scheduled Task set to run a second PowerShell script on a schedule\u003c/li\u003e\n\u003cli\u003eThe second PowerShell script takes any CSV files in the network location as input. It uses the data from the CSV files to build a Word document and then sends that document to a printer.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThis is the script that runs during the task sequence to collect information and write it to a CSV file on a network share. This example script is collecting the Serial Number, Asset Tag, and Computer Model.\u003c/p\u003e","title":"Create and Print a Word Document with PowerShell"},{"content":"Lately I have been helping many people with moving their update workloads from Configuration Manager and WSUS to Windows Update for Business. The one thing I get the most questions about with the move to Windows Update for Business is how to monitor update compliance. The computers are now pointing to the internet for updates, and as a result, no longer report update compliance information to Configuration Manager or WSUS. The answer to this is the Update Compliance solution in Azure Log Analytics.\nUpdate Compliance is a free solution that can be added to a log analytics workspace. Once it is configured, computers can be configured to report update compliance information to the solution. For information about configuring Update Compliance see the Microsoft Docs.\nUpdate Compliance is pretty good out of the box. It returns back useful information about the status of updates, delivery optimization, Windows Defender, and more. However, I have been getting many questions about how to view more detailed or specific information in Update Compliance. Many of the default views either show too little or too much information.\nThe way to dig into this data and get more specific information is to utilize the Logs node of the log analytics workspace. This node allows for the creation of custom queries that can surface specific data. More information about analyzing log data in Azure can be found Here.\nIn this post I have included examples of many queries I have found to be useful for analyzing Update Compliance data.\nA few notes about the queries\nWhen the queries are run, no computer names are returned or the computer name is returned as a # sign - - This can be a sign that devices have not been allowed to include their device names as part of the data sent to the log analytics workspace. This setting can be configured either through group policy or Policy CSP (Intune). - The group policy location for the setting is - Computer Configuration \u0026gt; Policies \u0026gt; Administrative Templates \u0026gt; Windows Components \u0026gt; Data Collection and Preview Builds \u0026gt; Allow device name to be sent in Windows diagnostic data - The Policy CSP location for the setting is - System/AllowDeviceNameInDiagnosticData In these examples, the time range to search is being set to 30 days in the queries by TimeGenerated \u0026gt; ago(30d). This can be removed and the time range can be set in the GUI, or this value can be modified. Some of these examples search for a specific computer name or set values like DeploymentStatus and UpdateCategory. Note that the values in these queries are case sensitive. So if a result is not being displayed as expected, check the case. Some of these example queries contain filters for UpdateCategory and DeploymentStatus. These are the available values for these filters. Remember that these values are case sensitive. - UpdateCategory - Quality - Feature - DeploymentStatus - Update completed - In progress - Progress stalled - Failed - Unknown Update Installation Status Queries List Operating System Information - All Computers\nWaaSUpdateStatus| where TimeGenerated \u0026gt; ago(30d)| summarize arg_max(OSVersion, OSArchitecture, OSEdition) by Computer List Operating System Information - Specific Computer\nWaaSUpdateStatus| where Computer == \u0026#34;COMPUTERNAME\u0026#34; and TimeGenerated \u0026gt; ago(30d)| summarize arg_max(OSVersion, OSArchitecture, OSEdition) by Computer List Feature and Quality Update Status - All Computers\nWaaSUpdateStatus| where TimeGenerated \u0026gt; ago(30d)| summarize arg_max(OSFeatureUpdateStatus, OSQualityUpdateStatus) by Computer List Feature and Quality Update Status - Specific Computer\nWaaSUpdateStatus| where Computer == \u0026#34;COMPUTERNAME\u0026#34; and TimeGenerated \u0026gt; ago(30d)| summarize arg_max(OSFeatureUpdateStatus, OSQualityUpdateStatus) by Computer List Updates in a Specific State - All Computers\nWaaSDeploymentStatus| where UpdateCategory == \u0026#34;Quality\u0026#34; and DeploymentStatus == \u0026#34;Failed\u0026#34; and TimeGenerated \u0026gt; ago(30d)| summarize arg_max(ReleaseName, DeploymentStatus, DetailedStatus, DetailedStatusLevel) by Computer List Updates in a Specific State - Specific Computer\nWaaSDeploymentStatus| where Computer == \u0026#34;COMPUTERNAME\u0026#34; and UpdateCategory == \u0026#34;Quality\u0026#34; and DeploymentStatus == \u0026#34;Failed\u0026#34; and TimeGenerated \u0026gt; ago(30d)| summarize arg_max(Computer, DeploymentStatus, DetailedStatus, DetailedStatusLevel) by ReleaseName List Specific Update in a Specific State - All Computers\nWaaSDeploymentStatus| where ReleaseName startswith \u0026#34;KB4487017\u0026#34; and DeploymentStatus == \u0026#34;Update completed\u0026#34; and TimeGenerated \u0026gt; ago(30d)| summarize arg_max(ReleaseName, DeploymentStatus) by Computer List Specific Update Status - All Computers\nWaaSDeploymentStatus| where ReleaseName startswith \u0026#34;KB4487017\u0026#34; and TimeGenerated \u0026gt; ago(30d)| summarize arg_max(ReleaseName, DeploymentStatus) by Computer List Specific Update Status - Specific Computer\nWaaSDeploymentStatus| where Computer == \u0026#34;COMPUTERNAME\u0026#34; and ReleaseName startswith \u0026#34;KB4487017\u0026#34; and TimeGenerated \u0026gt; ago(30d)| summarize arg_max(ReleaseName, DeploymentStatus) by Computer Windows Update for Business Configuration Status Queries List Feature and Quality Update Deferral Settings - All Computers\nWaaSUpdateStatus| where TimeGenerated \u0026gt; ago(30d)| summarize arg_max(QualityDeferralDays, FeatureDeferralDays) by Computer List Feature and Quality Update Deferral Settings - Specific Computer\nWaaSUpdateStatus| where Computer == \u0026#34;COMPUTERNAME\u0026#34; and TimeGenerated \u0026gt; ago(30d)| summarize arg_max(QualityDeferralDays, FeatureDeferralDays) by Computer List Feature and Quality Update Pause Status - All Computers\nWaaSUpdateStatus| where TimeGenerated \u0026gt; ago(30d)| summarize arg_max(QualityPauseState, QualityPauseDays, FeaturePauseState, FeaturePauseDays) by Computer List Feature and Quality Update Pause Status - Specific Computer\nWaaSUpdateStatus| where Computer == \u0026#34;COMPUTERNAME\u0026#34; and TimeGenerated \u0026gt; ago(30d)| summarize arg_max(QualityPauseState, QualityPauseDays, FeaturePauseState, FeaturePauseDays) by Computer Delivery Optimization Configuration Status Queries List Download Mode - All Computers\nWUDOStatus| where TimeGenerated \u0026gt; ago(30d)| summarize arg_max(DownloadMode, ContentDownloadMode) by Computer List Download Mode - Specific Computer\nWUDOStatus| where Computer == \u0026#34;COMPUTERNAME\u0026#34; and TimeGenerated \u0026gt; ago(30d)| summarize arg_max(DownloadMode, ContentDownloadMode) by Computer List Download Sources - All Computers\nWUDOStatus| where TimeGenerated \u0026gt; ago(30d)| summarize arg_max(BytesFromCDN, BytesFromPeers, BytesFromGroupPeers, BytesFromIntPeers) by Computer List Download Sources - Specific Computer\nWUDOStatus| where Computer == \u0026#34;COMPUTERNAME\u0026#34; and TimeGenerated \u0026gt; ago(30d)| summarize arg_max(BytesFromCDN, BytesFromPeers, BytesFromGroupPeers, BytesFromIntPeers) by Computer List Computer Location - All Computers\nWUDOStatus| where TimeGenerated \u0026gt; ago(30d)| summarize arg_max(City, Country, ISP) by Computer List Computer Location - Specific Computer\nWUDOStatus| where Computer == \u0026#34;COMPUTERNAME\u0026#34; and TimeGenerated \u0026gt; ago(30d)| summarize arg_max(City, Country, ISP) by Computer Windows Defender Status Queries General Defender Information - All Computers\nWDAVStatus| where TimeGenerated \u0026gt; ago(30d)| summarize arg_max(UpdateStatus, LastDefinitionUpdateTime, DefinitionVersion, ProtectionState, LastScan) by Computer General Defender Information - Specific Computer\nWDAVStatus| where Computer == \u0026#34;COMPUTERNAME\u0026#34; and TimeGenerated \u0026gt; ago(30d)| summarize arg_max(UpdateStatus, LastDefinitionUpdateTime, DefinitionVersion, ProtectionState, LastScan) by Computer These queries return data that I have found useful. However, this is just the tip of the iceberg when it comes to data that can be surfaced through queries in Azure Log Analytics.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/update-compliance-log-analytics-queries/","summary":"\u003cp\u003eLately I have been helping many people with moving their update workloads from Configuration Manager and WSUS to Windows Update for Business. The one thing I get the most questions about with the move to Windows Update for Business is how to monitor update compliance. The computers are now pointing to the internet for updates, and as a result, no longer report update compliance information to Configuration Manager or WSUS. The answer to this is the \u003cstrong\u003e\u003ca href=\"https://docs.microsoft.com/en-us/windows/deployment/update/update-compliance-monitor\"\u003eUpdate Compliance\u003c/a\u003e\u003c/strong\u003e solution in Azure Log Analytics.\u003c/p\u003e","title":"Update Compliance Log Analytics Queries"},{"content":"I was setting up a Configuration Manager environment in HTTPS mode and I was running into issues with the server selecting a client authentication certificate.\nI was seeing these messages in the MPControl.log.\nI was seeing this message in the IIS log.\nI was getting a 2148204809 error which translates to A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider. That told me something was wrong with the root CA trust. Some searching online brought up a few useful posts on the subject.\nhttps://support.microsoft.com/en-us/help/2802568/internet-information-services-iis-8-may-reject-client-certificate-requ\nhttps://stackoverflow.com/questions/26247462/http-error-403-16-client-certificate-trust-issue\nIt turned out that the environment had a group policy that was installing Intermediate CA certificates into the Trusted Root CA store. So the solution was to move the intermediate certificates out of the root store and into the intermediate store.\nThis PowerShell command can be used to find the problem certificates on the server.\nGet-Childitem cert:\\LocalMachine\\root -Recurse | Where-Object {$_.Issuer -ne $_.Subject} This command can be used to move the problem certificates out of the Trusted Root CA store and into the Intermediate CA store.\nGet-Childitem cert:\\LocalMachine\\root -Recurse | Where-Object {$_.Issuer -ne $_.Subject} | Move-Item -Destination Cert:\\LocalMachine\\CA ","permalink":"https://4c4806b4.configjon-blog.pages.dev/management-point-root-ca-trust-issue-http-403/","summary":"\u003cp\u003eI was setting up a Configuration Manager environment in HTTPS mode and I was running into issues with the server selecting a client authentication certificate.\u003c/p\u003e\n\u003cp\u003eI was seeing these messages in the \u003cstrong\u003eMPControl.log\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/management-point-root-ca-trust-issue-http-403/images/Certificate_Error-1024x243.png\"\u003e\u003c/p\u003e\n\u003cp\u003eI was seeing this message in the \u003cstrong\u003eIIS log\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/management-point-root-ca-trust-issue-http-403/images/IIS_Error-1.png\"\u003e\u003c/p\u003e\n\u003cp\u003eI was getting a \u003cstrong\u003e2148204809\u003c/strong\u003e error which translates to \u003cstrong\u003eA certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.\u003c/strong\u003e That told me something was wrong with the root CA trust. Some searching online brought up a few useful posts on the subject.\u003c/p\u003e","title":"Management Point Root CA Trust Issue (HTTP 403)"},{"content":"This is an updated version of a post I made on the Now Micro blog last year. The original version of this post can be read Here.\nWhy is Local Administrator Password Management Needed?\nThe question of how to deal with users having administrative rights on computers or other network resources is one that has many different answers and has evolved over time. While the scenarios around network and domain administrative access may be more complex, the local administrative rights scenario should be very similar for almost everyone.\nA common scenario, in organizations of all sizes, is all workstations sharing the same local administrator account password. The help desk uses this local administrator password when needing to do something on a computer that requires administrative rights. Occasionally this password has been given out to normal users for various reasons.\nThis scenario has some large security issues.\nHelp desk users or other network administrators using the local administrator account makes it more difficult to maintain accountability. Actions taken as the local administrator account could have been carried out by anyone with access to the credentials. If a normal user is given the local administrator account credentials, they now have local administrator access to every computer with those credentials. As more people know the local administrator credentials, the more likely they are to get passed around to other users. Eventually many users that are not supposed to have access to the credentials have them. Malware can take advantage of a password being shared across all systems to spread throughout the network. How to Mitigate These Security Issues The local administrator account on domain joined devices should rarely, if ever, be used. Ideally, normal users would not have local administrative rights on computers. If a normal user did require local administrative access on a permanent basis, they should have access to a domain account that has been granted local administrative access to their computer. Help desk personnel should have access to domain accounts that are set as local administrators of devices they may need to manage or troubleshoot. Logging in as the local administrator account should be saved for the rare occasion that a computer loses its domain trust relationship and needs to be re-joined to the domain.\nNow that the local administrator account is going to rarely be used, it would be nice to be able to change that password, so anyone who previously had known it can no longer use it. This is where Microsoft’s Local Administrator Password Solution (LAPS) comes into play. LAPS is a solution developed by Microsoft to handle the management of the local administrative accounts on domain joined computers. Any device that LAPS is deployed to is able to randomize the local administrator password, store that password in Active Directory, and then change that password on a set schedule.\nInstall the LAPS Management Utilities Download the LAPS Installer(s) to a domain joined computer Run either the LAPSx64.msi or LAPSx86.msi depending on your computer’s architecture At the Welcome screen, click Next At the License Agreement screen, accept the EULA and click Next At the Feature Installation screen, select to install all the available features, and click Next At the Confirmation screen, click Install At the Completion screen, click Finish Extend the Active Directory Schema LAPS requires an AD schema extension to create the attributes needed to store the administrator password and the password expiration date.\nOn the computer that the LAPS management utilities are installed on, open a PowerShell prompt with an account that has Schema Admin rights Run the command to import the LAPS PowerShell module Import-Module AdmPwd.PS Run the command to extend the AD Schema Update-AdmPwdADSchema After extending the schema, there will be two new attributes visible on the properties of the computer objects in AD ms-Mcs-AdmPwd – This attribute stores the local administrator password ms-Mcs-AdmPwdExpirationTime – This attribute stores the password expiration time Configure Active Directory Computer Permissions By default, computers will only be able to read the AdmPwd and AdmPwdExpirationTime attributes. For LAPS to work, computers need to be able to write to both attributes. The below steps will grant write permission to both attributes for the SELF account, which will then allow computer objects to update their own password and expiration time attributes.\nOn the computer that the LAPS management utilities are installed on, open a PowerShell prompt with an account that has Domain Admin rights Run the command to import the LAPS PowerShell module Import-Module AdmPwd.PS Run the command to grant write permission to the SELF account. Replace OU Name with the name of the OU that contains computers that will be managed with LAPS. The permissions will apply to any sub OUs of the OU you specify. Set-AdmPwdComputerSelfPermission -Identity \u0026#34;OU Name\u0026#34; NOTE: In the examples throughout this article, the common name of the OU is specified. The common name of the OU can be specified if the name is unique, otherwise specify the distinguished name of the OU.\nConfigure Active Directory User Permissions By default, only Domain Admins will be able to view and change the password and reset time attributes. These commands will allow you to delegate rights to users or groups to be able to either read or change the attributes.\nDelegate rights to an AD user or group to view the password and reset time attributes On the computer that the LAPS management utilities are installed on, open a PowerShell prompt with an account that has Domain Admin rights Run the command to import the LAPS PowerShell module Import-Module AdmPwd.PS Run the command to delegate read access to a specific user or group. Replace OU Name with the name of the OU that the user or group will be able to read the attributes for. Replace User or Group Name with the name of the user or group that will be delegated the read permission. Multiple users or groups can be specified in a comma separated list. Set-AdmPwdReadPasswordPermission –Identity \u0026#34;OU Name\u0026#34; –AllowedPrincipals \u0026#34;User or Group Name\u0026#34; Delegate rights to an AD user or Group to modify the reset time attribute On the computer that the LAPS management utilities are installed on, open a PowerShell prompt with an account that has Domain Admin rights Run the command to import the LAPS PowerShell module Import-Module AdmPwd.PS Run the command to delegate write access to a specific user or group. Replace OU Name with the name of the OU that the user or group will be able to modify the reset time attribute on. Replace User or Group Name with the name of the user or group that will be able to modify the reset password attribute. Multiple users or groups can be specified in a comma separated list. Set-AdmPwdResetPasswordPermission –Identity \u0026#34;OU Name\u0026#34; -AllowedPrincipals \u0026#34;User or Group Name\u0026#34; Verify User Permissions After delegating rights, this command can be run against an OU to determine which users or groups have access to view the password and reset time attributes.\nOn the computer that the LAPS management utilities are installed on, open a PowerShell prompt with an account that has Domain Admin rights Run the command to import the LAPS PowerShell module Import-Module AdmPwd.PS Run the command to view the permissions on a specific OU. Replace OU Name with the name of the OU the command will run against. Find-AdmPwdExtendedRights –Identity \u0026#34;OU Name\u0026#34; By default, NT AUTHORITY\\SYSTEM, and Domain Admins should be listed as extended right holders. Additionally, the group that was delegated read permissions should be listed as an extended right holder.\nIf there are any other users or groups listed under the ExtendedRightHolders property, these could be users or groups that unintentionally have access to view the attributes. This can happen if a user or group was previously delegated rights to this OU and the All extended rights permission was selected.\nTo make sure any of these extra users or groups cannot view the password or reset time attributes, follow these steps\nNOTE: This process removes All extended rights for the selected principal. Make sure the selected principal still has the permissions required to complete any delegated tasks against this OU.\nOpen Active Directory Users and Computers as an account with Domain Admin rights Right click on the OU in question and select Properties Click on the Security tab Click Advanced Select the user or group to modify permissions for Click Edit Uncheck the All extended rights box At this point, Active Directory has been configured to support LAPS, computer objects have been given permission to update their password attributes, and the appropriate users have been delegated rights to read and reset the passwords. See Part 2 of this post for instructions on creating the group policy object needed to actually deploy the LAPS functionality to clients.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/microsoft-laps-step-by-step-part-1/","summary":"\u003cp\u003eThis is an updated version of a post I made on the Now Micro blog last year. The original version of this post can be read \u003ca href=\"https://blog.nowmicro.com/2018/02/28/configuring-laps-part-1-configuring-active-directory/\"\u003e\u003cstrong\u003eHere\u003c/strong\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eWhy is Local Administrator Password Management Needed?\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThe question of how to deal with users having administrative rights on computers or other network resources is one that has many different answers and has evolved over time. While the scenarios around network and domain administrative access may be more complex, the local administrative rights scenario should be very similar for almost everyone.\u003c/p\u003e","title":"Microsoft LAPS Step by Step - Part 1"},{"content":"This post is the second part of a two-part series on configuring and deploying the Microsoft Local Administrator Password Solution (LAPS). The First Post covered the steps needed to configure Active Directory to support LAPS. This post will cover the steps needed to enable the LAPS functionally on devices.\nIn order for the local administrator password to be randomized on devices, two conditions need to be met.\nThe client needs to have a group policy object linked that enables LAPS The client needs to have the LAPS group policy client-side extensions installed so it knows what LAPS is Configure Group Policy to Deploy LAPS Settings Group Policy is used to configure LAPS settings and to enable the LAPS functionally on targeted devices. The LAPS settings can be added to an existing group policy object, however in this example, a new group policy object will be created to deploy the settings.\nInstall the LAPS Group Policy Administrative Template Group policy does not natively know about the LAPS settings. The settings need to be pulled from an administrative template.\nLog onto the computer where the LAPS management utilities were installed If the management utilities need to be re-installed, see the Install the LAPS Management Utilities section of the First Post of this series for instructions on doing so Open a file explorer window and navigate to C:\\Windows\\PolicyDefinitions Copy the AdmPwd.admx file found in the root of the directory and the AdmPwd.adml file found in the en-US subdirectory Paste the files in the group policy central store The group policy central store is located at \\\\domain.fqdn\\SYSVOL\\domain.fqdn\\Policies\\PolicyDefinitions If no group policy central store exists, refer to the Microsoft Documentation for instructions on creating one Create a Group Policy Object to Deploy LAPS Settings Open the Group Policy Management Console with an account that has rights to create and deploy group policy objects in the domain Right click on the Group Policy Objects folder and select New Name the policy and click OK (In this example the policy is named LAPS) Right click on the newly created policy and select Edit In the Group Policy Management Editor window, expand Computer Configuration \u0026gt; Policies \u0026gt; Administrative Templates \u0026gt; LAPS There are 4 settings available Enable local admin password management – This setting tells the device to randomize its local administrator password. This setting is required for LAPS to work and should be Enabled Password Settings – This setting tells the device what complexity requirements the random password should adhere to. It also tells the device how long the password should be and how often the password should change. This setting is required for LAPS to work and should be Enabled Do not allow password expiration time longer than required by policy – If this setting is not set, the password expiration time on a device could manually be set to be longer than the expiration period specified in the Password Settings setting. This setting is optional but recommended. Name of administrator account to manage – By default, LAPS will manage the password of the built-in local administrator account. If this setting is enabled, an account other than the built-in administrator account can be managed. This setting is optional Once the settings have been configured, close the group policy management editor window In the group policy management console, right click on the OU that the policy will be applied to and select Link an Existing GPO Select the group policy object that was just created and click OK Deploy the LAPS Group Policy Client-Side Extension LAPS is enabled and configured on devices using Group Policy. However, devices do not natively know about the LAPS settings. To have the Group Policy apply correctly, a Group Policy Client-Side Extension (CSE) needs to first be deployed to devices. There are many ways to get the CSE installed on devices. This example will cover how to deploy the CSE using Microsoft Configuration Manager.\nCreate an Application to Deploy Microsoft LAPS Download the LAPS Installer (This example will cover creating an application to deploy the 64-bit LAPS Install) Copy the LAPSx64.msi to the network share that acts as the Configuration Manager source directory Open the Configuration Manager Admin Console and navigate to Software Library \u0026gt; Application Management \u0026gt; Applications Right click on Applications and select Create Application On the Create Application Wizard window, click the Browse button to select the MSI file that was just copied to the network and then click Next On the Import Information screen, click Next On the General Information screen Specify the name of the application In the Install Behavior drop down menu, ensure Install for System is selected Verify the installation program command line looks like this Msiexec /I “LAPSx64.msi” /qn /norestart On the Summary screen, click Next On the Completion screen, click Close Distribute the LAPS Application to Distribution Point(s) In the Configuration Manager Admin Console, navigate to Software Library \u0026gt; Application Management \u0026gt; Applications Right click on the LAPS application that was created in the previous section and select Distribute Content On the Distribute Content Wizard window, click Next On the Content screen, click Next On the Content Distribution screen, click the Add button, then select either a distribution point or a distribution point group to distribute the content to, then click Next On the Summary screen, click Next On the Completion screen, click Close Deploy the Microsoft LAPS Application In the Configuration Manager Admin Console, navigate to Software Library \u0026gt; Application Management \u0026gt; Applications Right click on the LAPS application that was created in the previous section and select Deploy On the Deploy Software Wizard window, use the Browse button to select a collection of devices to deploy this application to, then click Next On the Content screen, click Next On the Deployment Settings screen, choose whether you want to application to be Available (Optional to install through the Software Center) or Required (Automatically installed), then click Next On the Scheduling screen, select when the application will be installed on devices, then click Next On the User Experience screen, select how the application should appear in the software center and whether or not the application should respect any existing maintenance windows, then click Next On the Alerts screen, optionally configure deployment alerting, then click Next On the Summary screen, click Next On the Completion screen, click Close Looking up and Resetting Passwords Now that AD has been configured, the Group Policy Client-Side Extension has been deployed, and the Group Policy Object has been created, LAPS should be functioning on devices. There are two ways to look up passwords for devices, from the properties of the computer object in Active Directory or using the LAPS GUI utility.\nPassword Lookup in AD Open the Active Directory Users and Computers console Navigate to a computer object that has a random password set by LAPS Right click on the computer object and select Properties Select the Attribute Editor tab Find the ms-Mcs-AdmPwd attribute Password Lookup Using the LAPS GUI Utility Download the LAPS Installer Run the installer, and at the Custom Setup screen, ensure the Fat Client UI option is selected (This will install the LAPS GUI utility) Once the install has completed, open the Start menu and select the LAPS UI application In the Window that appears, type the computer name of a device that has a random password set by LAPS, then click Search The password for a given device can be reset by manually entering a new time in the New expiration time box and then clicking the Set button Password Reset Using PowerShell LAPS passwords can also be reset using a PowerShell cmdlet. Here is an example of what a password reset command would look like\nReset-AdmPwdPassword -ComputerName NameOfComputer -WhenEffective \u0026#34;11.30.2017 17:00\u0026#34; Password Reset When Re-Imaging a Computer Consider a scenario where a computer has had its local administrator password randomized by LAPS. The password is set to automatically change every 30 days. This device is re-imaged and re-joined to the domain using the same computer object.\nThis computer will now have the local administrator password set to whatever the imaging process sets it to. But the computer object in Active Directory will still show the old randomized password. This situation will exist until the 30 day password reset period occurs at which point the local administrator password will once again be randomized.\nTo get around this issue, the re-imaging process should automatically reset the password reset counter for the device. A PowerShell script that accomplishes this can be found HERE. Simply add this script to your Configuration Manager or MDT task sequence.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/microsoft-laps-step-by-step-part-2/","summary":"\u003cp\u003eThis post is the second part of a two-part series on configuring and deploying the Microsoft Local Administrator Password Solution (LAPS). The \u003ca href=\"/microsoft-laps-step-by-step-part-1/\"\u003e\u003cstrong\u003eFirst Post\u003c/strong\u003e\u003c/a\u003e covered the steps needed to configure Active Directory to support LAPS. This post will cover the steps needed to enable the LAPS functionally on devices.\u003c/p\u003e\n\u003cp\u003eIn order for the local administrator password to be randomized on devices, two conditions need to be met.\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003col\u003e\n\u003cli\u003eThe client needs to have a group policy object linked that enables LAPS\u003c/li\u003e\n\u003cli\u003eThe client needs to have the LAPS group policy client-side extensions installed so it knows what LAPS is\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"configure-group-policy-to-deploy-laps-settings\"\u003eConfigure Group Policy to Deploy LAPS Settings\u003c/h2\u003e\n\u003cp\u003eGroup Policy is used to configure LAPS settings and to enable the LAPS functionally on targeted devices. The LAPS settings can be added to an existing group policy object, however in this example, a new group policy object will be created to deploy the settings.\u003c/p\u003e","title":"Microsoft LAPS Step by Step - Part 2"},{"content":"As I spend time working in many different Configuration Manager environments, I find myself regularly needing to create Antimalware Policies. Most of the settings in the antimalware policies can be configured quickly, however the setting that always takes me the most time is the Exclusion Settings.\nThere needs to be different policies with different exclusion settings for different types of devices. Each of these separate policies have 3 different areas for adding file paths, file types, and processes. And for some reason, unknown to me, the dialog window for adding exclusions has a 260 character limit. This means that even if all the exclusion settings are in a list, you can\u0026rsquo;t just copy the whole list in at once. All this adds up to make this process time consuming and inconsistent.\nI figured PowerShell could be the answer to this problem (as it usually is). I saw that there are PowerShell cmdlets for working with antimalware policies, specifically New-CMAntimalwarePolicy and Set-CMAntimalwarePolicy. I used these cmdlets and wrote a PowerShell script.\nNote: The script needs to be run from a computer that has the Configuration Manager console installed, so the ConfigurationManager.psd1 module can be imported.\n\u0026lt;# .DESCRIPTION This script can be used to automatically add exclusion settings to a new or existing antimalware policy in Configuration Manager. .PARAMETER SiteCode Site Code of the target Configuration Manager envrionment .PARAMETER SiteServer Name of the Configuration Manager primary site server .PARAMETER CsvPath Path to the CSV file that contains the antimalware exclusions .PARAMETER PolicyName Name of the anitmalware policy to create or modify .EXAMPLE Create_Exclusions.ps1 -SiteCode PS1 -SiteServer cm.example.local -CsvPath \u0026#34;C:\\Temp\\Exchange.csv\u0026#34; -PolicyName \u0026#34;Exchange AV Exclusions\u0026#34; .NOTES Created by: Jon Anderson Reference: /create-configuration-manager-antimalware-policies-with-powershell/ #\u0026gt; #Parameters param( [Parameter(Mandatory=$true)][ValidateLength(3,3)][string]$SiteCode, [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$SiteServer, [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$CsvPath, [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$PolicyName ) #Get the current working directory $OriginalLocation = Get-Location | Select-Object -ExpandProperty Path #Check if the Configuration Manager console is installed $DriveLetter = Get-Volume | Select-Object -ExpandProperty DriveLetter ForEach ($Letter in $DriveLetter){ $ModulePath = \u0026#34;$($Letter):\\Program Files (x86)\\Microsoft Configuration Manager\\AdminConsole\\bin\\ConfigurationManager.psd1\u0026#34; If (Test-Path $ModulePath){Break} $ModulePath = \u0026#34;$($Letter):\\Program Files\\Microsoft Configuration Manager\\AdminConsole\\bin\\ConfigurationManager.psd1\u0026#34; If (Test-Path $ModulePath){Break} Clear-Variable -Name \u0026#34;ModulePath\u0026#34; } If ($NULL -eq $ModulePath) { Throw \u0026#34;Could not find \\Microsoft Configuration Manager\\AdminConsole\\bin\\ConfigurationManager.psd1. This script should be run from a computer with the Configuration Manager console installed.\u0026#34; } #Connect to the Configuration Manager site If (!(Test-Path $SiteCode\u0026#34;:\u0026#34;)) { Import-Module $ModulePath New-PSDrive -Name $SiteCode -PSProvider \u0026#34;AdminUI.PS.Provider\\CMSite\u0026#34; -Root $SiteServer } Set-Location $SiteCode\u0026#34;:\u0026#34; #Create the specified policy object if it does not already exist If (!(Get-CMAntimalwarePolicy -Name $PolicyName)) { New-CMAntimalwarePolicy -Name $PolicyName -Policy ExclusionSettings } #Declare the array objects $FilePath = @() $FileType = @() $Process = @() #Import CSV data into the arrays Import-Csv $CsvPath | ForEach-Object { $FilePath += $_.FilePath $FileType += $_.FileType $Process += $_.Process } #Remove blank lines from the arrays $FilePath = $filePath | Where-Object {$_} $FileType = $fileType | Where-Object {$_} $Process = $process | Where-Object {$_} #If the array is not empty, add the file paths to the specified antimalware policy If ($FilePath.count -gt 0) { Set-CMAntimalwarePolicy -Name $PolicyName -ExcludeFilePath $FilePath } #If the array is not empty, add the file types to the specified antimalware policy If ($FileType.count -gt 0) { Set-CMAntimalwarePolicy -Name $PolicyName -ExcludeFileType $FileType } #If the array is not empty, add the processes to the specified antimalware policy If ($Process.count -gt 0) { Set-CMAntimalwarePolicy -Name $PolicyName -ExcludeProcess $Process } #Set the working directory back to the original location Set-Location $OriginalLocation This script takes a CSV file as input. This allows me to maintain a few CSV files with all the common exclusion settings for various types of devices. I can then use this script to quickly and consistently import these exclusion settings into Configuration Manager. The CSV files need to have 3 headings (FilePath, FileType, Process). These 3 headings should be there even if one of the columns is blank.\nThe script has 4 mandatory parameters.\nSiteCode - The site code of the Configuration Manager environment SiteServer - The name of the Configuration Manager primary site server CsvPath - The full path to the CSV file containing the exclusion settings PolicyName - The name of the antimalware policy to either create or edit Here is an example of the script being run with the parameters specified.\nCreate_Exclusions.ps1 -SiteCode PS1 -SiteServer cm.example.local -CsvPath \u0026#34;C:\\Temp\\Exchange.csv\u0026#34; -PolicyName \u0026#34;Exchange AV Exclusions\u0026#34; I have uploaded the script as well as some example CSV files to my GitHub. The CSV files contain generic exclusion recommendations collected from these sites. (Configuration Manager, Domain Controller, Exchange Server) You will need to modify these exclusion settings to work with your own environment.\n","permalink":"https://4c4806b4.configjon-blog.pages.dev/create-configuration-manager-antimalware-policies-with-powershell/","summary":"\u003cp\u003eAs I spend time working in many different Configuration Manager environments, I find myself regularly needing to create Antimalware Policies. Most of the settings in the antimalware policies can be configured quickly, however the setting that always takes me the most time is the Exclusion Settings.\u003c/p\u003e\n\u003cp\u003eThere needs to be different policies with different exclusion settings for different types of devices. Each of these separate policies have 3 different areas for adding file paths, file types, and processes. And for some reason, unknown to me, the dialog window for adding exclusions has a 260 character limit. This means that even if all the exclusion settings are in a list, you can\u0026rsquo;t just copy the whole list in at once. All this adds up to make this process time consuming and inconsistent.\u003c/p\u003e","title":"Create Configuration Manager Antimalware Policies with PowerShell"},{"content":"I was recently deploying an application that required Windows Firewall rules to be created for an executable that ran from each user\u0026rsquo;s AppData folder. The way I accomplished this was to use a combination of PowerShell scripts and the Windows Task Scheduler.\nI created two PowerShell scripts for this solution. Create_Scheduled_Task.ps1 and Create_Firewall_Rules.ps1.\nThe Create_Scheduled_Task.ps1 script copies the Create_Firewall_Rules.ps1 script to a subfolder in C:\\Users\\Public and creates a scheduled task to run that script each time a user logs onto the computer. You will need to set the $appName, $scriptName, and $folderPath variables.\n#Set variables ========================================================= $appName = \u0026#34;Example App\u0026#34; $scriptName = \u0026#34;Create_Firewall_Rules.ps1\u0026#34; $folderPath = \u0026#34;$Env:public\\\u0026#34; #======================================================================= #Set paths $scriptFolder = \u0026#34;$folderPath$appname\u0026#34; $scriptFile = \u0026#34;$scriptFolder\\$scriptName\u0026#34; #Create the public app directory if it does not already exist if (!(Test-Path -PathType Container \u0026#34;$scriptFolder\u0026#34;)){ New-Item -ItemType Directory -Path \u0026#34;$scriptFolder\u0026#34; } #Copy the firewall rules script to the public app directory if it does not already exist if (!(Test-Path \u0026#34;$scriptFile\u0026#34;)){ Copy-Item \u0026#34;$PSScriptRoot\\$scriptName\u0026#34; -Destination \u0026#34;$scriptFolder\u0026#34; } #Create a scheduled task to run the firewall rules script at user logon $taskName = \u0026#34;Create $appName Firewall Rules\u0026#34; $task = Get-ScheduledTask | Where-Object -Property TaskName -eq $taskName | Select-Object -ExpandProperty TaskName -ErrorAction SilentlyContinue if (!($task)){ $action = New-ScheduledTaskAction -Execute \u0026#39;Powershell.exe\u0026#39; ` -Argument \u0026#34;-ExecutionPolicy Bypass -File $scriptFile\u0026#34; $trigger = New-ScheduledTaskTrigger -AtLogon $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit 00:05:00 Register-ScheduledTask -Action $action -Trigger $trigger -TaskName \u0026#34;$taskName\u0026#34; -User \u0026#34;System\u0026#34; -Settings $settings -Description \u0026#34;Creates firewall rules to allow $appName for all domain users.\u0026#34; } The Create_Firewall_Rules.ps1 script finds all domain user profiles on the system and creates firewall rules for each profile that does not already have rules created. You will need to set the $domain, $appName, and $appDataPath variables.\n#Set seach domain (Case Sensitive) $domain = \u0026#39;LAB\u0026#39; #Set application name $appName = \u0026#34;Example App\u0026#34; #Set the AppData path to the executable $appDataPath = \u0026#34;AppData\\Local\\Example App\\App.exe\u0026#34; #Find all user profiles matching the search domain $profiles = \u0026#39;Registry::HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\*\u0026#39; $accounts = Get-ItemProperty -path $profiles Foreach ($account in $accounts) { $objUser = New-Object System.Security.Principal.SecurityIdentifier($account.PSChildName) $objName = $objUser.Translate([System.Security.Principal.NTAccount]) $account.PSChildName = $objName.value } $users = $accounts | Where-Object {$_.PSChildName -like \u0026#34;*$domain*\u0026#34;} | Select-Object -ExpandProperty PSChildName $users = $users.Replace(\u0026#34;$domain\\\u0026#34;,\u0026#34;\u0026#34;) #Create a firewall exception for each user profile found Foreach ($user in $users) { if (!(Get-NetFirewallRule -DisplayName \u0026#34;$appname $user\u0026#34; -ErrorAction SilentlyContinue)){ New-NetFirewallRule -DisplayName \u0026#34;$appName $user\u0026#34; -Direction Inbound -Protocol TCP -LocalPort Any -RemoteAddress Any -Program \u0026#34;C:\\Users\\$user\\$appDataPath\u0026#34; -Action Allow } } I deployed this script to devices using an application in Configuration Manager. The application calls the Create_Scheduled_Task.ps1 script. I used another PowerShell script for the detection method.\n$taskName = \u0026#34;Create Example App Firewall Rules\u0026#34; $task = Get-ScheduledTask | Where-Object -Property TaskName -eq $taskName | Select-Object -ExpandProperty TaskName $file = Test-Path \u0026#34;C:\\Users\\Public\\Example App\\Create_Firewall_Rules.ps1\u0026#34; if ($task -and $file){ Write-Host \u0026#34;Installed\u0026#34; } ","permalink":"https://4c4806b4.configjon-blog.pages.dev/create-windows-firewall-rules-for-appdata-executables/","summary":"\u003cp\u003eI was recently deploying an application that required Windows Firewall rules to be created for an executable that ran from each user\u0026rsquo;s AppData folder. The way I accomplished this was to use a combination of PowerShell scripts and the Windows Task Scheduler.\u003c/p\u003e\n\u003cp\u003eI created two PowerShell scripts for this solution. \u003cstrong\u003eCreate_Scheduled_Task.ps1\u003c/strong\u003e and \u003cstrong\u003eCreate_Firewall_Rules.ps1\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eThe \u003cstrong\u003eCreate_Scheduled_Task.ps1\u003c/strong\u003e script copies the Create_Firewall_Rules.ps1 script to a subfolder in C:\\Users\\Public and creates a scheduled task to run that script each time a user logs onto the computer. You will need to set the \u003cstrong\u003e$appName\u003c/strong\u003e, \u003cstrong\u003e$scriptName\u003c/strong\u003e, and \u003cstrong\u003e$folderPath\u003c/strong\u003e variables.\u003c/p\u003e","title":"Create Windows Firewall Rules for AppData Executables"},{"content":"I encountered a scenario where I needed to add or remove domain users from the local administrators group on an individual computer basis. The Run Script feature in Configuration Manager worked great for this.\nI used an Add script and a Remove script. Both scripts have a $Member parameter that takes the name of a domain user or group and adds it to or removes it from the local administrator group on selected computers.\nAdd users or groups to local administrators.\n#Create the Member parameter param([String]$Member) #Add the member to the local administrators group Add-LocalGroupMember -Group \u0026#34;Administrators\u0026#34; -Member $Member #Check if the member was added successfully if (Get-LocalGroupMember -Group \u0026#34;Administrators\u0026#34; | Where-Object Name -Like \u0026#34;*$Member\u0026#34; -ErrorAction SilentlyContinue) { Write-Host \u0026#34;Successfully added $Member to the local Administrators group.\u0026#34; } else { Write-Host \u0026#34;Failed to add $Member to the local Administrators group.\u0026#34; } Remove users or groups from local administrators\n#Create the Member parameter param([String]$Member) #Remove the member from the local administrators group Remove-LocalGroupMember -Group \u0026#34;Administrators\u0026#34; -Member $Member #Check if the member was removed successfully if (Get-LocalGroupMember -Group \u0026#34;Administrators\u0026#34; | Where-Object Name -Like \u0026#34;*$Member\u0026#34; -ErrorAction SilentlyContinue) { Write-Host \u0026#34;Failed to remove $Member from the local Administrators group.\u0026#34; } else { Write-Host \u0026#34;Successfully removed $Member from the local Administrators group.\u0026#34; } ","permalink":"https://4c4806b4.configjon-blog.pages.dev/modify-local-administrators-membership/","summary":"\u003cp\u003eI encountered a scenario where I needed to add or remove domain users from the local administrators group on an individual computer basis. The \u003ca href=\"https://docs.microsoft.com/en-us/sccm/apps/deploy-use/create-deploy-scripts\"\u003e\u003cstrong\u003eRun Script\u003c/strong\u003e\u003c/a\u003e feature in Configuration Manager worked great for this.\u003c/p\u003e\n\u003cp\u003eI used an Add script and a Remove script. Both scripts have a $Member parameter that takes the name of a domain user or group and adds it to or removes it from the local administrator group on selected computers.\u003c/p\u003e","title":"Modify Local Administrators Membership"}]