Task Sequence Password

Configuration manager has a built in function to allow the a password to be used to start a Task Sequence (TS) from PXE boot. But unfortunately there is no such function to stop a user from running the same TS from software centre

This obviously can be restricted by not deploying to Software centre, but what if you need the support guys to be able to rebuild/refresh the device from Software Centre without having to wait for the deployment to appear, and as we all know this can be a while with Config Manager.

I have created a simple password box to stop the TS being ran without knowing the simple password. This is not supposed to be a secure way, but just a way of restricting the inadvertent rebuilding of a machine.

I have seen a user rebuild thier machine without knowing what they where doing. His reply to the question “Why did you run that if you didn’t know what it would do” was “Well if you didn’t want me to do it why did you give me access to it”. OK fair point.. Least user access then…

In the TS I have added a step to create a TS variable.

The variable name is “BuildPW”. This variable will store the password entered into the simple input box. Next I create a package in MECM that contains a simple PowerShell script and the ServiceUI.exe.

ServiceUI.exe is a command-line tool that is included in the Microsoft Deployment Toolkit (MDT). It allows you to launch applications from within the system context, into the context of an active console user. This allows end users to interact with individual applications running as system.

Next in the TS update the TS Variable SMSTSErrorDialogTimeout to 1 second this will close the error box in 1 second if the password is incorrect.

Next Download the package created earlier to the machine

Next step is to run the InputBox.ps1

This is the command line used to run the inputbox.ps1

ServiceUI.exe -process:TSProgressUI.exe %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File InputBox.ps1 %BuildPW%

The input box will be shown and allow the input of the password. I have a loop in the script to check the password 3 times then if incorrect exit with an error. This will error the TS and not allow the rebuild of the machine. If the password is correct, confirm that the password was correct then carry on. I draw the input box and grab the return.

Finally I set the Variable SMSTSErrorDialogTimeout to 0 after the inputbox, this allows the error box on the TS to stay there and not time out. There have been occasions where an engineer has rebuilt a machine only for it to error close to the end and him not see the error box. Machine will reboot and end up on Ctrl+Alt+Del and they will not realise it has errored on something stupid.

Hope this helps someone to fix an issue or a problem

This is the PowerShell code.

# ==============================================================================================
# 
# NAME: InputBox.ps1
# 
# AUTHOR: Nick Drew
# DATE  : 01/11/2017
# 
# COMMENT: Checks the build password on a DLA TS run from Software Centre
#
#===============================================================================================
$Global:BuildPW = $args[0]
$Global:BuildPW = "O5dbu1ld"
$Global:ReturnValue = ""
$Global:CancelBuild = $false
$Global:ExitError
$Shell = new-object -comobject wscript.shell -ErrorAction Stop
$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment

$logPath = "C:\Logs"
$LogName = "AppInstall.log"
$Global:sFullPath = $logPath + "\" + $LogName

########### Starting
Add-Content -Path $sFullPath -Value "###########################################################"
Add-Content -Path $sFullPath -Value "[INFO] Started processing at [$([DateTime]::Now)]."
Add-Content -Path $sFullPath -Value "###########################################################"
Add-Content -Path $sFullPath -Value "[INFO] Task Sequence started from Software Centre - Checking the user has password"

#Exit Function
Function ExitVar($ExitError) {

    ########### Finishing
    Add-Content -Path $sFullPath -Value "###########################################################"
    Add-Content -Path $sFullPath -Value "[INFO] Stopped processing at [$([DateTime]::Now)]."
    Add-Content -Path $sFullPath -Value "###########################################################"
    Add-Content -Path $sFullPath -Value ""
    Add-Content -Path $sFullPath -Value "[INFO] Running Script version [$scriptVersion]."
    Add-Content -Path $sFullPath -Value ""
    Add-Content -Path $sFullPath -Value "###########################################################"
    Add-Content -Path $sFullPath -Value ""

    if ($Global:ExitError -gt 0) {Add-Content -Path $sFullPath -Value "[INFO] Exit Script with $Global:ExitError"
                                $tsenv.value("GatherLogs") = $true
                                $LASTEXITCODE = $Global:ExitError    
                                Exit $LASTEXITCODE}
    Else 
                {Add-Content -Path $sFullPath -Value "[INFO] Exit Script with $Global:ExitError"
                $LASTEXITCODE = $Global:ExitError 
                    Exit $LASTEXITCODE}
    }

########### Building the Form
function PasswordBox {

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 
$objForm = New-Object System.Windows.Forms.Form 
$objForm.Text = "Password Check"
$objForm.Size = New-Object System.Drawing.Size(300,200) 
$objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") 
    {$x=$objTextBox.Text;$objForm.Close()}})
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape") 
    {$objForm.Close()}})
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Add_Click({$x=$MaskedTextBox.Text;$objForm.Close()})
$objForm.Controls.Add($OKButton)
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$Global:CancelBuild=$true;$objForm.Close()})
$objForm.Controls.Add($CancelButton)
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20) 
$objLabel.Size = New-Object System.Drawing.Size(280,20) 
$objLabel.Text = "Please enter the information in the space below:"
$objForm.Controls.Add($objLabel) 
$MaskedTextBox = New-Object System.Windows.Forms.MaskedTextBox
$MaskedTextBox.PasswordChar = '*'
$MaskedTextBox.Location = New-Object System.Drawing.Size(10,40) 
$MaskedTextBox.Size = New-Object System.Drawing.Size(260,20) 
$objForm.Controls.Add($MaskedTextBox) 
$objForm.Topmost = $True
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()

If ($Global:CancelBuild -eq $true) {$Global:msgBody = "CANCEL Clicked"  +"`n `n"+ "The build will not continue. No Changes were made"
                                    $Global:msgTitle = "Build Password"
                                    $Shell.popup("$msgBody",120,"$msgTitle",0 + 16 + 4096)
                                    Add-Content -Path $sFullPath -Value "[INFO] Cancel Clicked - Build will not continue"
                                    $Global:ExitError = 2
                                    ExitVar($Global:ExitError)}

#Checking the responce 
$Global:ReternValue = $MaskedTextBox.Text
}

$Trys = 4

While ($Trys -gt 0) {
    #Exit If Cancel Clicked

    PasswordBox
    If ($Global:ReternValue -eq $BuildPW) {
        $Global:msgBody = "Password Correct - Build will continue"
        $Global:msgTitle = "Build Password"
        Add-Content -Path $sFullPath -Value "[INFO] Correct Build password entered - Build will continue"
        $Shell.popup("$msgBody",120,"$msgTitle", 0 + 64 + 4096)  
        $Global:ExitError = 0                        
        ExitVar($Global:ExitError)}
    else { 
        $Trys = $Trys - 1
        If ($trys -eq 0) {$Global:msgBody = "Incorrect password entered - You have $trys more attempts"  +"`n `n"+ "The build will not continue. No Changes were made"
                            $Global:msgTitle = "Build Password"
                            $Shell.popup("$msgBody",120,"$msgTitle",0 + 16 + 4096)
                            Add-Content -Path $sFullPath -Value "[INFO] Incorrect Build password entered - $trys attempts left. The build will not continue. No Changes were made"
                            $Global:ExitError = 2
                            ExitVar($Global:ExitError)}
        Add-Content -Path $sFullPath -Value "[INFO] Incorrect Build password entered - $trys attempts left."
        $Global:msgBody = "Incorrect password entered - You have $trys more attempts"
        $Global:msgTitle = "Build Password"
        $Shell.popup("$msgBody",120,"$msgTitle",0 + 48 + 4096)
    }
    
}