About Pre-Actions and Post-Actions

You can add actions that you want to execute on the assets for the Windows deployment job type. You can run scripts or install software on assets before or after the patches are installed using actions. You can add actions to determine the software version, install the software before the latest patch can be applied, install a patch that is not supported out-of-the-box by Qualys Patch Management, remediate a vulnerability that might require a configuration change and so on. You can run a job to only execute one or more actions without adding any patches to the job.

You can add the following actions:

- Pre-Action: Action that you want to execute before the job starts.

- Post-Action: Action that you want to execute after the job is complete.

For detailed information, refer to the following topics:

- Types of Actions

- Examples

- Consider this!

Types of Actions

For pre and post actions, you can add the following types of actions:

- Install Software

- Run Script

Note: The Run Script action is supported for Linux deployment job as well.

- Change Registry Key

- Uninstall Software

Install Software: Allows you to create a pre-action or post-action to install a specific software or update software that Qualys Patch Management does not support out-of-the-box.

You must provide the following information:

Field

Description

Action Name

The name of the software that you want to install.

Note: You can choose to enable or disable the Bypass Execution Policy while adding the Install Software pre-action or post-action to a Windows deployment job.

When you click the Click here link, you are navigated to the Configuration > Setup tab and then you can enable or disable the Bypass Execution Policy. For more information, see Bypass Execution Policy.

URL

Enter the download URL from where the software installer will be downloaded.
If you have configured the Qualys Gateway Services, the agent will proxy through QGS.

File Checksum/Hash

The agent validates the integrity of the downloaded file by comparing it to the hash that you provide. You can use publicly available methods, such as certUtil, to generate SHA256 for a file.

Detection Script (optional)

The detection script is used to determine whether to install the software on a specific asset. The script checks the pre-conditions that must be met for the software to be installed or updated.

The script returns one of the following codes after execution:

- Success, to indicate that the software can be installed on the asset: 0
- Failure, abort the action and not install the software: Nonzero (except 10 and 11)

Install Script

This script performs the installation. The installer file downloaded by our agent is stored at the following location: %ProgramData%\Qualys\QualysAgent\PatchManagement\PatchDownloads\

You can check details in the log to understand why an action failed.

The script returns one of the following codes after execution:

- Success, the software was installed: 0
- Failure, the software failed to install: Nonzero (except 10 and 11)
- Reboot needed
    – Success with reboot: 10
    – Failure with reboot: 11

You can use the Write-Host command in the Powershell script to provide a custom message that is returned in case the action fails.

Note that if the script indicates that a reboot is required, the agent uses the job reboot preferences to enforce a reboot. Only one reboot is enforced for a patch job.

 

For example, install Notepad++.

Install Notepad++

Run Script: Allows you to use a custom script to execute actions.

Field

Description

Script Name

Enter the script name.

Note: You can choose to enable or disable the Bypass Execution Policy while adding the Run Script pre-action or post-action to a Windows deployment job.

When you click the Click here link, you are navigated to the Configuration > Setup tab and then you can enable or disable the Bypass Execution Policy. For more information, see Bypass Execution Policy.

Custom Script

You can enter a custom script that you want to execute on the assets.

- For Windows deployment job, you can only enter a Powershell script. The script returns one of the following codes after execution:
 a) Success, the custom script was executed successfully: 0
 b) Failure, the custom script failed to execute: Nonzero

You can use the Write-Host command in the Powershell script to provide a custom message that is returned in case the action fails.

- For Linux deployment job, you can only enter a Shell script.

 

For example, run a script for to check noop failure.

Run Script

Note: The error codes and failure descriptions are reported on the Job Progress screen. If a reboot return code is returned by the script, the agent will reboot based on the reboot policy defined for the job.

Change Registry Key: Allows you to add or update the registry key for an application before or after installation.

Field

Description

Key PATH ending with Key name

Enter the key path, including the key name.

You can change the following registry keys:

 - HKEY_CURRENT_USER

 - HKEY_USERS

 - HKEY_LOCAL_MACHINE

 - HKEY_CLASSES_ROOT

 - HKEY_CURRENT_CONFIG

Note the following important points:

 - You cannot use a forward slash (/).

 - The path should not end with a backslash (\).

 - The path must contain at least one directory after the root path.

Registry Type

Select the registry key type.

 - REG_BINARY

 - REG_DWORD

 - REG_EXPAND_SZ

 - REG_MULTI_SZ

 - REG_QWORD

 - REG_SZ

Note: Only numerical values are accepted for the REG_BINARY, REG_DWORD, and REG_QWORD registry key type.

Registry Value name

Based on the registry type selected, enter the registry value name.

Registry Value data

Based on the registry type selected, enter the registry value data.

Add New Key

Select one of the following options:

 - True: if you want to add the registry key in case it doesn't exist.

 - False: if you don't want to take any action in case the registry key doesn't exist.

 

For example, change the registry key for Internet Explorer.

Registry Key Example

Uninstall Software: Allows you to uninstall a specified software. Uninstall software is supported only on Windows with PM-enabled assets, and software with msi exec-based installers.

Field

Description

Action Name

Enter an action name.

Example: Uninstall Notepad++ 8.5

Uninstall Registry Key

Enter the registry key path containing the registry value name.

For example, for putty, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1E0D5689-40F1-4E46-ABBB-EAAC68B5CD89}.

Software Display Name

Enter the value data for the value name DisplayName under the registry key path.

The value data is the exact name of the software that you want to uninstall.

Software Display Version

Enter the exact value data for the value name Version under the Registry key path. The value data is the version of the software that you want to uninstall.

Note: If you don't specify a version, then any installed version of the software will be uninstalled.

 

Uninstall Software Version Match

The Uninstall Software Version Match field is shown only when you enter details in the Software Display Version field.

Select Equals operator. With this release, we are supporting the Equals operator only, which is the default operator.

Note: When the Equals operator is selected, the software is uninstalled only if the Software Display Version that you provided matches the value data for the value name Version under the registry key.

 

For example, uninstall Notepad ++ version 8.5.

Uninstall Software

Examples

The following examples help you understand the pre-actions and post-actions user scenarios.

Example 1: To detect if the Notepad++ version 8.1.2 can be installed

This sample script detects if the software is installed or not. If the code returned is 0, the software can be installed, and if the code returned is 1, installation is not required.

Return Code:

- Success: 0

- Failure: 1

***********************************************************************

# Sample pre-detection script for Qualys Patch Manager       *

#                                                            *

#     This sample script demonstrate detection of installed  *

#     software. It returns 0 if software can be installed    *

#     and returns 1 if installation is not required          *

#                                                            *

#                                                            *

#       Return Code                                          *

#                                                            *

#        0 - success                                         *

#        1 - failure                                         *

#*************************************************************

# required parameter

[string]$SoftwareName = "notepad++*"

[string]$SoftwareVersion = "8.1.2"

# Print OS info for asset information and troubleshooting

Write-Host "Gathering OS Information..."

$osInfo = Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, ServicePackMajorVersion, OSArchitecture, CSName

$properties = @{

    Caption                 = $osInfo.Caption

    Version                 = $osInfo.Version

    ServicePackMajorVersion = $osInfo.ServicePackMajorVersion

    OSArchitecture          = $osInfo.OSArchitecture

    HostName                = $osInfo.CSNAme

}

$obj = New-Object -TypeName PSObject -Property $properties

Write-Output $obj

Write-Host "Looking for package installation...`n"

# Check install key in both wow64 and normal path. Application can be either 32-bit or 64-bit.

$32bit = Get-ItemProperty HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*

$64bit = Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*

$programs = $32bit + $64bit

$packageFound = $false

foreach ($program in $programs) {

    $program = Write-Output $program | Where-Object Displayname -like $SoftwareName

    if ($null -ne $program.DisplayName) {

        $LastModified = (Get-Item $program.uninstallstring).lastwritetime

        $properties = @{

            ProgramName     = $program.DisplayName

            Publisher       = $program.Publisher

            Version         = $program.DisplayVersion

            UninstallString = $program.UninstallString

            LastModified    = $LastModified

        }

        $package = New-Object -TypeName PSObject -Property $properties

        Write-Output $package

        $packageFound = $true

        break;

    }

}

if ($packageFound -eq $false) {

    Write-Host "No installed package found"

    # Package needs to be isntalled

    exit 0

}

Write-Host "Checking installed software version..."

[System.Version] $installedVersion = $package.Version

[System.Version] $ExpectedVersion = $SoftwareVersion

if ($installedVersion -lt $ExpectedVersion) {

    Write-Host "Installed software is older then required version. Patch upgrade needed"

    exit 0

}

else {

    Write-Host "Installed software is up to date."

    exit 1

}>

Example 2: To install the Notepad++ version 8.1.2

This sample script demonstrates the installation of software. If the code returned is 0, the software is installed successfully, and if the code returned is 1, the installation fails.

Return Code:

- Success: 0

- Failure: 1

#*************************************************************

# Sample install script for Qualys Patch Manager             *

#     This sample script demonstrate installation of         *

#     software. It returns 0 if software is installed        *

#     successfully and returns 1 if installation fails.      *

#       Return Code                                          *

#        0 - success                                         *

#        1 - failure                                         *

#*************************************************************

[string]$PackageName = "npp.8.1.2.Installer.x64.exe"

[string]$InstallerLocation = $Env:ProgramData + "\Qualys\QualysAgent\PatchManagement\PatchDownloads\"

[string]$Arguments = "/S"

#set this 1 if reboot is required after package installation

[int]$RebootFlag = 1

function Get-QualysScriptReturn {

    param (

        [ValidateRange(0, 1)]

        [Int]

        $Success_Code,

        [ValidateRange(0, 1)]

        [Int]

        $RebootFlag

    )

    return $Success_Code + ($RebootFlag * 10)

}

function Start-Program {

    param (

        [ValidateNotNullOrEmpty()]

        [string]

        $ProgramFullPath,

        [Parameter(Mandatory = $false)]

        [string]

        $Arguments        

    )

    

    try {   

        $pinfo = New-Object System.Diagnostics.ProcessStartInfo

        $pinfo.FileName = $ProgramFullPath

        $pinfo.RedirectStandardError = $true

        $pinfo.RedirectStandardOutput = $true

        $pinfo.UseShellExecute = $false

    

        if ($null -ne $Arguments) {

            $pinfo.Arguments = $Arguments

        }    

    

        $pinfo.WorkingDirectory = Get-Location

        $p = New-Object System.Diagnostics.Process

        $p.StartInfo = $pinfo

        $p.Start() | Out-Null

        $p.WaitForExit()

        $stdout = $p.StandardOutput.ReadToEnd()

        $stderr = $p.StandardError.ReadToEnd()

    

        Write-Host "Process Stdout:`n $stdout"

        Write-Host "Process Stderr:`n $stderr"

        Write-Host "exit code: "$p.ExitCode

        return $p.ExitCode

    }

    catch {

        Write-Host -ForegroundColor DarkRed "Failed to execute program" $_.Exception.Message

        return 1

    }

}

Write-Host "Running install script to install -"$PackageName

Write-Host "Looking package installer..."

$InstallerFullPath = $InstallerLocation + $PackageName

if (Test-Path $InstallerFullPath) {

    Write-Host "Found installer at "$InstallerFullPath

}

else {

    Write-Host "Installer does not exist at "$InstallerFullPath

    exit 1;

}

Write-Host "Launching installer..."

$ReturnCode = Start-Program $InstallerFullPath $Arguments

if ($ReturnCode -eq 0) {

    Write-Host -ForegroundColor Green "Installation successfull..."

    exit Get-QualysScriptReturn 0 $RebootFlag;

}

else {

    Write-Host -ForegroundColor DarkRed "Installation failed. See output for more details."

    exit 1

}

Example 3: Custom script to create array of text files

This sample script checks whether a specific file (pc.txt) already exists in a particular folder; if not, it generates a list of all AD computers and saves it to a new file named pc.txt. It returns 0 if the file does not exist and the latest AD computer list is saved and returns 1 if the file already exists.

Return Code:

- Success: 0

- Failure: 1

#*************************************************************

#     Sample custom script for Qualys Patch Manager          *

#                                                            *

#     This sample script checks whether a specific file      *

#     (pc.txt) already exists in a particular folder;        *

#   if not, it generates a list of all AD computers and      *

#   saves it to a new file named pc.txt. It returns 0 if      *

#     file does not exists and latest AD computer list is    *

#   saved and returns 1 if file already exists.              *

#                                                            *

#       Return Code                                          *

#        0 - success                                         *

#        1 - failure                                         *

#*************************************************************

  #create array of text files

  $files=Get-ChildItem C:\data\*.txt | select -expand fullname

  #check if file exists inside the array

  $files -match "pc.txt"

  #if matching return “True” key then exit, if “False” then create a report

  if($files -eq 'False'){

    Get-ADComputer -Filter * | Export-Csv -Path C:\data\pc.txt

exit 0

  }

  else{

     exit 1

  }

Consider this!

- You can add Pre and Post actions for both, Windows, and Linux jobs.

- You can only add actions on assets that have Windows Cloud Agent version 4.6.1.6 or later.

- You can add a maximum of 5 pre-actions and 5 post-actions each for a job.

- If one action fails, the other actions continue to execute.

- The script size cannot exceed 20 KB, and the script length must not be more than 20480 characters, including spaces. The script beyond 20480 characters will be truncated.

- Success or failure of action execution does not impact the patches that are part of the job. Installation of all patches in a job is attempted.

- The run time for each action cannot exceed 2 minutes. After 2 minutes, if the action is not completed, the next action will be executed.

- Only one reboot request is honored for one job. If the pre-actions require a reboot, the reboot will happen only after the patches are installed. Post-actions might be executed after the reboot.

- If a post-action requires a reboot, the job is considered complete only after a reboot.

- We strongly recommend not to use a force reboot in the script. Since Patch Management only allows one reboot for one job; this can cause the job to go into a reboot loop.

- You can view details for each action using the Job Progress option after the job is executed. For more information, see Viewing Action Details.

- You can include the pre-actions and post-actions results in the job progress report. For more information, refer to Reviewing Job Results.

- For the Install Software action type, ensure that you provide the SHA256 based checksum of the download file.

- The scripts that you provide will be sent in the base64 encoded format.

- Only PowerShell scripts are supported, and we recommend that you use signed scripts. The PowerShell scripts are executed based on the execution policy that you define. Patch Management will support all execution policies; however, we recommend that you use AllSigned or RemoteSigned execution policy for security reasons. For more information, see About Execution Policies.

Note: To ensure scripts are executed on an asset, ensure that PowerShell scripts are not blocked on the device or, in case the execution policy only allows signed scripts to run, ensure that you provide a signed script and paste both the scripts and its signature in the script text box.

- You can use publicly available methods, such as certUtil, to generate SHA256 for a file. For example, you can run the following command in your command prompt:   certUtil -hashfile "<<filename>>" SHA256.

  Utility Example

- For the Install Software action type, ensure that the script that you add contains the code to deploy the binary.

- The detection script acts as a pre-check for the Install Software action type. The detection script is not mandatory, and if you don't enter the detection script, the install script action will be executed directly. If the detection script fails, the install software action will not be executed.

Note: Patch Management does not perform any validation and executes any script that is provided by you. We recommend that you exercise caution with the scripts that you run.


Managing Patch Jobs for Windows Assets